diff --git a/api/v1alpha1/operatorconfig_types.go b/api/v1alpha1/operatorconfig_types.go index 26142540..9bf1131b 100644 --- a/api/v1alpha1/operatorconfig_types.go +++ b/api/v1alpha1/operatorconfig_types.go @@ -59,16 +59,6 @@ type JumpstarterTargetMapping struct { // Example: "j storage flash ${IMAGE}" // +optional FlashCmd string `json:"flashCmd,omitempty"` - - // Architecture is the default CPU architecture for builds targeting this device - // Example: "arm64" - // +optional - Architecture string `json:"architecture,omitempty"` - - // ExtraArgs are default extra arguments passed to AIB for builds targeting this device - // Example: ["--separate-partitions"] - // +optional - ExtraArgs []string `json:"extraArgs,omitempty"` } // DefaultJumpstarterImage is the default container image for Jumpstarter CLI operations diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 168987d3..a1ab4ee9 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -692,7 +692,7 @@ func (in *JumpstarterConfig) DeepCopyInto(out *JumpstarterConfig) { in, out := &in.TargetMappings, &out.TargetMappings *out = make(map[string]JumpstarterTargetMapping, len(*in)) for key, val := range *in { - (*out)[key] = *val.DeepCopy() + (*out)[key] = val } } } @@ -710,11 +710,6 @@ func (in *JumpstarterConfig) DeepCopy() *JumpstarterConfig { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *JumpstarterTargetMapping) DeepCopyInto(out *JumpstarterTargetMapping) { *out = *in - if in.ExtraArgs != nil { - in, out := &in.ExtraArgs, &out.ExtraArgs - *out = make([]string, len(*in)) - copy(*out, *in) - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JumpstarterTargetMapping. diff --git a/cmd/caib/main.go b/cmd/caib/main.go index 73249a56..a3ceb9d2 100644 --- a/cmd/caib/main.go +++ b/cmd/caib/main.go @@ -813,26 +813,26 @@ func fetchTargetDefaults(ctx context.Context, api *buildapiclient.Client, target } // applyTargetDefaults applies architecture and extra-args defaults from the operator config -// target mapping. CLI flags override mapping defaults when explicitly set. +// target defaults (ConfigMap). CLI flags override defaults when explicitly set. func applyTargetDefaults(cmd *cobra.Command, config *buildapitypes.OperatorConfigResponse, req *buildapitypes.BuildRequest) { - if config == nil || len(config.JumpstarterTargets) == 0 { + if config == nil || len(config.TargetDefaults) == 0 { return } - defaults, exists := config.JumpstarterTargets[string(req.Target)] + defaults, exists := config.TargetDefaults[string(req.Target)] if !exists { return } if defaults.Architecture != "" && !cmd.Flags().Changed("arch") { req.Architecture = buildapitypes.Architecture(defaults.Architecture) - fmt.Printf("Using architecture %q from target mapping for %q\n", defaults.Architecture, req.Target) + fmt.Printf("Using architecture %q from target defaults for %q\n", defaults.Architecture, req.Target) } if len(defaults.ExtraArgs) > 0 { - // Mapping args come first, user args appended + // Default args come first, user args appended req.AIBExtraArgs = append(defaults.ExtraArgs, req.AIBExtraArgs...) - fmt.Printf("Prepending extra args %v from target mapping for %q\n", defaults.ExtraArgs, req.Target) + fmt.Printf("Prepending extra args %v from target defaults for %q\n", defaults.ExtraArgs, req.Target) } } diff --git a/cmd/caib/main_test.go b/cmd/caib/main_test.go index 6f40e447..9f4f17ae 100644 --- a/cmd/caib/main_test.go +++ b/cmd/caib/main_test.go @@ -36,7 +36,7 @@ func TestApplyTargetDefaults_NilConfig(t *testing.T) { func TestApplyTargetDefaults_EmptyTargets(t *testing.T) { cmd := newCmdWithArchFlag(archAMD64, false) config := &buildapitypes.OperatorConfigResponse{ - JumpstarterTargets: map[string]buildapitypes.TargetDefaults{}, + TargetDefaults: map[string]buildapitypes.TargetDefaults{}, } req := &buildapitypes.BuildRequest{ Target: "ebbr", @@ -53,8 +53,8 @@ func TestApplyTargetDefaults_EmptyTargets(t *testing.T) { func TestApplyTargetDefaults_NoMatchingTarget(t *testing.T) { cmd := newCmdWithArchFlag(archAMD64, false) config := &buildapitypes.OperatorConfigResponse{ - JumpstarterTargets: map[string]buildapitypes.TargetDefaults{ - "qemu": {Selector: "board-type=qemu"}, + TargetDefaults: map[string]buildapitypes.TargetDefaults{ + "qemu": {}, }, } req := &buildapitypes.BuildRequest{ @@ -72,9 +72,8 @@ func TestApplyTargetDefaults_NoMatchingTarget(t *testing.T) { func TestApplyTargetDefaults_AppliesArchFromMapping(t *testing.T) { cmd := newCmdWithArchFlag(archAMD64, false) config := &buildapitypes.OperatorConfigResponse{ - JumpstarterTargets: map[string]buildapitypes.TargetDefaults{ + TargetDefaults: map[string]buildapitypes.TargetDefaults{ "ebbr": { - Selector: "board-type=ebbr", Architecture: archARM64, }, }, @@ -94,9 +93,8 @@ func TestApplyTargetDefaults_AppliesArchFromMapping(t *testing.T) { func TestApplyTargetDefaults_ExplicitArchOverridesMapping(t *testing.T) { cmd := newCmdWithArchFlag(archAMD64, true) // user explicitly set --arch amd64 config := &buildapitypes.OperatorConfigResponse{ - JumpstarterTargets: map[string]buildapitypes.TargetDefaults{ + TargetDefaults: map[string]buildapitypes.TargetDefaults{ "ebbr": { - Selector: "board-type=ebbr", Architecture: archARM64, }, }, @@ -116,9 +114,8 @@ func TestApplyTargetDefaults_ExplicitArchOverridesMapping(t *testing.T) { func TestApplyTargetDefaults_ExplicitArchArm64OverridesMapping(t *testing.T) { cmd := newCmdWithArchFlag(archARM64, true) // user explicitly set --arch arm64 config := &buildapitypes.OperatorConfigResponse{ - JumpstarterTargets: map[string]buildapitypes.TargetDefaults{ + TargetDefaults: map[string]buildapitypes.TargetDefaults{ "ebbr": { - Selector: "board-type=ebbr", Architecture: archAMD64, // mapping says amd64 }, }, @@ -138,9 +135,8 @@ func TestApplyTargetDefaults_ExplicitArchArm64OverridesMapping(t *testing.T) { func TestApplyTargetDefaults_PrependsExtraArgs(t *testing.T) { cmd := newCmdWithArchFlag(archAMD64, false) config := &buildapitypes.OperatorConfigResponse{ - JumpstarterTargets: map[string]buildapitypes.TargetDefaults{ + TargetDefaults: map[string]buildapitypes.TargetDefaults{ "ride": { - Selector: "board-type=ride", ExtraArgs: []string{"--separate-partitions"}, }, }, @@ -167,9 +163,8 @@ func TestApplyTargetDefaults_PrependsExtraArgs(t *testing.T) { func TestApplyTargetDefaults_ExtraArgsWithNoUserArgs(t *testing.T) { cmd := newCmdWithArchFlag(archAMD64, false) config := &buildapitypes.OperatorConfigResponse{ - JumpstarterTargets: map[string]buildapitypes.TargetDefaults{ + TargetDefaults: map[string]buildapitypes.TargetDefaults{ "ride": { - Selector: "board-type=ride", ExtraArgs: []string{"--separate-partitions", "--verbose"}, }, }, @@ -195,9 +190,8 @@ func TestApplyTargetDefaults_ExtraArgsWithNoUserArgs(t *testing.T) { func TestApplyTargetDefaults_BothArchAndExtraArgs(t *testing.T) { cmd := newCmdWithArchFlag(archAMD64, false) config := &buildapitypes.OperatorConfigResponse{ - JumpstarterTargets: map[string]buildapitypes.TargetDefaults{ + TargetDefaults: map[string]buildapitypes.TargetDefaults{ "ride": { - Selector: "board-type=ride", Architecture: archARM64, ExtraArgs: []string{"--separate-partitions"}, }, @@ -228,9 +222,8 @@ func TestApplyTargetDefaults_BothArchAndExtraArgs(t *testing.T) { func TestApplyTargetDefaults_MappingWithEmptyArchDoesNotOverride(t *testing.T) { cmd := newCmdWithArchFlag(archAMD64, false) config := &buildapitypes.OperatorConfigResponse{ - JumpstarterTargets: map[string]buildapitypes.TargetDefaults{ + TargetDefaults: map[string]buildapitypes.TargetDefaults{ "qemu": { - Selector: "board-type=qemu", // Architecture intentionally empty }, }, diff --git a/config/crd/bases/automotive.sdv.cloud.redhat.com_operatorconfigs.yaml b/config/crd/bases/automotive.sdv.cloud.redhat.com_operatorconfigs.yaml index b8a8a05a..1e74b0d7 100644 --- a/config/crd/bases/automotive.sdv.cloud.redhat.com_operatorconfigs.yaml +++ b/config/crd/bases/automotive.sdv.cloud.redhat.com_operatorconfigs.yaml @@ -442,18 +442,6 @@ spec: description: JumpstarterTargetMapping defines the Jumpstarter configuration for a specific build target properties: - architecture: - description: |- - Architecture is the default CPU architecture for builds targeting this device - Example: "arm64" - type: string - extraArgs: - description: |- - ExtraArgs are default extra arguments passed to AIB for builds targeting this device - Example: ["--separate-partitions"] - items: - type: string - type: array flashCmd: description: |- FlashCmd is the command template for flashing the device diff --git a/internal/buildapi/server.go b/internal/buildapi/server.go index 96347af5..926e0f52 100644 --- a/internal/buildapi/server.go +++ b/internal/buildapi/server.go @@ -22,6 +22,7 @@ import ( "github.com/gin-gonic/gin" "github.com/go-logr/logr" "github.com/google/uuid" + "gopkg.in/yaml.v3" corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -82,6 +83,44 @@ var loadOperatorConfigFn = func( return operatorConfig, nil } +var loadTargetDefaultsFn = func( + ctx context.Context, + k8sClient client.Client, + namespace string, +) (map[string]TargetDefaults, error) { + cm := &corev1.ConfigMap{} + if err := k8sClient.Get(ctx, types.NamespacedName{ + Namespace: namespace, + Name: "aib-target-defaults", + }, cm); err != nil { + return nil, err + } + + data, ok := cm.Data["target-defaults.yaml"] + if !ok { + return nil, nil + } + + var parsed struct { + Targets map[string]struct { + Architecture string `yaml:"architecture"` + ExtraArgs []string `yaml:"extraArgs"` + } `yaml:"targets"` + } + if err := yaml.Unmarshal([]byte(data), &parsed); err != nil { + return nil, fmt.Errorf("failed to parse target-defaults.yaml: %w", err) + } + + result := make(map[string]TargetDefaults, len(parsed.Targets)) + for name, t := range parsed.Targets { + result[name] = TargetDefaults{ + Architecture: t.Architecture, + ExtraArgs: t.ExtraArgs, + } + } + return result, nil +} + // defaultInternalRegistryURL is an alias for the shared constant. const defaultInternalRegistryURL = tasks.DefaultInternalRegistryURL @@ -2489,20 +2528,30 @@ func (a *APIServer) handleGetOperatorConfig(c *gin.Context) { return } - // Build the response with Jumpstarter target mappings + // Build the response with Jumpstarter target mappings (flash-specific, from CRD) response := OperatorConfigResponse{} if operatorConfig.Spec.Jumpstarter != nil && len(operatorConfig.Spec.Jumpstarter.TargetMappings) > 0 { - response.JumpstarterTargets = make(map[string]TargetDefaults) + response.JumpstarterTargets = make(map[string]JumpstarterTarget) for target, mapping := range operatorConfig.Spec.Jumpstarter.TargetMappings { - response.JumpstarterTargets[target] = TargetDefaults{ - Selector: mapping.Selector, - Architecture: mapping.Architecture, - ExtraArgs: mapping.ExtraArgs, + response.JumpstarterTargets[target] = JumpstarterTarget{ + Selector: mapping.Selector, + FlashCmd: mapping.FlashCmd, } } } + // Load build defaults from target-defaults ConfigMap + targetDefaults, err := loadTargetDefaultsFn(ctx, k8sClient, namespace) + if err != nil { + if !k8serrors.IsNotFound(err) { + a.log.Error(err, "failed to load target defaults ConfigMap", "reqID", reqID, "namespace", namespace) + } + // Non-fatal: continue without target defaults + } else if len(targetDefaults) > 0 { + response.TargetDefaults = targetDefaults + } + c.JSON(http.StatusOK, response) } diff --git a/internal/buildapi/server_test.go b/internal/buildapi/server_test.go index 4322a479..26d243ca 100644 --- a/internal/buildapi/server_test.go +++ b/internal/buildapi/server_test.go @@ -105,6 +105,7 @@ var _ = Describe("APIServer", func() { var ( originalGetClientFromRequestFn func(*gin.Context) (ctrlclient.Client, error) originalLoadOperatorConfigFn func(context.Context, ctrlclient.Client, string) (*automotivev1alpha1.OperatorConfig, error) + originalLoadTargetDefaultsFn func(context.Context, ctrlclient.Client, string) (map[string]TargetDefaults, error) originalNamespace string hasOriginalNamespace bool ) @@ -112,6 +113,7 @@ var _ = Describe("APIServer", func() { BeforeEach(func() { originalGetClientFromRequestFn = getClientFromRequestFn originalLoadOperatorConfigFn = loadOperatorConfigFn + originalLoadTargetDefaultsFn = loadTargetDefaultsFn originalNamespace, hasOriginalNamespace = os.LookupEnv("BUILD_API_NAMESPACE") Expect(os.Setenv("BUILD_API_NAMESPACE", "default")).To(Succeed()) }) @@ -119,6 +121,7 @@ var _ = Describe("APIServer", func() { AfterEach(func() { getClientFromRequestFn = originalGetClientFromRequestFn loadOperatorConfigFn = originalLoadOperatorConfigFn + loadTargetDefaultsFn = originalLoadTargetDefaultsFn if hasOriginalNamespace { Expect(os.Setenv("BUILD_API_NAMESPACE", originalNamespace)).To(Succeed()) } else { @@ -153,9 +156,10 @@ var _ = Describe("APIServer", func() { var response OperatorConfigResponse Expect(json.Unmarshal(w.Body.Bytes(), &response)).To(Succeed()) Expect(response.JumpstarterTargets).To(BeNil()) + Expect(response.TargetDefaults).To(BeNil()) }) - It("should return jumpstarter target mappings when config exists", func() { + It("should return jumpstarter targets and target defaults when config exists", func() { config := &automotivev1alpha1.OperatorConfig{ Spec: automotivev1alpha1.OperatorConfigSpec{ Jumpstarter: &automotivev1alpha1.JumpstarterConfig{ @@ -164,9 +168,8 @@ var _ = Describe("APIServer", func() { Selector: "board-type=qemu", }, "ebbr": { - Selector: "board-type=ebbr", - Architecture: "arm64", - ExtraArgs: []string{"--separate-partitions"}, + Selector: "board-type=ebbr", + FlashCmd: "j storage flash ${IMAGE}", }, }, }, @@ -179,6 +182,11 @@ var _ = Describe("APIServer", func() { loadOperatorConfigFn = func(_ context.Context, _ ctrlclient.Client, _ string) (*automotivev1alpha1.OperatorConfig, error) { return config, nil } + loadTargetDefaultsFn = func(_ context.Context, _ ctrlclient.Client, _ string) (map[string]TargetDefaults, error) { + return map[string]TargetDefaults{ + "ebbr": {Architecture: "arm64", ExtraArgs: []string{"--separate-partitions"}}, + }, nil + } req, err := http.NewRequest(http.MethodGet, "/v1/config", nil) Expect(err).NotTo(HaveOccurred()) @@ -193,9 +201,13 @@ var _ = Describe("APIServer", func() { var response OperatorConfigResponse Expect(json.Unmarshal(w.Body.Bytes(), &response)).To(Succeed()) Expect(response.JumpstarterTargets).To(HaveLen(2)) - Expect(response.JumpstarterTargets["qemu"]).To(Equal(TargetDefaults{Selector: "board-type=qemu"})) - Expect(response.JumpstarterTargets["ebbr"]).To(Equal(TargetDefaults{ - Selector: "board-type=ebbr", + Expect(response.JumpstarterTargets["qemu"]).To(Equal(JumpstarterTarget{Selector: "board-type=qemu"})) + Expect(response.JumpstarterTargets["ebbr"]).To(Equal(JumpstarterTarget{ + Selector: "board-type=ebbr", + FlashCmd: "j storage flash ${IMAGE}", + })) + Expect(response.TargetDefaults).To(HaveLen(1)) + Expect(response.TargetDefaults["ebbr"]).To(Equal(TargetDefaults{ Architecture: "arm64", ExtraArgs: []string{"--separate-partitions"}, })) diff --git a/internal/buildapi/types.go b/internal/buildapi/types.go index f6581129..4a8d08fa 100644 --- a/internal/buildapi/types.go +++ b/internal/buildapi/types.go @@ -252,17 +252,24 @@ type BuildListItem struct { DiskImage string `json:"diskImage,omitempty"` } -// TargetDefaults contains build defaults and Jumpstarter configuration for a target +// JumpstarterTarget contains flash-specific config for a target (from CRD) +type JumpstarterTarget struct { + Selector string `json:"selector"` + FlashCmd string `json:"flashCmd,omitempty"` +} + +// TargetDefaults contains build defaults for a target (from ConfigMap) type TargetDefaults struct { - Selector string `json:"selector"` Architecture string `json:"architecture,omitempty"` ExtraArgs []string `json:"extraArgs,omitempty"` } // OperatorConfigResponse returns relevant operator configuration for CLI validation type OperatorConfigResponse struct { - // JumpstarterTargets contains the target mappings with build defaults - JumpstarterTargets map[string]TargetDefaults `json:"jumpstarterTargets,omitempty"` + // JumpstarterTargets contains flash-specific config per target (from CRD) + JumpstarterTargets map[string]JumpstarterTarget `json:"jumpstarterTargets,omitempty"` + // TargetDefaults contains build defaults per target (from ConfigMap) + TargetDefaults map[string]TargetDefaults `json:"targetDefaults,omitempty"` } type ( diff --git a/internal/common/tasks/scripts/push_artifact.sh b/internal/common/tasks/scripts/push_artifact.sh index 0198e2d5..43fb26c8 100644 --- a/internal/common/tasks/scripts/push_artifact.sh +++ b/internal/common/tasks/scripts/push_artifact.sh @@ -174,7 +174,7 @@ distro="$(params.distro)" target="$(params.target)" arch="$(params.arch)" -config_file="/etc/partition-config/partition-rules.yaml" +config_file="/etc/target-defaults/target-defaults.yaml" default_partitions="" if [ -f "$config_file" ]; then # Use yq to extract included partitions for target (using bracket notation for safety) diff --git a/internal/common/tasks/tasks.go b/internal/common/tasks/tasks.go index d4865232..36de46bc 100644 --- a/internal/common/tasks/tasks.go +++ b/internal/common/tasks/tasks.go @@ -107,8 +107,8 @@ func GeneratePushArtifactRegistryTask(namespace string) *tektonv1.Task { SubPath: ".dockerconfigjson", }, { - Name: "partition-config", - MountPath: "/etc/partition-config", + Name: "target-defaults", + MountPath: "/etc/target-defaults", ReadOnly: true, }, }, @@ -124,11 +124,11 @@ func GeneratePushArtifactRegistryTask(namespace string) *tektonv1.Task { }, }, { - Name: "partition-config", + Name: "target-defaults", VolumeSource: corev1.VolumeSource{ ConfigMap: &corev1.ConfigMapVolumeSource{ LocalObjectReference: corev1.LocalObjectReference{ - Name: "aib-partition-config", + Name: "aib-target-defaults", }, Optional: ptr.To(true), }, diff --git a/internal/controller/operatorconfig/controller.go b/internal/controller/operatorconfig/controller.go index b990c61d..1a53cc82 100644 --- a/internal/controller/operatorconfig/controller.go +++ b/internal/controller/operatorconfig/controller.go @@ -37,6 +37,51 @@ const ( unmanagedAnnotationTrue = "true" ) +// targetDefaultsYAML is the default content for the aib-target-defaults ConfigMap. +// It defines per-target build defaults (architecture, extra args, partition rules). +var targetDefaultsYAML = `targets: + ridesx4: + architecture: arm64 + extraArgs: ["--separate-partitions"] + include: ["system_a", "system_b", "boot_a", "boot_b"] + ridesx4_r3: + architecture: arm64 + extraArgs: ["--separate-partitions"] + include: ["system_a", "system_b", "boot_a", "boot_b"] + ridesx4_scmi: + architecture: arm64 + extraArgs: ["--separate-partitions"] + include: ["system_a", "system_b", "boot_a", "boot_b"] + ride4_sa8775p_sx_r3: + architecture: arm64 + extraArgs: ["--separate-partitions"] + include: ["system_a", "system_b", "boot_a", "boot_b"] + ride4_sa8775p_sx: + architecture: arm64 + extraArgs: ["--separate-partitions"] + include: ["system_a", "system_b", "boot_a", "boot_b"] + ride4_sa8775p_sx_legacy: + architecture: arm64 + extraArgs: ["--separate-partitions"] + include: ["system_a", "system_b", "boot_a", "boot_b"] + ride4_sa8775p_sx_legacy_r3: + architecture: arm64 + extraArgs: ["--separate-partitions"] + include: ["system_a", "system_b", "boot_a", "boot_b"] + ride4_sa8650p_sx_r3: + architecture: arm64 + extraArgs: ["--separate-partitions"] + include: ["system_a", "system_b", "boot_a", "boot_b"] + ebbr: + architecture: arm64 + rcar_s4: + architecture: arm64 + j784s4evm: + architecture: arm64 + s32g_vnp_rdb3: + architecture: arm64 +` + // isNoMatchError checks if error is "no matches for kind" error (CRD doesn't exist) func isNoMatchError(err error) bool { if err == nil { @@ -524,10 +569,10 @@ func (r *OperatorConfigReconciler) deployOSBuilds( } } - // Create partition configuration ConfigMap - if err := r.createOrUpdatePartitionConfig(ctx, config); err != nil { - r.Log.Error(err, "Failed to create partition configuration") - return fmt.Errorf("failed to create partition configuration: %w", err) + // Create target defaults ConfigMap (architecture, partition rules, etc.) + if err := r.createOrUpdateTargetDefaults(ctx, config); err != nil { + r.Log.Error(err, "Failed to create target defaults ConfigMap") + return fmt.Errorf("failed to create target defaults ConfigMap: %w", err) } // Generate and deploy Tekton tasks @@ -570,31 +615,14 @@ func (r *OperatorConfigReconciler) deployOSBuilds( return nil } -func (r *OperatorConfigReconciler) createOrUpdatePartitionConfig(ctx context.Context, owner *automotivev1alpha1.OperatorConfig) error { +func (r *OperatorConfigReconciler) createOrUpdateTargetDefaults(ctx context.Context, owner *automotivev1alpha1.OperatorConfig) error { configMap := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ - Name: "aib-partition-config", + Name: "aib-target-defaults", Namespace: owner.Namespace, }, Data: map[string]string{ - "partition-rules.yaml": `targets: - ridesx4: - include: ["system_a", "system_b", "boot_a", "boot_b"] - ridesx4_r3: - include: ["system_a", "system_b", "boot_a", "boot_b"] - ridesx4_scmi: - include: ["system_a", "system_b", "boot_a", "boot_b"] - ride4_sa8775p_sx_r3: - include: ["system_a", "system_b", "boot_a", "boot_b"] - ride4_sa8775p_sx: - include: ["system_a", "system_b", "boot_a", "boot_b"] - ride4_sa8775p_sx_legacy: - include: ["system_a", "system_b", "boot_a", "boot_b"] - ride4_sa8775p_sx_legacy_r3: - include: ["system_a", "system_b", "boot_a", "boot_b"] - ride4_sa8650p_sx_r3: - include: ["system_a", "system_b", "boot_a", "boot_b"] -`, + "target-defaults.yaml": targetDefaultsYAML, }, } @@ -727,14 +755,14 @@ func (r *OperatorConfigReconciler) cleanupBuildController(ctx context.Context, c func (r *OperatorConfigReconciler) cleanupOSBuilds(ctx context.Context, config *automotivev1alpha1.OperatorConfig) error { r.Log.Info("Cleaning up OSBuilds resources") - // Delete partition configuration ConfigMap + // Delete target defaults ConfigMap configMap := &corev1.ConfigMap{} - configMap.Name = "aib-partition-config" + configMap.Name = "aib-target-defaults" configMap.Namespace = config.Namespace if err := r.Delete(ctx, configMap); err != nil && !errors.IsNotFound(err) { - return fmt.Errorf("failed to delete partition configuration ConfigMap: %w", err) + return fmt.Errorf("failed to delete target defaults ConfigMap: %w", err) } - r.Log.Info("Partition configuration ConfigMap deleted") + r.Log.Info("Target defaults ConfigMap deleted") // Delete Tekton tasks taskNames := []string{"build-automotive-image", "push-artifact-registry", "prepare-builder", "flash-image"} diff --git a/internal/controller/operatorconfig/resources_test.go b/internal/controller/operatorconfig/resources_test.go index e8a88782..1922db3e 100644 --- a/internal/controller/operatorconfig/resources_test.go +++ b/internal/controller/operatorconfig/resources_test.go @@ -21,6 +21,7 @@ import ( . "github.com/onsi/ginkgo/v2" //nolint:revive . "github.com/onsi/gomega" //nolint:revive + "gopkg.in/yaml.v3" corev1 "k8s.io/api/core/v1" ) @@ -113,6 +114,43 @@ var _ = Describe("OperatorConfig Resources", func() { }) }) + Describe("targetDefaultsYAML", func() { + It("should be valid YAML", func() { + var parsed map[string]interface{} + err := yaml.Unmarshal([]byte(targetDefaultsYAML), &parsed) + Expect(err).NotTo(HaveOccurred(), "targetDefaultsYAML should be valid YAML") + }) + + It("should have a targets key with entries", func() { + var parsed struct { + Targets map[string]struct { + Architecture string `yaml:"architecture"` + ExtraArgs []string `yaml:"extraArgs"` + Include []string `yaml:"include"` + } `yaml:"targets"` + } + err := yaml.Unmarshal([]byte(targetDefaultsYAML), &parsed) + Expect(err).NotTo(HaveOccurred()) + Expect(parsed.Targets).NotTo(BeEmpty(), "should have at least one target") + }) + + It("should have a valid architecture for every target", func() { + var parsed struct { + Targets map[string]struct { + Architecture string `yaml:"architecture"` + } `yaml:"targets"` + } + Expect(yaml.Unmarshal([]byte(targetDefaultsYAML), &parsed)).To(Succeed()) + + validArchitectures := map[string]bool{"arm64": true, "amd64": true} + for name, t := range parsed.Targets { + Expect(t.Architecture).NotTo(BeEmpty(), "target %q should have an architecture", name) + Expect(validArchitectures).To(HaveKey(t.Architecture), + "target %q has unexpected architecture %q", name, t.Architecture) + } + }) + }) + Describe("buildBuildControllerDeployment", func() { It("should use ado-build-controller service account", func() { deployment := r.buildBuildControllerDeployment("test-namespace")