Skip to content

Commit

Permalink
Merge pull request #2827 from zaneb/manage-user-data
Browse files Browse the repository at this point in the history
Manage user data
  • Loading branch information
openshift-merge-robot authored Dec 8, 2021
2 parents 2cca448 + 59f1381 commit b50080b
Show file tree
Hide file tree
Showing 9 changed files with 243 additions and 45 deletions.
2 changes: 2 additions & 0 deletions cmd/machine-config-operator/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ func runStartCmd(cmd *cobra.Command, args []string) {
ctrlctx.ClientBuilder.ConfigClientOrDie(componentName),
ctrlctx.OpenShiftKubeAPIServerKubeNamespacedInformerFactory.Core().V1().ConfigMaps(),
ctrlctx.KubeInformerFactory.Core().V1().Nodes(),
ctrlctx.KubeMAOSharedInformer.Core().V1().Secrets(),
)

ctrlctx.NamespacedInformerFactory.Start(ctrlctx.Stop)
Expand All @@ -85,6 +86,7 @@ func runStartCmd(cmd *cobra.Command, args []string) {
ctrlctx.ConfigInformerFactory.Start(ctrlctx.Stop)
ctrlctx.OpenShiftKubeAPIServerKubeNamespacedInformerFactory.Start(ctrlctx.Stop)
ctrlctx.OperatorInformerFactory.Start(ctrlctx.Stop)
ctrlctx.KubeMAOSharedInformer.Start(ctrlctx.Stop)
close(ctrlctx.InformersStarted)

go controller.Run(2, ctrlctx.Stop)
Expand Down
9 changes: 9 additions & 0 deletions manifests/userdata_secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: v1
kind: Secret
metadata:
name: {{.Role}}-user-data-managed
namespace: openshift-machine-api
type: Opaque
data:
disableTemplating: "dHJ1ZQo="
userData: {{.PointerConfig}}
4 changes: 4 additions & 0 deletions pkg/controller/common/controller_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ type ControllerContext struct {
APIExtInformerFactory apiextinformers.SharedInformerFactory
ConfigInformerFactory configinformers.SharedInformerFactory
OperatorInformerFactory operatorinformers.SharedInformerFactory
KubeMAOSharedInformer informers.SharedInformerFactory

AvailableResources map[schema.GroupVersionResource]bool

Expand Down Expand Up @@ -74,6 +75,8 @@ func CreateControllerContext(cb *clients.Builder, stop <-chan struct{}, targetNa
opt.FieldSelector = fields.OneTermEqualSelector("metadata.name", "kube-apiserver-to-kubelet-client-ca").String()
},
)
// this is needed to listen for changes in MAO user data secrets to re-apply the ones we define in the MCO (since we manage them)
kubeMAOSharedInformer := informers.NewFilteredSharedInformerFactory(kubeClient, resyncPeriod()(), "openshift-machine-api", nil)

// filter out CRDs that do not have the MCO label
assignFilterLabels := func(opts *metav1.ListOptions) {
Expand Down Expand Up @@ -103,5 +106,6 @@ func CreateControllerContext(cb *clients.Builder, stop <-chan struct{}, targetNa
Stop: stop,
InformersStarted: make(chan struct{}),
ResyncPeriod: resyncPeriod(),
KubeMAOSharedInformer: kubeMAOSharedInformer,
}
}
36 changes: 36 additions & 0 deletions pkg/controller/common/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"io/ioutil"
"net/url"
"reflect"
"sort"

Expand All @@ -29,6 +30,7 @@ import (
"github.com/ghodss/yaml"
"github.com/golang/glog"
"github.com/pkg/errors"
"github.com/vincent-petithory/dataurl"
kerr "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
Expand Down Expand Up @@ -131,6 +133,40 @@ func MergeMachineConfigs(configs []*mcfgv1.MachineConfig, osImageURL string) (*m
}, nil
}

// PointerConfig generates the stub ignition for the machine to boot properly
// NOTE: If you change this, you also need to change the pointer configuration in openshift/installer, see
// https://github.com/openshift/installer/blob/master/pkg/asset/ignition/machine/node.go#L20
func PointerConfig(ignitionHost string, rootCA []byte) (ign3types.Config, error) {
configSourceURL := &url.URL{
Scheme: "https",
Host: ignitionHost,
Path: "/config/{{.Role}}",
}
// we do decoding here as curly brackets are escaped to %7B and breaks golang's templates
ignitionHostTmpl, err := url.QueryUnescape(configSourceURL.String())
if err != nil {
return ign3types.Config{}, err
}
CASource := dataurl.EncodeBytes(rootCA)
return ign3types.Config{
Ignition: ign3types.Ignition{
Version: ign3types.MaxVersion.String(),
Config: ign3types.IgnitionConfig{
Merge: []ign3types.Resource{{
Source: &ignitionHostTmpl,
}},
},
Security: ign3types.Security{
TLS: ign3types.TLS{
CertificateAuthorities: []ign3types.Resource{{
Source: &CASource,
}},
},
},
},
}, nil
}

// NewIgnConfig returns an empty ignition config with version set as latest version
func NewIgnConfig() ign3types.Config {
return ign3types.Config{
Expand Down
98 changes: 64 additions & 34 deletions pkg/operator/assets/bindata.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pkg/operator/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ func RenderBootstrap(
templatectrl.BaremetalRuntimeCfgKey: imgs.BaremetalRuntimeCfg,
}

config := getRenderConfig("", string(filesData[kubeAPIServerServingCA]), spec, &imgs.RenderConfigImages, infra.Status.APIServerInternalURL)
config := getRenderConfig("", string(filesData[kubeAPIServerServingCA]), spec, &imgs.RenderConfigImages, infra.Status.APIServerInternalURL, nil)

manifests := []manifest{
{
Expand Down
5 changes: 5 additions & 0 deletions pkg/operator/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ type Operator struct {
oseKubeAPIListerSynced cache.InformerSynced
nodeListerSynced cache.InformerSynced
dnsListerSynced cache.InformerSynced
maoSecretInformerSynced cache.InformerSynced

// queue only ever has one item, but it has nice error handling backoff/retry semantics
queue workqueue.RateLimitingInterface
Expand Down Expand Up @@ -134,6 +135,7 @@ func New(
configClient configclientset.Interface,
oseKubeAPIInformer coreinformersv1.ConfigMapInformer,
nodeInformer coreinformersv1.NodeInformer,
maoSecretInformer coreinformersv1.SecretInformer,
) *Operator {
eventBroadcaster := record.NewBroadcaster()
eventBroadcaster.StartLogging(glog.Infof)
Expand Down Expand Up @@ -168,6 +170,7 @@ func New(
oseKubeAPIInformer.Informer(),
nodeInformer.Informer(),
dnsInformer.Informer(),
maoSecretInformer.Informer(),
} {
i.AddEventHandler(optr.eventHandler())
}
Expand All @@ -189,6 +192,7 @@ func New(
optr.nodeLister = nodeInformer.Lister()
optr.nodeListerSynced = nodeInformer.Informer().HasSynced

optr.maoSecretInformerSynced = maoSecretInformer.Informer().HasSynced
optr.serviceAccountInformerSynced = serviceAccountInfomer.Informer().HasSynced
optr.clusterRoleInformerSynced = clusterRoleInformer.Informer().HasSynced
optr.clusterRoleBindingInformerSynced = clusterRoleBindingInformer.Informer().HasSynced
Expand Down Expand Up @@ -237,6 +241,7 @@ func (optr *Operator) Run(workers int, stopCh <-chan struct{}) {
optr.clusterCmListerSynced,
optr.serviceAccountInformerSynced,
optr.clusterRoleInformerSynced,
optr.maoSecretInformerSynced,
optr.clusterRoleBindingInformerSynced,
optr.networkListerSynced,
optr.proxyListerSynced,
Expand Down
49 changes: 41 additions & 8 deletions pkg/operator/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,28 +31,46 @@ type renderConfig struct {
KubeAPIServerServingCA string
Infra configv1.Infrastructure
Constants map[string]string
PointerConfig string
}

func renderAsset(config *renderConfig, path string) ([]byte, error) {
objBytes, err := manifests.ReadFile(path)
type assetRenderer struct {
Path string
tmpl *template.Template
templateData string
}

func newAssetRenderer(path string) *assetRenderer {
return &assetRenderer{
Path: path,
tmpl: template.New(path),
}
}

func (a *assetRenderer) read() error {
objBytes, err := manifests.ReadFile(a.Path)
if err != nil {
return nil, fmt.Errorf("error getting asset %s: %v", path, err)
return fmt.Errorf("error getting asset %s: %v", a.Path, err)
}
a.templateData = string(objBytes)
return nil
}

func (a *assetRenderer) addTemplateFuncs() {
funcs := sprig.TxtFuncMap()
funcs["toYAML"] = toYAML
funcs["onPremPlatformAPIServerInternalIP"] = onPremPlatformAPIServerInternalIP
funcs["onPremPlatformIngressIP"] = onPremPlatformIngressIP
funcs["onPremPlatformShortName"] = onPremPlatformShortName
funcs["onPremPlatformKeepalivedEnableUnicast"] = onPremPlatformKeepalivedEnableUnicast

if config.Constants == nil {
config.Constants = constants.ConstantsByName
}
a.tmpl = a.tmpl.Funcs(funcs)
}

tmpl, err := template.New(path).Funcs(funcs).Parse(string(objBytes))
func (a *assetRenderer) render(config interface{}) ([]byte, error) {
tmpl, err := a.tmpl.Parse(a.templateData)
if err != nil {
return nil, fmt.Errorf("failed to parse asset %s: %v", path, err)
return nil, fmt.Errorf("failed to parse asset %s: %v", a.Path, err)
}

buf := new(bytes.Buffer)
Expand All @@ -63,6 +81,21 @@ func renderAsset(config *renderConfig, path string) ([]byte, error) {
return buf.Bytes(), nil
}

func renderAsset(config *renderConfig, path string) ([]byte, error) {
asset := newAssetRenderer(path)
if err := asset.read(); err != nil {
return nil, err
}

if config.Constants == nil {
config.Constants = constants.ConstantsByName
}

asset.addTemplateFuncs()

return asset.render(config)
}

func toYAML(i interface{}) []byte {
out, err := yaml.Marshal(i)
if err != nil {
Expand Down
83 changes: 81 additions & 2 deletions pkg/operator/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import (
"encoding/pem"
"fmt"
"io/ioutil"
"net"
"net/url"
"strconv"
"strings"
"time"

Expand All @@ -29,8 +32,10 @@ import (
"github.com/openshift/machine-config-operator/lib/resourceread"
"github.com/openshift/machine-config-operator/manifests"
mcfgv1 "github.com/openshift/machine-config-operator/pkg/apis/machineconfiguration.openshift.io/v1"
ctrlcommon "github.com/openshift/machine-config-operator/pkg/controller/common"
templatectrl "github.com/openshift/machine-config-operator/pkg/controller/template"
daemonconsts "github.com/openshift/machine-config-operator/pkg/daemon/constants"
"github.com/openshift/machine-config-operator/pkg/server"
"github.com/openshift/machine-config-operator/pkg/version"
)

Expand Down Expand Up @@ -312,11 +317,51 @@ func (optr *Operator) syncRenderConfig(_ *renderConfig) error {
templatectrl.BaremetalRuntimeCfgKey: imgs.BaremetalRuntimeCfg,
}

ignitionHost, err := getIgnitionHost(&infra.Status)
if err != nil {
return err
}

pointerConfig, err := ctrlcommon.PointerConfig(ignitionHost, rootCA)
if err != nil {
return err
}
pointerConfigData, err := json.Marshal(pointerConfig)
if err != nil {
return err
}

// create renderConfig
optr.renderConfig = getRenderConfig(optr.namespace, string(kubeAPIServerServingCABytes), spec, &imgs.RenderConfigImages, infra.Status.APIServerInternalURL)
optr.renderConfig = getRenderConfig(optr.namespace, string(kubeAPIServerServingCABytes), spec, &imgs.RenderConfigImages, infra.Status.APIServerInternalURL, pointerConfigData)
return nil
}

func getIgnitionHost(infraStatus *configv1.InfrastructureStatus) (string, error) {
internalURL := infraStatus.APIServerInternalURL
internalURLParsed, err := url.Parse(internalURL)
if err != nil {
return "", err
}
securePortStr := strconv.Itoa(server.SecurePort)
ignitionHost := fmt.Sprintf("%s:%s", internalURLParsed.Hostname(), securePortStr)
if infraStatus.PlatformStatus != nil {
switch infraStatus.PlatformStatus.Type {
case configv1.BareMetalPlatformType:
ignitionHost = net.JoinHostPort(infraStatus.PlatformStatus.BareMetal.APIServerInternalIP, securePortStr)
case configv1.OpenStackPlatformType:
ignitionHost = net.JoinHostPort(infraStatus.PlatformStatus.OpenStack.APIServerInternalIP, securePortStr)
case configv1.OvirtPlatformType:
ignitionHost = net.JoinHostPort(infraStatus.PlatformStatus.Ovirt.APIServerInternalIP, securePortStr)
case configv1.VSpherePlatformType:
if infraStatus.PlatformStatus.VSphere.APIServerInternalIP != "" {
ignitionHost = net.JoinHostPort(infraStatus.PlatformStatus.VSphere.APIServerInternalIP, securePortStr)
}
}
}

return ignitionHost, nil
}

func (optr *Operator) syncCustomResourceDefinitions() error {
crds := []string{
"manifests/controllerconfig.crd.yaml",
Expand Down Expand Up @@ -360,6 +405,39 @@ func (optr *Operator) syncMachineConfigPools(config *renderConfig) error {
}
}

userDataTemplatePath := "manifests/userdata_secret.yaml"
pools, err := optr.mcpLister.List(labels.Everything())
if err != nil {
return err
}
// base64.StdEncoding.EncodeToString
for _, pool := range pools {
pointerConfigAsset := newAssetRenderer("pointer-config")
pointerConfigAsset.templateData = config.PointerConfig
pointerConfigData, err := pointerConfigAsset.render(struct{ Role string }{pool.Name})
if err != nil {
return err
}

userDataAsset := newAssetRenderer(userDataTemplatePath)
if err := userDataAsset.read(); err != nil {
return err
}
userDataAsset.addTemplateFuncs()
userdataBytes, err := userDataAsset.render(struct{ Role, PointerConfig string }{
pool.Name,
base64.StdEncoding.EncodeToString(pointerConfigData),
})
if err != nil {
return err
}
p := resourceread.ReadSecretV1OrDie(userdataBytes)
_, _, err = resourceapply.ApplySecret(optr.kubeClient.CoreV1(), p)
if err != nil {
return err
}
}

return nil
}

Expand Down Expand Up @@ -833,14 +911,15 @@ func (optr *Operator) getGlobalConfig() (*configv1.Infrastructure, *configv1.Net
return infra, network, proxy, dns, nil
}

func getRenderConfig(tnamespace, kubeAPIServerServingCA string, ccSpec *mcfgv1.ControllerConfigSpec, imgs *RenderConfigImages, apiServerURL string) *renderConfig {
func getRenderConfig(tnamespace, kubeAPIServerServingCA string, ccSpec *mcfgv1.ControllerConfigSpec, imgs *RenderConfigImages, apiServerURL string, pointerConfigData []byte) *renderConfig {
return &renderConfig{
TargetNamespace: tnamespace,
Version: version.Raw,
ControllerConfig: *ccSpec,
Images: imgs,
APIServerURL: apiServerURL,
KubeAPIServerServingCA: kubeAPIServerServingCA,
PointerConfig: string(pointerConfigData),
}
}

Expand Down

0 comments on commit b50080b

Please sign in to comment.