@@ -30,66 +30,89 @@ import (
3030)
3131
3232// DefaultClusterVariables defaults ClusterVariables.
33- func DefaultClusterVariables (clusterVariables []clusterv1.ClusterVariable , clusterClassVariables []clusterv1.ClusterClassVariable , fldPath * field.Path ) ([]clusterv1.ClusterVariable , field.ErrorList ) {
33+ func DefaultClusterVariables (clusterVariables []clusterv1.ClusterVariable , clusterClassVariables []clusterv1.ClusterClassStatusVariable , fldPath * field.Path ) ([]clusterv1.ClusterVariable , field.ErrorList ) {
3434 return defaultClusterVariables (clusterVariables , clusterClassVariables , true , fldPath )
3535}
3636
3737// DefaultMachineDeploymentVariables defaults MachineDeploymentVariables.
38- func DefaultMachineDeploymentVariables (machineDeploymentVariables []clusterv1.ClusterVariable , clusterClassVariables []clusterv1.ClusterClassVariable , fldPath * field.Path ) ([]clusterv1.ClusterVariable , field.ErrorList ) {
38+ func DefaultMachineDeploymentVariables (machineDeploymentVariables []clusterv1.ClusterVariable , clusterClassVariables []clusterv1.ClusterClassStatusVariable , fldPath * field.Path ) ([]clusterv1.ClusterVariable , field.ErrorList ) {
3939 return defaultClusterVariables (machineDeploymentVariables , clusterClassVariables , false , fldPath )
4040}
4141
4242// defaultClusterVariables defaults variables.
4343// If they do not exist yet, they are created if createVariables is set.
44- func defaultClusterVariables (clusterVariables []clusterv1.ClusterVariable , clusterClassVariables []clusterv1.ClusterClassVariable , createVariables bool , fldPath * field.Path ) ([]clusterv1.ClusterVariable , field.ErrorList ) {
44+ func defaultClusterVariables (clusterVariables []clusterv1.ClusterVariable , clusterClassVariables []clusterv1.ClusterClassStatusVariable , createVariables bool , fldPath * field.Path ) ([]clusterv1.ClusterVariable , field.ErrorList ) {
4545 var allErrs field.ErrorList
4646
47- // Build maps for easier and faster access.
48- clusterVariablesMap := getClusterVariablesMap (clusterVariables )
49- clusterClassVariablesMap := getClusterClassVariablesMap (clusterClassVariables )
50-
51- // Validate that all variables in the Cluster are defined in the ClusterClass.
52- // Note: If we don't validate this, we would get a nil pointer dereference below.
53- allErrs = append (allErrs , validateClusterVariablesDefined (clusterVariables , clusterClassVariablesMap , fldPath )... )
54- if len (allErrs ) > 0 {
55- return nil , allErrs
47+ // Get a map of ClusterVariables and ensure that variables are not defined more than once in Cluster spec.
48+ clusterVariablesMap , err := getClusterVariablesMap (clusterVariables )
49+ if err != nil {
50+ return nil , append (allErrs , field .Invalid (fldPath , clusterVariables ,
51+ fmt .Sprintf ("cluster variables not valid: %s" , err )))
5652 }
5753
54+ // Get a map of ClusterClassVariables for each variable name and definition.
55+ clusterClassVariablesMap := getClusterClassVariablesMap (clusterClassVariables )
56+
5857 // allVariables is used to get a full correctly ordered list of variables.
59- allVariables := []string {}
58+ allVariables := []clusterv1. ClusterVariable {}
6059 // Add any ClusterVariables that already exist.
61- for _ , variable := range clusterVariables {
62- allVariables = append (allVariables , variable .Name )
63- }
60+ allVariables = append (allVariables , clusterVariables ... )
61+
6462 // Add variables from the ClusterClass, which currently don't exist on the Cluster.
6563 for _ , variable := range clusterClassVariables {
66- // Continue if the ClusterClass variable already exists.
67- if _ , ok := clusterVariablesMap [variable .Name ]; ok {
68- continue
64+ for _ , definition := range variable .Definitions {
65+ if _ , ok := clusterVariablesMap [variable .Name ]; ok {
66+ // Continue if the Cluster variable with a definitionFrom this ClusterClass variable exists.
67+ if _ , ok := clusterVariablesMap [variable.Name ][definition.From ]; ok {
68+ continue
69+ }
70+ // Continue if the Cluster variable with an empty definitionFrom exists. The user intention here is to
71+ // use the default value from a ClusterClass variable with no conflicting variables.
72+ if _ , ok := clusterVariablesMap [variable.Name ][emptyVariableDefinitionFrom ]; ok {
73+ continue
74+ }
75+ }
76+ allVariables = append (allVariables , clusterv1.ClusterVariable {
77+ Name : variable .Name ,
78+ DefinitionFrom : definition .From ,
79+ })
6980 }
70-
71- allVariables = append (allVariables , variable .Name )
7281 }
7382
7483 // Default all variables.
7584 defaultedClusterVariables := []clusterv1.ClusterVariable {}
76- for i , variableName := range allVariables {
77- clusterClassVariable := clusterClassVariablesMap [variableName ]
78- clusterVariable := clusterVariablesMap [variableName ]
85+ for i , variable := range allVariables {
86+ clusterClassVariable , found := clusterClassVariablesMap [ccVariableMapKey {name : variable .Name , from : variable .DefinitionFrom }]
87+ if ! found {
88+ allErrs = append (allErrs , field .Invalid (fldPath .Index (i ).Child ("name" ), variable .Name ,
89+ fmt .Sprintf ("variable with name %q from %q is not defined in ClusterClass `status.Variables`." , variable .Name , variable .DefinitionFrom )))
90+ continue
91+ }
7992
80- defaultedClusterVariable , errs := defaultClusterVariable (clusterVariable , clusterClassVariable , fldPath .Index (i ), createVariables )
93+ // If the variable is defined in the Cluster spec get the definition.
94+ var clusterVariable * clusterv1.ClusterVariable
95+ if variablesWithName , ok := clusterVariablesMap [variable .Name ]; ok {
96+ if variableFromDefinition , ok := variablesWithName [variable .DefinitionFrom ]; ok {
97+ clusterVariable = & variableFromDefinition
98+ }
99+ }
100+
101+ defaultedClusterVariable , errs := defaultClusterVariable (clusterVariable , & clusterv1.ClusterClassVariable {
102+ Name : variable .Name ,
103+ Required : clusterClassVariable .Required ,
104+ Schema : clusterClassVariable .Schema ,
105+ }, clusterClassVariable .From , fldPath .Index (i ), createVariables )
81106 if len (errs ) > 0 {
82107 allErrs = append (allErrs , errs ... )
83108 continue
84109 }
85-
86110 // Continue if there is no defaulted variable.
87111 // NOTE: This happens when the variable doesn't exist on the CLuster before and
88112 // there is no top-level default value.
89113 if defaultedClusterVariable == nil {
90114 continue
91115 }
92-
93116 defaultedClusterVariables = append (defaultedClusterVariables , * defaultedClusterVariable )
94117 }
95118
@@ -101,7 +124,7 @@ func defaultClusterVariables(clusterVariables []clusterv1.ClusterVariable, clust
101124}
102125
103126// defaultClusterVariable defaults a clusterVariable based on the default value in the clusterClassVariable.
104- func defaultClusterVariable (clusterVariable * clusterv1.ClusterVariable , clusterClassVariable * clusterv1.ClusterClassVariable , fldPath * field.Path , createVariable bool ) (* clusterv1.ClusterVariable , field.ErrorList ) {
127+ func defaultClusterVariable (clusterVariable * clusterv1.ClusterVariable , clusterClassVariable * clusterv1.ClusterClassVariable , definitionFrom string , fldPath * field.Path , createVariable bool ) (* clusterv1.ClusterVariable , field.ErrorList ) {
105128 if clusterVariable == nil {
106129 // Return if the variable does not exist yet and createVariable is false.
107130 if ! createVariable {
@@ -159,10 +182,12 @@ func defaultClusterVariable(clusterVariable *clusterv1.ClusterVariable, clusterC
159182 return nil , field.ErrorList {field .Invalid (fldPath , "" ,
160183 fmt .Sprintf ("failed to marshal default value of variable %q: %v" , clusterClassVariable .Name , err ))}
161184 }
162- return & clusterv1.ClusterVariable {
185+ v := & clusterv1.ClusterVariable {
163186 Name : clusterClassVariable .Name ,
164187 Value : apiextensionsv1.JSON {
165188 Raw : defaultedVariableValue ,
166189 },
167- }, nil
190+ DefinitionFrom : definitionFrom ,
191+ }
192+ return v , nil
168193}
0 commit comments