From b4230852744a9014665f1bb5a6d36200a6d3e27d Mon Sep 17 00:00:00 2001 From: Utku Ozdemir Date: Thu, 12 Dec 2024 00:55:16 +0100 Subject: [PATCH] feat: set machine labels directly on `InfraMachineStatus` We do not need to set initial machine labels via META values: as the provider has access to Omni, it can write these labels directly to the resources in creates on Omni side. Signed-off-by: Utku Ozdemir --- hack/test/integration.sh | 1 + .../controllers/infra_machine_status.go | 11 +++- internal/provider/imagefactory/client.go | 50 +------------------ internal/provider/provider.go | 31 +++++++++++- 4 files changed, 41 insertions(+), 52 deletions(-) diff --git a/hack/test/integration.sh b/hack/test/integration.sh index 1bfe1d9..60a4bb2 100755 --- a/hack/test/integration.sh +++ b/hack/test/integration.sh @@ -183,6 +183,7 @@ docker run -d --network host \ --api-power-mgmt-state-dir=/api-power-mgmt-state \ --ipmi-pxe-boot-mode=bios \ --min-reboot-interval=1m \ + --machine-labels=a=b,c \ --debug docker logs -f provider & diff --git a/internal/provider/controllers/infra_machine_status.go b/internal/provider/controllers/infra_machine_status.go index 8b753c9..7e7a2d8 100644 --- a/internal/provider/controllers/infra_machine_status.go +++ b/internal/provider/controllers/infra_machine_status.go @@ -54,8 +54,8 @@ type APIPowerManager interface { type InfraMachineController = qtransform.QController[*infra.Machine, *infra.MachineStatus] // NewInfraMachineController initializes InfraMachineController. -func NewInfraMachineController(agentService AgentService, apiPowerManager APIPowerManager, state state.State, pxeBootMode pxe.BootMode, - requeueInterval, minRebootInterval time.Duration, +func NewInfraMachineController(agentService AgentService, apiPowerManager APIPowerManager, state state.State, + pxeBootMode pxe.BootMode, requeueInterval, minRebootInterval time.Duration, machineLabels map[string]string, ) *InfraMachineController { helper := &infraMachineControllerHelper{ agentService: agentService, @@ -64,6 +64,7 @@ func NewInfraMachineController(agentService AgentService, apiPowerManager APIPow pxeBootMode: pxeBootMode, requeueInterval: requeueInterval, minRebootInterval: minRebootInterval, + machineLabels: machineLabels, } return qtransform.NewQController( @@ -96,6 +97,7 @@ type infraMachineControllerHelper struct { agentService AgentService apiPowerManager APIPowerManager state state.State + machineLabels map[string]string pxeBootMode pxe.BootMode requeueInterval time.Duration minRebootInterval time.Duration @@ -256,6 +258,11 @@ func (h *infraMachineControllerHelper) removeInternalStatus(ctx context.Context, func (h *infraMachineControllerHelper) populateInfraMachineStatus(status *baremetal.MachineStatus, infraMachineStatus *infra.MachineStatus) error { infraMachineStatus.TypedSpec().Value.ReadyToUse = false + // set the labels + for k, v := range h.machineLabels { + infraMachineStatus.Metadata().Labels().Set(k, v) + } + // update power state switch status.TypedSpec().Value.PowerState { case specs.PowerState_POWER_STATE_ON: diff --git a/internal/provider/imagefactory/client.go b/internal/provider/imagefactory/client.go index da37cce..485ab39 100644 --- a/internal/provider/imagefactory/client.go +++ b/internal/provider/imagefactory/client.go @@ -7,13 +7,10 @@ package imagefactory import ( "context" "fmt" - "strings" "time" "github.com/siderolabs/image-factory/pkg/client" "github.com/siderolabs/image-factory/pkg/schematic" - "github.com/siderolabs/omni/client/pkg/meta" - "gopkg.in/yaml.v3" ) var agentModeExtensions = []string{ @@ -36,16 +33,10 @@ type Client struct { factoryClient *client.Client pxeBaseURL string agentModeTalosVersion string - machineLabelsMeta string } // NewClient creates a new image factory client. -func NewClient(baseURL, pxeBaseURL, agentModeTalosVersion string, machineLabels []string) (*Client, error) { - labelsMeta, err := parseLabels(machineLabels) - if err != nil { - return nil, err - } - +func NewClient(baseURL, pxeBaseURL, agentModeTalosVersion string) (*Client, error) { factoryClient, err := client.New(baseURL) if err != nil { return nil, err @@ -54,9 +45,7 @@ func NewClient(baseURL, pxeBaseURL, agentModeTalosVersion string, machineLabels return &Client{ pxeBaseURL: pxeBaseURL, agentModeTalosVersion: agentModeTalosVersion, - machineLabelsMeta: labelsMeta, - - factoryClient: factoryClient, + factoryClient: factoryClient, }, nil } @@ -66,13 +55,6 @@ func NewClient(baseURL, pxeBaseURL, agentModeTalosVersion string, machineLabels func (c *Client) SchematicIPXEURL(ctx context.Context, agentMode bool, talosVersion, arch string, extensions, extraKernelArgs []string) (string, error) { var metaValues []schematic.MetaValue - if c.machineLabelsMeta != "" { - metaValues = append(metaValues, schematic.MetaValue{ - Key: meta.LabelsMeta, - Value: c.machineLabelsMeta, - }) - } - if !agentMode && talosVersion == "" { return "", fmt.Errorf("talosVersion is required when not booting into agent mode") } @@ -105,31 +87,3 @@ func (c *Client) SchematicIPXEURL(ctx context.Context, agentMode bool, talosVers return ipxeURL, err } - -func parseLabels(machineLabels []string) (string, error) { - labels := map[string]string{} - - for _, l := range machineLabels { - parts := strings.Split(l, "=") - if len(parts) > 2 { - return "", fmt.Errorf("malformed label %s", l) - } - - value := "" - - if len(parts) > 1 { - value = parts[1] - } - - labels[parts[0]] = value - } - - data, err := yaml.Marshal(meta.ImageLabels{ - Labels: labels, - }) - if err != nil { - return "", err - } - - return string(data), nil -} diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 29e452b..6dd4098 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -10,6 +10,7 @@ import ( _ "embed" "fmt" "os" + "strings" "time" "github.com/cosi-project/runtime/pkg/controller/runtime" @@ -110,7 +111,7 @@ func (p *Provider) Run(ctx context.Context) error { return fmt.Errorf("failed to create/update provider status: %w", err) } - imageFactoryClient, err := imagefactory.NewClient(p.options.ImageFactoryBaseURL, p.options.ImageFactoryPXEBaseURL, p.options.AgentModeTalosVersion, p.options.MachineLabels) + imageFactoryClient, err := imagefactory.NewClient(p.options.ImageFactoryBaseURL, p.options.ImageFactoryPXEBaseURL, p.options.AgentModeTalosVersion) if err != nil { return fmt.Errorf("failed to create image factory client: %w", err) } @@ -131,6 +132,11 @@ func (p *Provider) Run(ctx context.Context) error { return fmt.Errorf("failed to create config handler: %w", err) } + parsedMachineLabels, err := p.parseLabels() + if err != nil { + return fmt.Errorf("failed to parse machine labels: %w", err) + } + srvr := server.New(ctx, p.options.APIListenAddress, p.options.APIPort, p.options.UseLocalBootAssets, configHandler, ipxeHandler, p.logger.With(zap.String("component", "server"))) agentService := agent.NewService(srvr, omniState, p.options.WipeWithZeroes, p.logger.With(zap.String("component", "agent_service"))) //nolint:contextcheck // false positive machineStatusPoller := machinestatus.NewPoller(agentService, omniState, p.logger.With(zap.String("component", "machine_status_poller"))) @@ -141,7 +147,7 @@ func (p *Provider) Run(ctx context.Context) error { // todo: enable if we re-enable reverse tunnel on Omni: https://github.com/siderolabs/omni/pull/746 // reverseTunnel := tunnel.New(omniState, omniAPIClient, p.logger.With(zap.String("component", "reverse_tunnel"))) - infraMachineController := controllers.NewInfraMachineController(agentService, apiPowerManager, omniState, pxeBootMode, 1*time.Minute, p.options.MinRebootInterval) + infraMachineController := controllers.NewInfraMachineController(agentService, apiPowerManager, omniState, pxeBootMode, 1*time.Minute, p.options.MinRebootInterval, parsedMachineLabels) if err = cosiRuntime.RegisterQController(infraMachineController); err != nil { return fmt.Errorf("failed to register controller: %w", err) @@ -275,3 +281,24 @@ func (p *Provider) clearState(ctx context.Context, st state.State) error { return errs } + +func (p *Provider) parseLabels() (map[string]string, error) { + labels := make(map[string]string, len(p.options.MachineLabels)) + + for _, l := range p.options.MachineLabels { + parts := strings.Split(l, "=") + if len(parts) > 2 { + return nil, fmt.Errorf("malformed label %s", l) + } + + value := "" + + if len(parts) > 1 { + value = parts[1] + } + + labels[parts[0]] = value + } + + return labels, nil +}