@@ -37,14 +37,16 @@ chain --replace %s
3737
3838// ImageFactoryClient represents an image factory client which ensures a schematic exists on image factory, and returns the PXE URL to it.
3939type ImageFactoryClient interface {
40- SchematicIPXEURL (ctx context.Context , talosVersion , arch string , extensions , extraKernelArgs []string ) (string , error )
40+ EnsureSchematic (ctx context.Context , extensions , extraKernelArgs []string ) (string , error )
41+ GetIPXEURL (schematicID , talosVersion , arch string ) (string , error )
4142}
4243
4344// HandlerOptions represents the options for the iPXE handler.
4445type HandlerOptions struct {
4546 APIAdvertiseAddress string
4647 TalosVersion string
4748 ExtraKernelArgs string
49+ SchematicID string
4850 Extensions []string
4951 APIPort int
5052}
@@ -93,9 +95,12 @@ func (handler *Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
9395
9496 // TODO: later, we can do per-machine kernel args and system extensions here
9597
96- kernelArgs := slices .Concat (handler .kernelArgs , handler .consoleKernelArgs (arch ))
98+ consoleKernelArgs := handler .consoleKernelArgs (arch )
99+ kernelArgs := slices .Concat (handler .kernelArgs , consoleKernelArgs )
97100
98- body , statusCode , err := handler .bootViaFactoryIPXEScript (ctx , handler .options .TalosVersion , arch , handler .options .Extensions , kernelArgs )
101+ logger .Debug ("injected console kernel args to the iPXE request" , zap .Strings ("console_kernel_args" , consoleKernelArgs ))
102+
103+ body , statusCode , err := handler .bootViaFactoryIPXEScript (ctx , arch , kernelArgs )
99104 if err != nil {
100105 handler .logger .Error ("failed to get iPXE script" , zap .Error (err ))
101106
@@ -123,9 +128,18 @@ func (handler *Handler) handleInitScript(w http.ResponseWriter) {
123128 }
124129}
125130
126- func (handler * Handler ) bootViaFactoryIPXEScript (ctx context.Context , talosVersion , arch string , extensions , kernelArgs []string ) (body string , statusCode int , err error ) {
127- ipxeURL , err := handler .imageFactoryClient .SchematicIPXEURL (ctx , talosVersion , arch , extensions , kernelArgs )
128- if err != nil {
131+ func (handler * Handler ) bootViaFactoryIPXEScript (ctx context.Context , arch string , kernelArgs []string ) (body string , statusCode int , err error ) {
132+ schematicID := handler .options .SchematicID
133+
134+ if schematicID == "" {
135+ if schematicID , err = handler .imageFactoryClient .EnsureSchematic (ctx , handler .options .Extensions , kernelArgs ); err != nil {
136+ return "" , http .StatusInternalServerError , fmt .Errorf ("failed to get schematic IPXE URL: %w" , err )
137+ }
138+ }
139+
140+ var ipxeURL string
141+
142+ if ipxeURL , err = handler .imageFactoryClient .GetIPXEURL (schematicID , handler .options .TalosVersion , arch ); err != nil {
129143 return "" , http .StatusInternalServerError , fmt .Errorf ("failed to get schematic IPXE URL: %w" , err )
130144 }
131145
@@ -145,6 +159,21 @@ func (handler *Handler) consoleKernelArgs(arch string) []string {
145159
146160// NewHandler creates a new iPXE server.
147161func NewHandler (ctx context.Context , configServerEnabled bool , imageFactoryClient ImageFactoryClient , options HandlerOptions , logger * zap.Logger ) (* Handler , error ) {
162+ apiHostPort := net .JoinHostPort (options .APIAdvertiseAddress , strconv .Itoa (options .APIPort ))
163+ talosConfigURL := fmt .Sprintf ("http://%s/config?u=${uuid}" , apiHostPort )
164+ talosConfigKernelArg := fmt .Sprintf ("%s=%s" , constants .KernelParamConfig , talosConfigURL )
165+
166+ if options .SchematicID != "" {
167+ if len (options .Extensions ) > 0 || len (options .ExtraKernelArgs ) > 0 {
168+ return nil , fmt .Errorf ("schematicID cannot be used with extensions or extraKernelArgs" )
169+ }
170+
171+ if configServerEnabled {
172+ logger .Sugar ().Warnf ("schematic ID is set explicitly to %q and the config server is enabled (e.g., Omni connection is requested), " +
173+ "note that if this schematic does not contain the kernel arg %q, the machines will not be able to connect to the config server" , options .SchematicID , talosConfigKernelArg )
174+ }
175+ }
176+
148177 initScript , err := buildInitScript (options .APIAdvertiseAddress , options .APIPort )
149178 if err != nil {
150179 return nil , fmt .Errorf ("failed to build init script: %w" , err )
@@ -161,10 +190,9 @@ func NewHandler(ctx context.Context, configServerEnabled bool, imageFactoryClien
161190 kernelArgs := strings .Fields (options .ExtraKernelArgs )
162191
163192 if configServerEnabled {
164- apiHostPort := net .JoinHostPort (options .APIAdvertiseAddress , strconv .Itoa (options .APIPort ))
165- talosConfigURL := fmt .Sprintf ("http://%s/config?u=${uuid}" , apiHostPort )
193+ kernelArgs = append (kernelArgs , talosConfigKernelArg )
166194
167- kernelArgs = append ( kernelArgs , fmt . Sprintf ( "%s=%s " , constants . KernelParamConfig , talosConfigURL ))
195+ logger . Debug ( "injected talos config kernel arg to the iPXE requests" , zap . String ( "arg " , talosConfigKernelArg ))
168196 }
169197
170198 return & Handler {
0 commit comments