diff --git a/cmd/main.go b/cmd/main.go index 8fc309f03a..2b44a06609 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -2,6 +2,7 @@ package main import ( "flag" + "fmt" "io/ioutil" "time" @@ -35,6 +36,11 @@ func init() { flag.Parse() } +const ( + providerAWS = "aws" + providerLibvirt = "libvirt" +) + func main() { // Hack to deploy cluster and machineSet objects @@ -84,7 +90,6 @@ func deployMachineSet() { if err != nil { glog.Fatalf("Error building kube config %#v", err) } - client, err := clientset.NewForConfig(config) clusterApiScheme.AddToScheme(scheme.Scheme) decode := scheme.Codecs.UniversalDeserializer().Decode @@ -95,8 +100,15 @@ func deployMachineSet() { glog.Fatalf("Error reading machine-api-operator config: %v", err) } + var machinesFolder string + if operatorConfig.Provider == providerAWS { + machinesFolder = "machines/aws" + } else if operatorConfig.Provider == providerLibvirt { + machinesFolder = "machines/libvirt" + } + // Create Cluster object - clusterTemplateData, err := ioutil.ReadFile("machines/cluster.yaml") // just pass the file name + clusterTemplateData, err := ioutil.ReadFile(fmt.Sprintf("%s/cluster.yaml", machinesFolder)) // just pass the file name if err != nil { glog.Fatalf("Error reading %#v", err) } @@ -113,7 +125,7 @@ func deployMachineSet() { cluster := clusterObj.(*clusterv1.Cluster) // Create MachineSet object - machineSetTemplateData, err := ioutil.ReadFile("machines/machine-set.yaml") // just pass the file name + machineSetTemplateData, err := ioutil.ReadFile(fmt.Sprintf("%s/machine-set.yaml", machinesFolder)) // just pass the file name if err != nil { glog.Fatalf("Error reading %#v", err) } @@ -131,14 +143,14 @@ func deployMachineSet() { for { glog.Info("Trying to deploy Cluster object") - if _, err := v1alphaClient.Clusters("test").Create(cluster); err != nil { + if _, err := v1alphaClient.Clusters("default").Create(cluster); err != nil { glog.Infof("Cannot create cluster, retrying in 5 secs: %v", err) } else { glog.Info("Created Cluster object") } glog.Info("Trying to deploy MachineSet object") - _, err = v1alphaClient.MachineSets("test").Create(machineSet) + _, err = v1alphaClient.MachineSets("default").Create(machineSet) if err != nil { glog.Infof("Cannot create MachineSet, retrying in 5 secs: %v", err) } else { diff --git a/examples/machine-api-operator-config-aws.yaml b/examples/machine-api-operator-config-aws.yaml new file mode 100644 index 0000000000..6accacf85a --- /dev/null +++ b/examples/machine-api-operator-config-aws.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: machineAPIOperatorConfig +provider: aws +aws: + clusterName: meh + clusterID: b302cf66-f5ff-4d5d-1cc1-0ab2755d2065 + image: ami-0e502f54daeb8686e + region: eu-west-1 + availabilityZone: eu-west-1a + replicas: 1 diff --git a/examples/machine-api-operator-config-libvirt.yaml b/examples/machine-api-operator-config-libvirt.yaml new file mode 100644 index 0000000000..efa42f5961 --- /dev/null +++ b/examples/machine-api-operator-config-libvirt.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +kind: machineAPIOperatorConfig +provider: libvirt +libvirt: + uri: qemu+tcp://host_private_ip/system \ No newline at end of file diff --git a/machines/aws/cluster.yaml b/machines/aws/cluster.yaml new file mode 100644 index 0000000000..cd381fe1aa --- /dev/null +++ b/machines/aws/cluster.yaml @@ -0,0 +1,15 @@ +--- +apiVersion: "cluster.k8s.io/v1alpha1" +kind: Cluster +metadata: + name: {{.AWS.ClusterName}} + namespace: default +spec: + clusterNetwork: + services: + cidrBlocks: + - "10.0.0.1/24" + pods: + cidrBlocks: + - "10.0.0.2/24" + serviceDomain: unused diff --git a/machines/aws/machine-set.yaml b/machines/aws/machine-set.yaml new file mode 100644 index 0000000000..65d18c62c3 --- /dev/null +++ b/machines/aws/machine-set.yaml @@ -0,0 +1,56 @@ +--- +apiVersion: cluster.k8s.io/v1alpha1 +kind: MachineSet +metadata: + name: worker + namespace: default + labels: + sigs.k8s.io/cluster-api-cluster: {{.AWS.ClusterName}} + sigs.k8s.io/cluster-api-machine-role: worker + sigs.k8s.io/cluster-api-machine-type: worker +spec: + replicas: {{.AWS.Replicas}} + selector: + matchLabels: + sigs.k8s.io/cluster-api-machineset: worker + sigs.k8s.io/cluster-api-cluster: {{.AWS.ClusterName}} + template: + metadata: + labels: + sigs.k8s.io/cluster-api-machineset: worker + sigs.k8s.io/cluster-api-cluster: {{.AWS.ClusterName}} + sigs.k8s.io/cluster-api-machine-role: worker + sigs.k8s.io/cluster-api-machine-type: worker + spec: + providerConfig: + value: + apiVersion: aws.cluster.k8s.io/v1alpha1 + kind: AWSMachineProviderConfig + ami: + id: {{.AWS.Image}} + instanceType: m4.large + placement: + region: {{.AWS.Region}} + availabilityZone: {{.AWS.AvailabilityZone}} + subnet: + filters: + - name: "tag:Name" + values: + - {{.AWS.ClusterName}}-worker-{{.AWS.AvailabilityZone}} + publicIp: true + iamInstanceProfile: + id: {{.AWS.ClusterName}}-master-profile + keyName: tectonic + tags: + - name: tectonicClusterID + value: {{.AWS.ClusterID}} + securityGroups: + - filters: + - name: "tag:Name" + values: + - {{.AWS.ClusterName}}_worker_sg + userDataSecret: + name: ignition-worker + versions: + kubelet: "" + controlPlane: "" diff --git a/machines/cluster.yaml b/machines/cluster.yaml deleted file mode 100644 index 3044bc1ef5..0000000000 --- a/machines/cluster.yaml +++ /dev/null @@ -1,39 +0,0 @@ -apiVersion: "cluster.k8s.io/v1alpha1" -kind: Cluster -metadata: - name: test - namespace: test -spec: - clusterNetwork: - services: - cidrBlocks: - - "10.0.0.1/24" - pods: - cidrBlocks: - - "10.0.0.2/24" - serviceDomain: example.com - providerConfig: - value: - apiVersion: awsproviderconfig/v1alpha1 - kind: AWSClusterProviderConfig - clusterId: {{.VpcName}} - clusterVersionRef: - namespace: test - name: test - hardware: - aws: - region: {{.Region}} - keyPairName: {{.SshKey}} - defaultHardwareSpec: - aws: - instanceType: m4.large - machineSets: - - nodeType: Master - size: 1 - - shortName: infra - nodeType: Compute - infra: true - size: 1 - - shortName: compute - nodeType: Compute - size: 1 diff --git a/machines/libvirt/cluster.yaml b/machines/libvirt/cluster.yaml new file mode 100644 index 0000000000..829be2fde9 --- /dev/null +++ b/machines/libvirt/cluster.yaml @@ -0,0 +1,15 @@ +--- +apiVersion: "cluster.k8s.io/v1alpha1" +kind: Cluster +metadata: + name: {{.Libvirt.ClusterName}} + namespace: default +spec: + clusterNetwork: + services: + cidrBlocks: + - "10.0.0.1/24" + pods: + cidrBlocks: + - "10.0.0.2/24" + serviceDomain: unused diff --git a/machines/libvirt/machine-set.yaml b/machines/libvirt/machine-set.yaml new file mode 100644 index 0000000000..e6f9954d36 --- /dev/null +++ b/machines/libvirt/machine-set.yaml @@ -0,0 +1,43 @@ +--- +apiVersion: cluster.k8s.io/v1alpha1 +kind: MachineSet +metadata: + name: worker + namespace: default + labels: + sigs.k8s.io/cluster-api-cluster: {{.Libvirt.ClusterName}} + sigs.k8s.io/cluster-api-machine-role: worker + sigs.k8s.io/cluster-api-machine-type: worker +spec: + replicas: {{.Libvirt.Replicas}} + selector: + matchLabels: + sigs.k8s.io/cluster-api-machineset: worker + sigs.k8s.io/cluster-api-cluster: {{.Libvirt.ClusterName}} + sigs.k8s.io/cluster-api-machine-role: worker + sigs.k8s.io/cluster-api-machine-type: worker + template: + metadata: + labels: + sigs.k8s.io/cluster-api-machineset: worker + sigs.k8s.io/cluster-api-cluster: {{.Libvirt.ClusterName}} + sigs.k8s.io/cluster-api-machine-role: infra + sigs.k8s.io/cluster-api-machine-type: worker + spec: + providerConfig: + value: + apiVersion: libvirtproviderconfig/v1alpha1 + kind: LibvirtMachineProviderConfig + domainMemory: 2048 + domainVcpu: 2 + ignKey: /var/lib/libvirt/images/worker.ign + volume: + poolName: default + baseVolumeID: /var/lib/libvirt/images/coreos_base + networkInterfaceName: tectonic + networkInterfaceAddress: 192.168.124.12 + autostart: false + uri: {{.Libvirt.URI}} + versions: + kubelet: "" + controlPlane: "" \ No newline at end of file diff --git a/machines/machine-set.yaml b/machines/machine-set.yaml deleted file mode 100644 index 7ed7359ca8..0000000000 --- a/machines/machine-set.yaml +++ /dev/null @@ -1,40 +0,0 @@ -apiVersion: cluster.k8s.io/v1alpha1 -kind: MachineSet -metadata: - name: worker - namespace: test - labels: - machineapioperator.openshift.io/cluster: test -spec: - replicas: 3 - selector: - matchLabels: - machineapioperator.openshift.io/machineset: worker - machineapioperator.openshift.io/cluster: test - template: - metadata: - labels: - machineapioperator.openshift.io/machineset: worker - machineapioperator.openshift.io/cluster: test - spec: - providerConfig: - value: - apiVersion: awsproviderconfig/v1alpha1 - kind: AWSMachineProviderConfig - clusterId: {{.VpcName}} - clusterHardware: - aws: - keyPairName: {{.SshKey}} - region: {{.Region}} - hardware: - aws: - instanceType: m4.large - infra: false - vmImage: - awsImage: {{.Image}} - versions: - kubelet: 0.0.0 - controlPlane: 0.0.0 - roles: - - Master - diff --git a/manifests/clusterapi-controller.yaml b/manifests/clusterapi-controller.yaml index a804120d4c..46cf54995d 100644 --- a/manifests/clusterapi-controller.yaml +++ b/manifests/clusterapi-controller.yaml @@ -2,12 +2,15 @@ apiVersion: apps/v1beta1 kind: Deployment metadata: name: clusterapi-controllers - namespace: default + namespace: kube-system labels: api: clusterapi k8s-app: controller tectonic-operators.coreos.com/managed-by: machine-api-operator spec: + securityContext: + runAsNonRoot: true + runAsUser: 65534 selector: matchLabels: api: clusterapi @@ -44,15 +47,20 @@ spec: limits: cpu: 100m memory: 30Mi + {{- if .AWS }} - name: aws-machine-controller - image: quay.io/alberto_lamela/aws-machine-controller:mvp # TODO: move this to openshift org + image: quay.io/alberto_lamela/aws-machine-controller:dev # TODO: move this to openshift org + {{- else if .Libvirt}} + - name: libvirt-machine-controller + image: quay.io/alberto_lamela/libvirt-machine-controller:0.0.1-dev # TODO: move this to openshift org + {{- end}} env: - name: NODE_NAME valueFrom: fieldRef: fieldPath: spec.nodeName command: - - /opt/services/aws-machine-controller + - /machine-controller args: - --log-level=debug resources: diff --git a/pkg/render/config.go b/pkg/render/config.go index 78ecd2a88f..ed79f2c962 100644 --- a/pkg/render/config.go +++ b/pkg/render/config.go @@ -12,10 +12,22 @@ const ( // OperatorConfig contains configuration for KAO managed add-ons type OperatorConfig struct { metav1.TypeMeta `json:",inline"` - VpcName string `json:"vpcName"` - SshKey string `json:"sshKey"` - ClusterName string `json:"clusterName"` - ClusterDomain string `json:"clusterDomain"` - Region string `json:"region"` - Image string `json:"image"` + Provider string `json:"provider"` + AWS *awsConfig `json:"aws"` + Libvirt *libvirtConfig `json:"libvirt"` +} + +type libvirtConfig struct { + URI string `json:"uri"` + ClusterName string `json:"clusterName"` + Replicas string `json:"replicas"` +} + +type awsConfig struct { + ClusterName string `json:"clusterName"` + ClusterID string `json:"clusterID"` + Region string `json:"region"` + AvailabilityZone string `json:"availabilityZone"` + Image string `json:"image"` + Replicas string `json:"replicas"` } diff --git a/pkg/render/machine-api-operator-config.yaml b/pkg/render/machine-api-operator-config.yaml deleted file mode 100644 index 783cb8f17e..0000000000 --- a/pkg/render/machine-api-operator-config.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v1 -kind: machineAPIOperatorConfig -vpcName: "test" -sshKey: "test" -clusterName: "test" -clusterDomain: "test" diff --git a/pkg/render/render.go b/pkg/render/render.go index ee6120072a..cf8fa3f1cc 100644 --- a/pkg/render/render.go +++ b/pkg/render/render.go @@ -3,10 +3,10 @@ package render import ( "bytes" "fmt" - "html/template" "io/ioutil" "os" "path/filepath" + "text/template" "github.com/ghodss/yaml" "github.com/golang/glog" diff --git a/pkg/render/render_test.go b/pkg/render/render_test.go index 58d5de782a..252ecea13d 100644 --- a/pkg/render/render_test.go +++ b/pkg/render/render_test.go @@ -33,106 +33,242 @@ func testRenderManifest(t *testing.T, filename string, config *OperatorConfig, e } } -func TestClusterManifest(t *testing.T) { +func TestClusterAWSManifest(t *testing.T) { config := OperatorConfig{ - VpcName: "TestClusterManifest-VpcName", - SshKey: "TestClusterManifest-SshKey", - ClusterName: "TestClusterManifest-ClusterName", - ClusterDomain: "TestClusterManifest.ClusterDomain", // TODO(frobware) - currently not a template value - Region: "TestClusterManifest-Region", - Image: "TestClusterManifest-Image", + Provider: "AWS", + AWS: &awsConfig{ + ClusterName: "TestClusterManifest-ClusterName", + ClusterID: "TestClusterManifest-ClusterID", + Region: "TestClusterManifest-Region", + AvailabilityZone: "TestClusterManifest-AvailabilityZone", + Image: "TestClusterManifest-Image", + Replicas: "TestClusterManifest-Replicas", + }, } - testRenderManifest(t, "../../machines/cluster.yaml", &config, ` + testRenderManifest(t, "../../machines/aws/cluster.yaml", &config, ` +--- apiVersion: "cluster.k8s.io/v1alpha1" kind: Cluster metadata: - name: test - namespace: test + name: TestClusterManifest-ClusterName + namespace: default spec: clusterNetwork: services: cidrBlocks: - - "10.0.0.1/24" + - "10.0.0.1/24" pods: cidrBlocks: - - "10.0.0.2/24" - serviceDomain: example.com - providerConfig: - value: - apiVersion: awsproviderconfig/v1alpha1 - kind: AWSClusterProviderConfig - clusterId: TestClusterManifest-VpcName - clusterVersionRef: - namespace: test - name: test - hardware: - aws: - region: TestClusterManifest-Region - keyPairName: TestClusterManifest-SshKey - defaultHardwareSpec: - aws: - instanceType: m4.large - machineSets: - - nodeType: Master - size: 1 - - shortName: infra - nodeType: Compute - infra: true - size: 1 - - shortName: compute - nodeType: Compute - size: 1`) + - "10.0.0.2/24" + serviceDomain: unused +`) } -func TestMachineSetManifest(t *testing.T) { +func TestMachineSetAWSManifest(t *testing.T) { config := OperatorConfig{ - VpcName: "TestMachineSetManifest-VpcName", - SshKey: "TestMachineSetManifest-SshKey", - ClusterName: "TestMachineSetManifest-ClusterName", - ClusterDomain: "TestMachineSetManifest.ClusterDomain", // TODO(frobware) - currently not a template value - Region: "TestMachineSetManifest-Region", - Image: "TestMachineSetManifest-Image", + Provider: "aws", + AWS: &awsConfig{ + ClusterName: "TestClusterManifest-ClusterName", + ClusterID: "TestClusterManifest-ClusterID", + Region: "TestClusterManifest-Region", + AvailabilityZone: "TestClusterManifest-AvailabilityZone", + Image: "TestClusterManifest-Image", + Replicas: "TestClusterManifest-Replicas", + }, } - testRenderManifest(t, "../../machines/machine-set.yaml", &config, ` + testRenderManifest(t, "../../machines/aws/machine-set.yaml", &config, ` +--- apiVersion: cluster.k8s.io/v1alpha1 kind: MachineSet metadata: name: worker - namespace: test + namespace: default labels: - machineapioperator.openshift.io/cluster: test + sigs.k8s.io/cluster-api-cluster: TestClusterManifest-ClusterName + sigs.k8s.io/cluster-api-machine-role: worker + sigs.k8s.io/cluster-api-machine-type: worker spec: - replicas: 3 + replicas: TestClusterManifest-Replicas selector: matchLabels: - machineapioperator.openshift.io/machineset: worker - machineapioperator.openshift.io/cluster: test + sigs.k8s.io/cluster-api-machineset: worker + sigs.k8s.io/cluster-api-cluster: TestClusterManifest-ClusterName template: metadata: labels: - machineapioperator.openshift.io/machineset: worker - machineapioperator.openshift.io/cluster: test + sigs.k8s.io/cluster-api-machineset: worker + sigs.k8s.io/cluster-api-cluster: TestClusterManifest-ClusterName + sigs.k8s.io/cluster-api-machine-role: worker + sigs.k8s.io/cluster-api-machine-type: worker spec: providerConfig: value: - apiVersion: awsproviderconfig/v1alpha1 + apiVersion: aws.cluster.k8s.io/v1alpha1 kind: AWSMachineProviderConfig - clusterId: TestMachineSetManifest-VpcName - clusterHardware: - aws: - keyPairName: TestMachineSetManifest-SshKey - region: TestMachineSetManifest-Region - hardware: - aws: - instanceType: m4.large - infra: false - vmImage: - awsImage: TestMachineSetManifest-Image + ami: + id: TestClusterManifest-Image + instanceType: m4.large + placement: + region: TestClusterManifest-Region + availabilityZone: TestClusterManifest-AvailabilityZone + subnet: + filters: + - name: "tag:Name" + values: + - TestClusterManifest-ClusterName-worker-TestClusterManifest-AvailabilityZone + publicIp: true + iamInstanceProfile: + id: TestClusterManifest-ClusterName-master-profile + keyName: tectonic + tags: + - name: tectonicClusterID + value: TestClusterManifest-ClusterID + securityGroups: + - filters: + - name: "tag:Name" + values: + - TestClusterManifest-ClusterName_worker_sg + userDataSecret: + name: ignition-worker + versions: + kubelet: "" + controlPlane: ""`) +} + +func TestMachineSetLibvirtManifest(t *testing.T) { + config := OperatorConfig{ + Provider: "libvirt", + Libvirt: &libvirtConfig{ + URI: "qemu+tcp://host_private_ip/system", + Replicas: "2", + ClusterName: "test", + }, + } + + testRenderManifest(t, "../../machines/libvirt/machine-set.yaml", &config, ` +--- +apiVersion: cluster.k8s.io/v1alpha1 +kind: MachineSet +metadata: + name: worker + namespace: default + labels: + sigs.k8s.io/cluster-api-cluster: test + sigs.k8s.io/cluster-api-machine-role: worker + sigs.k8s.io/cluster-api-machine-type: worker +spec: + replicas: 2 + selector: + matchLabels: + sigs.k8s.io/cluster-api-machineset: worker + sigs.k8s.io/cluster-api-cluster: test + sigs.k8s.io/cluster-api-machine-role: worker + sigs.k8s.io/cluster-api-machine-type: worker + template: + metadata: + labels: + sigs.k8s.io/cluster-api-machineset: worker + sigs.k8s.io/cluster-api-cluster: test + sigs.k8s.io/cluster-api-machine-role: infra + sigs.k8s.io/cluster-api-machine-type: worker + spec: + providerConfig: + value: + apiVersion: libvirtproviderconfig/v1alpha1 + kind: LibvirtMachineProviderConfig + domainMemory: 2048 + domainVcpu: 2 + ignKey: /var/lib/libvirt/images/worker.ign + volume: + poolName: default + baseVolumeID: /var/lib/libvirt/images/coreos_base + networkInterfaceName: tectonic + networkInterfaceAddress: 192.168.124.12 + autostart: false + uri: qemu+tcp://host_private_ip/system versions: - kubelet: 0.0.0 - controlPlane: 0.0.0 - roles: - - Master`) + kubelet: "" + controlPlane: ""`) +} + +func TestClusterapiControllerManifest(t *testing.T) { + config := OperatorConfig{ + Provider: "libvirt", + Libvirt: &libvirtConfig{ + URI: "qemu+tcp://host_private_ip/system", + Replicas: "2", + ClusterName: "test", + }, + } + + testRenderManifest(t, "../../manifests/clusterapi-controller.yaml", &config, ` +apiVersion: apps/v1beta1 +kind: Deployment +metadata: + name: clusterapi-controllers + namespace: kube-system + labels: + api: clusterapi + k8s-app: controller + tectonic-operators.coreos.com/managed-by: machine-api-operator +spec: + securityContext: + runAsNonRoot: true + runAsUser: 65534 + selector: + matchLabels: + api: clusterapi + k8s-app: controller + replicas: 1 + template: + metadata: + labels: + api: clusterapi + k8s-app: controller + spec: + nodeSelector: + node-role.kubernetes.io/master: "" + tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/master + - key: CriticalAddonsOnly + operator: Exists + - effect: NoExecute + key: node.alpha.kubernetes.io/notReady + operator: Exists + - effect: NoExecute + key: node.alpha.kubernetes.io/unreachable + operator: Exists + containers: + - name: controller-manager + image: gcr.io/k8s-cluster-api/controller-manager:0.0.7 + command: + - "./controller-manager" + resources: + requests: + cpu: 100m + memory: 20Mi + limits: + cpu: 100m + memory: 30Mi + - name: libvirt-machine-controller + image: quay.io/alberto_lamela/libvirt-machine-controller:0.0.1-dev # TODO: move this to openshift org + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + command: + - /machine-controller + args: + - --log-level=debug + resources: + requests: + cpu: 100m + memory: 20Mi + limits: + cpu: 100m + memory: 30Mi`) }