diff --git a/cmd/machine-config-operator/start.go b/cmd/machine-config-operator/start.go index 5e12eff7b1..35b92ea97a 100644 --- a/cmd/machine-config-operator/start.go +++ b/cmd/machine-config-operator/start.go @@ -92,6 +92,7 @@ func startControllers(ctx *common.ControllerContext) error { ctx.KubeNamespacedInformerFactory.Apps().V1().DaemonSets(), ctx.KubeNamespacedInformerFactory.Rbac().V1().ClusterRoles(), ctx.KubeNamespacedInformerFactory.Rbac().V1().ClusterRoleBindings(), + ctx.KubeNamespacedInformerFactory.Core().V1().ConfigMaps(), ctx.ClientBuilder.MachineConfigClientOrDie(componentName), ctx.ClientBuilder.KubeClientOrDie(componentName), ctx.ClientBuilder.APIExtClientOrDie(componentName), diff --git a/install/0000_50_machine-config-operator_05_osimageurl.yaml b/install/0000_50_machine-config-operator_05_osimageurl.yaml new file mode 100644 index 0000000000..55043d99d6 --- /dev/null +++ b/install/0000_50_machine-config-operator_05_osimageurl.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: machine-config-osimageurl + namespace: openshift-machine-config-operator +data: + # The OS payload, managed by the daemon + pivot + rpm-ostree + # https://github.com/openshift/machine-config-operator/issues/183 + osImageURL: "registry.svc.ci.openshift.org/rhcos/maipo@sha256:61dc83d62cfb5054c4c5532bd2478742a0711075ef5151572e63f94babeacc1a" diff --git a/install/image-references b/install/image-references index ddb6527a69..5db5e0adf8 100644 --- a/install/image-references +++ b/install/image-references @@ -2,6 +2,7 @@ kind: ImageStream apiVersion: image.openshift.io/v1 spec: tags: + # These are the 4 components of the MCO - name: machine-config-operator from: kind: DockerImage @@ -18,3 +19,10 @@ spec: from: kind: DockerImage name: docker.io/openshift/origin-machine-config-daemon:v4.0.0 + # This one is special, it's the OS payload + # https://github.com/openshift/machine-config-operator/issues/183 + # See the machine-config-osimageurl configmap. + - name: machine-os-content + from: + kind: DockerImage + name: registry.svc.ci.openshift.org/rhcos/maipo@sha256:61dc83d62cfb5054c4c5532bd2478742a0711075ef5151572e63f94babeacc1a diff --git a/lib/resourcemerge/machineconfig.go b/lib/resourcemerge/machineconfig.go index e113208b07..f809658488 100644 --- a/lib/resourcemerge/machineconfig.go +++ b/lib/resourcemerge/machineconfig.go @@ -58,6 +58,7 @@ func ensureControllerConfigSpec(modified *bool, existing *mcfgv1.ControllerConfi setStringIfSet(modified, &existing.Platform, required.Platform) setStringIfSet(modified, &existing.BaseDomain, required.BaseDomain) setStringIfSet(modified, &existing.SSHKey, required.SSHKey) + setStringIfSet(modified, &existing.OSImageURL, required.OSImageURL) setBytesIfSet(modified, &existing.EtcdCAData, required.EtcdCAData) setBytesIfSet(modified, &existing.RootCAData, required.RootCAData) diff --git a/pkg/apis/machineconfiguration.openshift.io/v1/types.go b/pkg/apis/machineconfiguration.openshift.io/v1/types.go index 6cc4068129..aa13fdf0fd 100644 --- a/pkg/apis/machineconfiguration.openshift.io/v1/types.go +++ b/pkg/apis/machineconfiguration.openshift.io/v1/types.go @@ -136,6 +136,9 @@ type ControllerConfigSpec struct { // Public SSH SSHKey string `json:"sshKey"` + + // Sourced from configmap/machine-config-osimageurl + OSImageURL string `json:"osImageURL` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/pkg/operator/bootstrap.go b/pkg/operator/bootstrap.go index 9f1131eb23..36ec04a827 100644 --- a/pkg/operator/bootstrap.go +++ b/pkg/operator/bootstrap.go @@ -42,7 +42,7 @@ func RenderBootstrap( return fmt.Errorf("error discovering MCOConfig from %q: %v", clusterConfigConfigMapFile, err) } - config := getRenderConfig(mcoconfig, filesData[etcdCAFile], filesData[rootCAFile], nil, imgs) + config := getRenderConfig(mcoconfig, filesData[etcdCAFile], filesData[rootCAFile], nil, imgs, "") manifests := []struct { name string diff --git a/pkg/operator/operator.go b/pkg/operator/operator.go index 2b1448bb04..e4d52422eb 100644 --- a/pkg/operator/operator.go +++ b/pkg/operator/operator.go @@ -24,6 +24,7 @@ import ( "k8s.io/client-go/kubernetes" coreclientsetv1 "k8s.io/client-go/kubernetes/typed/core/v1" appslisterv1 "k8s.io/client-go/listers/apps/v1" + corelisterv1 "k8s.io/client-go/listers/core/v1" "k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/record" "k8s.io/client-go/util/workqueue" @@ -45,6 +46,9 @@ const ( // // 5ms, 10ms, 20ms, 40ms, 80ms, 160ms, 320ms, 640ms, 1.3s, 2.6s, 5.1s, 10.2s, 20.4s, 41s, 82s maxRetries = 15 + + // osImageConfigMapName is the name of our configmap for the osImageURL + osImageConfigMapName = "machine-config-osimageurl" ) // Operator defines machince config operator. @@ -67,11 +71,13 @@ type Operator struct { mcLister mcfglistersv1.MachineConfigLister deployLister appslisterv1.DeploymentLister daemonsetLister appslisterv1.DaemonSetLister + cmLister corelisterv1.ConfigMapLister crdListerSynced cache.InformerSynced mcoconfigListerSynced cache.InformerSynced deployListerSynced cache.InformerSynced daemonsetListerSynced cache.InformerSynced + cmListerSynced cache.InformerSynced // queue only ever has one item, but it has nice error handling backoff/retry semantics queue workqueue.RateLimitingInterface @@ -91,6 +97,7 @@ func New( daemonsetInformer appsinformersv1.DaemonSetInformer, clusterRoleInformer rbacinformersv1.ClusterRoleInformer, clusterRoleBindingInformer rbacinformersv1.ClusterRoleBindingInformer, + cmInformer coreinformersv1.ConfigMapInformer, client mcfgclientset.Interface, kubeClient kubernetes.Interface, apiExtClient apiextclientset.Interface, @@ -120,6 +127,7 @@ func New( daemonsetInformer.Informer().AddEventHandler(optr.eventHandler()) clusterRoleInformer.Informer().AddEventHandler(optr.eventHandler()) clusterRoleBindingInformer.Informer().AddEventHandler(optr.eventHandler()) + cmInformer.Informer().AddEventHandler(optr.eventHandler()) optr.syncHandler = optr.sync @@ -133,6 +141,8 @@ func New( optr.deployListerSynced = deployInformer.Informer().HasSynced optr.daemonsetLister = daemonsetInformer.Lister() optr.daemonsetListerSynced = daemonsetInformer.Informer().HasSynced + optr.cmLister = cmInformer.Lister() + optr.cmListerSynced = cmInformer.Informer().HasSynced return optr } @@ -149,6 +159,7 @@ func (optr *Operator) Run(workers int, stopCh <-chan struct{}) { optr.crdListerSynced, optr.mcoconfigListerSynced, optr.deployListerSynced, + optr.cmListerSynced, optr.daemonsetListerSynced) { glog.Error("failed to sync caches") return @@ -255,10 +266,24 @@ func (optr *Operator) sync(key string) error { return err } - rc := getRenderConfig(mcoconfig, etcdCA, rootCA, &v1.ObjectReference{Namespace: "kube-system", Name: "coreos-pull-secret"}, imgs) + osimageurl, err := optr.getOsImageURL(namespace) + glog.Infof("using osimageurl: %s", osimageurl) + if err != nil { + return err + } + + rc := getRenderConfig(mcoconfig, etcdCA, rootCA, &v1.ObjectReference{Namespace: "kube-system", Name: "coreos-pull-secret"}, imgs, osimageurl) return optr.syncAll(rc) } +func (optr *Operator) getOsImageURL(namespace string) (string, error) { + cm, err := optr.kubeClient.CoreV1().ConfigMaps(namespace).Get(osImageConfigMapName, metav1.GetOptions{}) + if err != nil { + return "", err + } + return cm.Data["osImageURL"], nil +} + func (optr *Operator) getCAsFromConfigMap(namespace, name, key string) ([]byte, error) { cm, err := optr.kubeClient.CoreV1().ConfigMaps(namespace).Get(name, metav1.GetOptions{}) if err != nil { @@ -307,7 +332,7 @@ func icFromClusterConfig(cm *v1.ConfigMap) (installertypes.InstallConfig, error) return ic, nil } -func getRenderConfig(mc *mcfgv1.MCOConfig, etcdCAData, rootCAData []byte, ps *v1.ObjectReference, imgs Images) renderConfig { +func getRenderConfig(mc *mcfgv1.MCOConfig, etcdCAData, rootCAData []byte, ps *v1.ObjectReference, imgs Images, osimageurl string) renderConfig { controllerconfig := mcfgv1.ControllerConfigSpec{ ClusterDNSIP: mc.Spec.ClusterDNSIP, CloudProviderConfig: mc.Spec.CloudProviderConfig, @@ -318,6 +343,7 @@ func getRenderConfig(mc *mcfgv1.MCOConfig, etcdCAData, rootCAData []byte, ps *v1 RootCAData: rootCAData, PullSecret: ps, SSHKey: mc.Spec.SSHKey, + OSImageURL: osimageurl, } return renderConfig{ TargetNamespace: mc.GetNamespace(),