-
Notifications
You must be signed in to change notification settings - Fork 231
Read Metal3 config from a new CRD #470
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| package operator | ||
|
|
||
| import ( | ||
| "github.com/golang/glog" | ||
| metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
| "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" | ||
| "k8s.io/apimachinery/pkg/runtime/schema" | ||
| dynamic "k8s.io/client-go/dynamic" | ||
| ) | ||
|
|
||
| var provisioningGVR = schema.GroupVersionResource{Group: "metal3.io", Resource: "provisionings", Version: "v1alpha1"} | ||
| var baremetalProvisioningCR = "cluster" | ||
|
|
||
| // Provisioning Config needed to deploy Metal3 pod | ||
| type BaremetalProvisioningConfig struct { | ||
| ProvisioningInterface string | ||
| ProvisioningIp string | ||
| ProvisioningNetworkCIDR string | ||
| ProvisioningDHCPExternal bool | ||
| ProvisioningDHCPRange string | ||
| } | ||
|
|
||
| func getBaremetalProvisioningConfig(dc dynamic.Interface, configName string) (BaremetalProvisioningConfig, error) { | ||
| provisioningClient := dc.Resource(provisioningGVR) | ||
| provisioningConfig, err := provisioningClient.Get(configName, metav1.GetOptions{}) | ||
| if err != nil { | ||
| glog.Errorf("Error getting config from Baremetal provisioning CR %s", configName) | ||
| return BaremetalProvisioningConfig{}, err | ||
| } | ||
| provisioningSpec, found, err := unstructured.NestedMap(provisioningConfig.UnstructuredContent(), "spec") | ||
| if !found { | ||
| glog.Errorf("Nested Spec not found in Baremetal provisioning CR %s", configName) | ||
| return BaremetalProvisioningConfig{}, err | ||
| } | ||
| provisioningInterface, found, err := unstructured.NestedString(provisioningSpec, "provisioningInterface") | ||
| if !found { | ||
| glog.Errorf("provisioningInterface not found in Baremetal provisioning CR %s", configName) | ||
| return BaremetalProvisioningConfig{}, err | ||
| } | ||
| provisioningIP, found, err := unstructured.NestedString(provisioningSpec, "provisioningIP") | ||
| if !found { | ||
| glog.Errorf("provisioningIP not found in Baremetal provisioning CR %s", configName) | ||
| return BaremetalProvisioningConfig{}, err | ||
| } | ||
| provisioningNetworkCIDR, found, err := unstructured.NestedString(provisioningSpec, "provisioningNetworkCIDR") | ||
| if !found { | ||
| glog.Errorf("provisioningNetworkCIDR not found in Baremetal provisioning CR %s", configName) | ||
| return BaremetalProvisioningConfig{}, err | ||
| } | ||
| provisioningDHCPExternal, found, err := unstructured.NestedBool(provisioningSpec, "provisioningDHCPExternal") | ||
| if !found { | ||
| glog.Errorf("provisioningDHCPExternal not found in Baremetal provisioning CR %s", configName) | ||
| return BaremetalProvisioningConfig{}, err | ||
| } | ||
| provisioningDHCPRange, found, err := unstructured.NestedString(provisioningSpec, "provisioningDHCPRange") | ||
| if !found { | ||
| glog.Errorf("provisioningDHCPRange not found in Baremetal provisioning CR %s", configName) | ||
| return BaremetalProvisioningConfig{}, err | ||
| } | ||
| return BaremetalProvisioningConfig{ | ||
| ProvisioningInterface: provisioningInterface, | ||
| ProvisioningIp: provisioningIP, | ||
| ProvisioningNetworkCIDR: provisioningNetworkCIDR, | ||
| ProvisioningDHCPExternal: provisioningDHCPExternal, | ||
| ProvisioningDHCPRange: provisioningDHCPRange, | ||
| }, nil | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,7 +4,31 @@ import ( | |
| "testing" | ||
|
|
||
| metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
| "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" | ||
| "k8s.io/apimachinery/pkg/runtime" | ||
| fakedynamic "k8s.io/client-go/dynamic/fake" | ||
| fakekube "k8s.io/client-go/kubernetes/fake" | ||
| "sigs.k8s.io/yaml" | ||
| ) | ||
|
|
||
| var yamlContent = ` | ||
| apiVersion: metal3.io/v1alpha1 | ||
| kind: Provisioning | ||
| metadata: | ||
| name: test | ||
| spec: | ||
| provisioningInterface: "ensp0" | ||
| provisioningIP: "172.30.20.3" | ||
| provisioningNetworkCIDR: "172.30.20.0/24" | ||
| provisioningDHCPExternal: false | ||
| provisioningDHCPRange: "172.30.20.10, 72.30.20.100" | ||
| ` | ||
| var ( | ||
| expectedProvisioningInterface = "ensp0" | ||
| expectedProvisioningIP = "172.30.20.3" | ||
| expectedProvisioningNetworkCIDR = "172.30.20.0/24" | ||
| expectedProvisioningDHCPExternal = false | ||
| expectedProvisioningDHCPRange = "172.30.20.10, 72.30.20.100" | ||
| ) | ||
|
|
||
| func TestGenerateRandomPassword(t *testing.T) { | ||
|
|
@@ -71,3 +95,40 @@ func TestCreateMariadbPasswordSecret(t *testing.T) { | |
| t.Logf("First Mariadb password is being preserved over re-creation as expected.") | ||
| } | ||
| } | ||
|
|
||
| func TestGetBaremetalProvisioningConfig(t *testing.T) { | ||
| u := &unstructured.Unstructured{Object: map[string]interface{}{}} | ||
| if err := yaml.Unmarshal([]byte(yamlContent), &u); err != nil { | ||
| t.Errorf("failed to unmarshall input yaml content:%v", err) | ||
| } | ||
| dynamicClient := fakedynamic.NewSimpleDynamicClient(runtime.NewScheme(), u) | ||
| baremetalConfig, err := getBaremetalProvisioningConfig(dynamicClient, "test") | ||
| if err != nil { | ||
| t.Logf("Unstructed Config: %+v", u) | ||
| t.Fatalf("Failed to get Baremetal Provisioning Interface from CR %s", "test") | ||
| } | ||
| if baremetalConfig.ProvisioningInterface != expectedProvisioningInterface || | ||
| baremetalConfig.ProvisioningIp != expectedProvisioningIP || | ||
| baremetalConfig.ProvisioningNetworkCIDR != expectedProvisioningNetworkCIDR || | ||
| baremetalConfig.ProvisioningDHCPExternal != expectedProvisioningDHCPExternal || | ||
| baremetalConfig.ProvisioningDHCPRange != expectedProvisioningDHCPRange { | ||
| t.Logf("Actual BaremetalProvisioningConfig: %+v", baremetalConfig) | ||
| t.Logf("Expected : ProvisioningInterface: %s, ProvisioningIP: %s, ProvisioningNetworkCIDR: %s, ProvisioningDHCPExternal: %t, expectedProvisioningDHCPRange: %s", expectedProvisioningInterface, expectedProvisioningIP, expectedProvisioningNetworkCIDR, expectedProvisioningDHCPExternal, expectedProvisioningDHCPRange) | ||
sadasu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| t.Fatalf("failed getBaremetalProvisioningConfig. One or more BaremetalProvisioningConfig items do not match the expected config.") | ||
| } | ||
| } | ||
|
|
||
| func TestGetIncorrectBaremetalProvisioningCR(t *testing.T) { | ||
| u := &unstructured.Unstructured{Object: map[string]interface{}{}} | ||
| if err := yaml.Unmarshal([]byte(yamlContent), &u); err != nil { | ||
| t.Errorf("failed to unmarshall input yaml content:%v", err) | ||
| } | ||
| dynamicClient := fakedynamic.NewSimpleDynamicClient(runtime.NewScheme(), u) | ||
| baremetalConfig, err := getBaremetalProvisioningConfig(dynamicClient, "test1") | ||
| if err != nil { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. wouldn't be the client expected to error here and so For unit testing we prefer to have one testTunction per function i.e |
||
| t.Logf("Unable to get Baremetal Provisioning Config from CR %s as expected", "test1") | ||
| } | ||
| if baremetalConfig.ProvisioningInterface != "" { | ||
| t.Errorf("BaremetalProvisioningConfig is not expected to be set.") | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -74,13 +74,18 @@ func (optr *Operator) syncClusterAPIController(config *OperatorConfig) error { | |
| } | ||
|
|
||
| func (optr *Operator) syncBaremetalControllers(config *OperatorConfig) error { | ||
| // First create a Secret needed for the Metal3 deployment | ||
| // Try to get baremetal provisioning config from a CR | ||
| baremetalProvisioningConfig, err := getBaremetalProvisioningConfig(optr.dynamicClient, baremetalProvisioningCR) | ||
| if err != nil { | ||
| glog.Infof("Unable to read Baremetal Provisioning config from CR %s.", baremetalProvisioningCR) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I find it weird not returning err here, at minimum this should log.error, and make clear in the message the function will continue nevertheless
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In this release, we cannot return error and stop deploying Metal3 because during discussions around upgrade strategy, we had decided to have one release where the config could be obtained from either sources, the ConfigMap or the newly created Config resource. |
||
| } | ||
| // Create a Secret needed for the Metal3 deployment | ||
| if err := createMariadbPasswordSecret(optr.kubeClient.CoreV1(), config); err != nil { | ||
| glog.Error("Not proceeding with Metal3 deployment. Failed to create Mariadb password.") | ||
| return err | ||
| } | ||
|
|
||
| metal3Deployment := newMetal3Deployment(config) | ||
| metal3Deployment := newMetal3Deployment(config, baremetalProvisioningConfig) | ||
| _, updated, err := resourceapply.ApplyDeployment(optr.kubeClient.AppsV1(), metal3Deployment) | ||
| if err != nil { | ||
| return err | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.