diff --git a/pkg/apis/machine/v1beta1/machine_types.go b/pkg/apis/machine/v1beta1/machine_types.go index ff69037560..5cf1fc2968 100644 --- a/pkg/apis/machine/v1beta1/machine_types.go +++ b/pkg/apis/machine/v1beta1/machine_types.go @@ -17,8 +17,6 @@ limitations under the License. package v1beta1 import ( - "fmt" - corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -196,13 +194,8 @@ type LastOperation struct { func (m *Machine) Validate() field.ErrorList { errors := field.ErrorList{} - // validate spec.labels - fldPath := field.NewPath("spec") - if m.Labels[MachineClusterIDLabel] == "" { - errors = append(errors, field.Invalid(fldPath.Child("labels"), m.Labels, fmt.Sprintf("missing %v label.", MachineClusterIDLabel))) - } - // validate provider config is set + fldPath := field.NewPath("spec") if m.Spec.ProviderSpec.Value == nil { errors = append(errors, field.Invalid(fldPath.Child("spec").Child("providerspec"), m.Spec.ProviderSpec, "value field must be set")) } diff --git a/pkg/controller/machine/controller.go b/pkg/controller/machine/controller.go index 8b84b7e0ab..22b4768685 100644 --- a/pkg/controller/machine/controller.go +++ b/pkg/controller/machine/controller.go @@ -22,6 +22,7 @@ import ( "fmt" "time" + configv1 "github.com/openshift/api/config/v1" machinev1 "github.com/openshift/machine-api-operator/pkg/apis/machine/v1beta1" "github.com/openshift/machine-api-operator/pkg/util" corev1 "k8s.io/api/core/v1" @@ -91,6 +92,8 @@ const ( unknownInstanceState = "Unknown" skipWaitForDeleteTimeoutSeconds = 60 * 5 + + globalInfrastuctureName = "cluster" ) var DefaultActuator Actuator @@ -175,6 +178,11 @@ func (r *ReconcileMachine) Reconcile(request reconcile.Request) (reconcile.Resul return reconcile.Result{}, err } + // Add clusterID label + if err := r.setClusterIDLabel(ctx, m); err != nil { + return reconcile.Result{}, err + } + // If object hasn't been deleted and doesn't have a finalizer, add one // Add a finalizer to newly created objects. if m.ObjectMeta.DeletionTimestamp.IsZero() { @@ -462,6 +470,25 @@ func (r *ReconcileMachine) patchFailedMachineInstanceAnnotation(machine *machine return nil } +func (r *ReconcileMachine) setClusterIDLabel(ctx context.Context, m *machinev1.Machine) error { + infra := &configv1.Infrastructure{} + infraName := client.ObjectKey{Name: globalInfrastuctureName} + + if err := r.Client.Get(ctx, infraName, infra); err != nil { + return err + } + + clusterID := infra.Status.InfrastructureName + + if m.Labels == nil { + m.Labels = make(map[string]string) + } + + m.Labels[machinev1.MachineClusterIDLabel] = clusterID + + return nil +} + func machineIsProvisioned(machine *machinev1.Machine) bool { return len(machine.Status.Addresses) > 0 || stringPointerDeref(machine.Spec.ProviderID) != "" } diff --git a/pkg/controller/machine/controller_test.go b/pkg/controller/machine/controller_test.go index 3cf43202ad..2540a8812a 100644 --- a/pkg/controller/machine/controller_test.go +++ b/pkg/controller/machine/controller_test.go @@ -24,6 +24,7 @@ import ( "time" . "github.com/onsi/gomega" + configv1 "github.com/openshift/api/config/v1" machinev1 "github.com/openshift/machine-api-operator/pkg/apis/machine/v1beta1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -40,7 +41,20 @@ var ( _ reconcile.Reconciler = &ReconcileMachine{} ) +func init() { + configv1.AddToScheme(scheme.Scheme) +} + func TestReconcileRequest(t *testing.T) { + infra := configv1.Infrastructure{ + ObjectMeta: metav1.ObjectMeta{ + Name: globalInfrastuctureName, + }, + Status: configv1.InfrastructureStatus{ + InfrastructureName: "test-id", + }, + } + machineProvisioning := machinev1.Machine{ TypeMeta: metav1.TypeMeta{ Kind: "Machine", @@ -278,6 +292,7 @@ func TestReconcileRequest(t *testing.T) { &machineDeleting, &machineFailed, &machineRunning, + &infra, ), scheme: scheme.Scheme, actuator: act, @@ -714,3 +729,31 @@ func TestDelayIfRequeueAfterError(t *testing.T) { }) } } + +func TestSetClusterIDLabel(t *testing.T) { + clusterID := "test-id" + infra := &configv1.Infrastructure{ + ObjectMeta: metav1.ObjectMeta{ + Name: globalInfrastuctureName, + }, + Status: configv1.InfrastructureStatus{ + InfrastructureName: clusterID, + }, + } + + machine := &machinev1.Machine{} + + reconciler := &ReconcileMachine{ + Client: fake.NewFakeClientWithScheme(scheme.Scheme, infra), + scheme: scheme.Scheme, + } + + if err := reconciler.setClusterIDLabel(ctx, machine); err != nil { + t.Fatal(err) + } + + actualClusterID := machine.Labels[machinev1.MachineClusterIDLabel] + if actualClusterID != clusterID { + t.Fatalf("Expected clusterID %s, got %s", clusterID, actualClusterID) + } +} diff --git a/pkg/controller/machine/machine_controller_suite_test.go b/pkg/controller/machine/machine_controller_suite_test.go index 73fafa124f..84c013ec80 100644 --- a/pkg/controller/machine/machine_controller_suite_test.go +++ b/pkg/controller/machine/machine_controller_suite_test.go @@ -23,6 +23,7 @@ import ( "path/filepath" "testing" + configv1 "github.com/openshift/api/config/v1" "github.com/openshift/machine-api-operator/pkg/apis/machine/v1beta1" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" @@ -37,9 +38,12 @@ var ( func TestMain(m *testing.M) { t := &envtest.Environment{ - CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "install")}, + CRDDirectoryPaths: []string{ + filepath.Join("..", "..", "..", "install"), + filepath.Join("..", "..", "..", "vendor", "github.com", "openshift", "api", "config", "v1")}, } v1beta1.AddToScheme(scheme.Scheme) + configv1.AddToScheme(scheme.Scheme) var err error if cfg, err = t.Start(); err != nil { diff --git a/pkg/controller/machine/machine_controller_test.go b/pkg/controller/machine/machine_controller_test.go index 45583780c1..544d963a4a 100644 --- a/pkg/controller/machine/machine_controller_test.go +++ b/pkg/controller/machine/machine_controller_test.go @@ -21,6 +21,7 @@ import ( "time" . "github.com/onsi/gomega" + configv1 "github.com/openshift/api/config/v1" machinev1beta1 "github.com/openshift/machine-api-operator/pkg/apis/machine/v1beta1" "golang.org/x/net/context" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -52,6 +53,15 @@ func TestReconcile(t *testing.T) { }, } + infra := &configv1.Infrastructure{ + ObjectMeta: metav1.ObjectMeta{ + Name: globalInfrastuctureName, + }, + Status: configv1.InfrastructureStatus{ + InfrastructureName: "test-id", + }, + } + // Setup the Manager and Controller. Wrap the Controller Reconcile function so it writes each request to a // channel when it is finished. mgr, err := manager.New(cfg, manager.Options{MetricsBindAddress: "0"}) @@ -74,6 +84,11 @@ func TestReconcile(t *testing.T) { } }() + if err := c.Create(context.TODO(), infra); err != nil { + t.Fatalf("error creating instance: %v", err) + } + defer c.Delete(context.TODO(), infra) + // Create the Machine object and expect Reconcile and the actuator to be called if err := c.Create(context.TODO(), instance); err != nil { t.Fatalf("error creating instance: %v", err)