diff --git a/cmd/openshift-install/create.go b/cmd/openshift-install/create.go index c5349128525..07d8e89f0a6 100644 --- a/cmd/openshift-install/create.go +++ b/cmd/openshift-install/create.go @@ -26,15 +26,8 @@ import ( configclient "github.com/openshift/client-go/config/clientset/versioned" routeclient "github.com/openshift/client-go/route/clientset/versioned" "github.com/openshift/installer/pkg/asset" - "github.com/openshift/installer/pkg/asset/cluster" - "github.com/openshift/installer/pkg/asset/ignition/bootstrap" - "github.com/openshift/installer/pkg/asset/ignition/machine" - "github.com/openshift/installer/pkg/asset/installconfig" - "github.com/openshift/installer/pkg/asset/kubeconfig" - "github.com/openshift/installer/pkg/asset/manifests" assetstore "github.com/openshift/installer/pkg/asset/store" - "github.com/openshift/installer/pkg/asset/templates" - "github.com/openshift/installer/pkg/asset/tls" + targetassets "github.com/openshift/installer/pkg/asset/targets" destroybootstrap "github.com/openshift/installer/pkg/destroy/bootstrap" cov1helpers "github.com/openshift/library-go/pkg/config/clusteroperator/v1helpers" ) @@ -56,7 +49,7 @@ var ( // FIXME: add longer descriptions for our commands with examples for better UX. // Long: "", }, - assets: []asset.WritableAsset{&installconfig.InstallConfig{}}, + assets: targetassets.InstallConfig, } manifestsTarget = target{ @@ -67,7 +60,7 @@ var ( // FIXME: add longer descriptions for our commands with examples for better UX. // Long: "", }, - assets: []asset.WritableAsset{&manifests.Manifests{}, &manifests.Openshift{}}, + assets: targetassets.Manifests, } manifestTemplatesTarget = target{ @@ -77,7 +70,7 @@ var ( Short: "Generates the unrendered Kubernetes manifest templates", Long: "", }, - assets: templates.Templates, + assets: targetassets.ManifestTemplates, } ignitionConfigsTarget = target{ @@ -88,7 +81,7 @@ var ( // FIXME: add longer descriptions for our commands with examples for better UX. // Long: "", }, - assets: []asset.WritableAsset{&bootstrap.Bootstrap{}, &machine.Master{}, &machine.Worker{}, &kubeconfig.Admin{}, &cluster.Metadata{}}, + assets: targetassets.IgnitionConfigs, } clusterTarget = target{ @@ -129,7 +122,7 @@ var ( } }, }, - assets: []asset.WritableAsset{&cluster.TerraformVariables{}, &kubeconfig.Admin{}, &tls.JournalCertKey{}, &cluster.Metadata{}, &cluster.Cluster{}}, + assets: targetassets.Cluster, } targets = []target{installConfigTarget, manifestTemplatesTarget, manifestsTarget, ignitionConfigsTarget, clusterTarget} diff --git a/pkg/asset/machines/master.go b/pkg/asset/machines/master.go index 08d3f376d34..609f53e67ef 100644 --- a/pkg/asset/machines/master.go +++ b/pkg/asset/machines/master.go @@ -111,6 +111,10 @@ func (m *Master) Generate(dependencies asset.Parents) error { } m.MachinesRaw = raw case nonetypes.Name: + // This is needed to ensure that roundtrip generate-load tests pass when + // comparing this value. Otherwise, generate will use a nil value while + // load will use an empty byte slice. + m.MachinesRaw = []byte{} case openstacktypes.Name: mpool := defaultOpenStackMachinePoolPlatform(ic.Platform.OpenStack.FlavorName) mpool.Set(ic.Platform.OpenStack.DefaultMachinePlatform) diff --git a/pkg/asset/machines/worker.go b/pkg/asset/machines/worker.go index d73ec0ba3be..fc0c612d42b 100644 --- a/pkg/asset/machines/worker.go +++ b/pkg/asset/machines/worker.go @@ -131,6 +131,10 @@ func (w *Worker) Generate(dependencies asset.Parents) error { } w.MachineSetRaw = raw case nonetypes.Name: + // This is needed to ensure that roundtrip generate-load tests pass when + // comparing this value. Otherwise, generate will use a nil value while + // load will use an empty byte slice. + w.MachineSetRaw = []byte{} case openstacktypes.Name: mpool := defaultOpenStackMachinePoolPlatform(ic.Platform.OpenStack.FlavorName) mpool.Set(ic.Platform.OpenStack.DefaultMachinePlatform) diff --git a/pkg/asset/store/assetcreate_test.go b/pkg/asset/store/assetcreate_test.go new file mode 100644 index 00000000000..795cc7e6f15 --- /dev/null +++ b/pkg/asset/store/assetcreate_test.go @@ -0,0 +1,113 @@ +package store + +import ( + "io/ioutil" + "os" + "path/filepath" + "reflect" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/openshift/installer/pkg/asset" + "github.com/openshift/installer/pkg/asset/targets" +) + +const userProvidedAssets = `{ + "*installconfig.baseDomain": { + "BaseDomain": "test-domain" + }, + "*installconfig.clusterID": { + "ClusterID": "test-cluster-id" + }, + "*installconfig.clusterName": { + "ClusterName": "test-cluster" + }, + "*installconfig.platform": { + "none": {} + }, + "*installconfig.pullSecret": { + "PullSecret": "{\"auths\": {\"example.com\": {\"auth\": \"test-auth\"}}}\n" + }, + "*installconfig.sshPublicKey": {} +}` + +func TestCreatedAssetsAreNotDirty(t *testing.T) { + cases := []struct { + name string + targets []asset.WritableAsset + }{ + { + name: "install config", + targets: targets.InstallConfig, + }, + { + name: "manifest templates", + targets: targets.ManifestTemplates, + }, + { + name: "manifests", + targets: targets.Manifests, + }, + { + name: "ignition configs", + targets: targets.IgnitionConfigs, + }, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + tempDir, err := ioutil.TempDir("", "TestCreatedAssetsAreNotDirty") + if err != nil { + t.Fatalf("could not create the temp dir: %v", err) + } + defer os.RemoveAll(tempDir) + + if err := ioutil.WriteFile(filepath.Join(tempDir, stateFileName), []byte(userProvidedAssets), 0666); err != nil { + t.Fatalf("could not write the state file: %v", err) + } + + assetStore, err := newStore(tempDir) + if err != nil { + t.Fatalf("failed to create asset store: %v", err) + } + + for _, a := range tc.targets { + if err := assetStore.Fetch(a); err != nil { + t.Fatalf("failed to fetch %q: %v", a.Name(), err) + } + + if err := asset.PersistToFile(a, tempDir); err != nil { + t.Fatalf("failed to write asset %q to disk: %v", a.Name(), err) + } + } + + newAssetStore, err := newStore(tempDir) + if err != nil { + t.Fatalf("failed to create new asset store: %v", err) + } + + for _, a := range tc.targets { + newAsset := reflect.New(reflect.TypeOf(a).Elem()).Interface().(asset.WritableAsset) + if err := newAssetStore.Fetch(newAsset); err != nil { + t.Fatalf("failed to fetch %q in new store: %v", a.Name(), err) + } + assetState := newAssetStore.assets[reflect.TypeOf(a)] + // Make an exception for metadata. It's files are read-only. + if a.Name() != "Metadata" { + assert.Truef(t, assetState.presentOnDisk, "asset %q was not found on disk", a.Name()) + } + } + + assert.Equal(t, len(assetStore.assets), len(newAssetStore.assets), "new asset store does not have the same number of assets as original") + + for _, a := range newAssetStore.assets { + originalAssetState, ok := assetStore.assets[reflect.TypeOf(a.asset)] + if !ok { + t.Fatalf("asset %q not found in original store", a.asset.Name()) + } + assert.Equalf(t, originalAssetState.asset, a.asset, "fetched and generated asset %q are not equal", a.asset.Name()) + assert.Equalf(t, stateFileSource, a.source, "asset %q was not fetched from the state file", a.asset.Name()) + } + }) + } +} diff --git a/pkg/asset/targets/targets.go b/pkg/asset/targets/targets.go new file mode 100644 index 00000000000..029ae6fe05e --- /dev/null +++ b/pkg/asset/targets/targets.go @@ -0,0 +1,67 @@ +package targets + +import ( + "github.com/openshift/installer/pkg/asset" + "github.com/openshift/installer/pkg/asset/cluster" + "github.com/openshift/installer/pkg/asset/ignition/bootstrap" + "github.com/openshift/installer/pkg/asset/ignition/machine" + "github.com/openshift/installer/pkg/asset/installconfig" + "github.com/openshift/installer/pkg/asset/kubeconfig" + "github.com/openshift/installer/pkg/asset/manifests" + "github.com/openshift/installer/pkg/asset/templates/content/bootkube" + "github.com/openshift/installer/pkg/asset/templates/content/openshift" + "github.com/openshift/installer/pkg/asset/tls" +) + +var ( + // InstallConfig are the install-config targeted assets. + InstallConfig = []asset.WritableAsset{ + &installconfig.InstallConfig{}, + } + + // Manifests are the manifests targeted assets. + Manifests = []asset.WritableAsset{ + &manifests.Manifests{}, + &manifests.Openshift{}, + } + + // ManifestTemplates are the manifest-templates targeted assets. + ManifestTemplates = []asset.WritableAsset{ + &bootkube.KubeCloudConfig{}, + &bootkube.MachineConfigServerTLSSecret{}, + &bootkube.OpenshiftServiceCertSignerSecret{}, + &bootkube.Pull{}, + &bootkube.CVOOverrides{}, + &bootkube.HostEtcdServiceEndpointsKubeSystem{}, + &bootkube.KubeSystemConfigmapEtcdServingCA{}, + &bootkube.KubeSystemConfigmapRootCA{}, + &bootkube.KubeSystemSecretEtcdClient{}, + &bootkube.OpenshiftMachineConfigOperator{}, + &bootkube.OpenshiftClusterAPINamespace{}, + &bootkube.OpenshiftServiceCertSignerNamespace{}, + &bootkube.EtcdServiceKubeSystem{}, + &bootkube.HostEtcdServiceKubeSystem{}, + &openshift.BindingDiscovery{}, + &openshift.CloudCredsSecret{}, + &openshift.KubeadminPasswordSecret{}, + &openshift.RoleCloudCredsSecretReader{}, + } + + // IgnitionConfigs are the ignition-configs targeted assets. + IgnitionConfigs = []asset.WritableAsset{ + &kubeconfig.Admin{}, + &machine.Master{}, + &machine.Worker{}, + &bootstrap.Bootstrap{}, + &cluster.Metadata{}, + } + + // Cluster are the cluster targeted assets. + Cluster = []asset.WritableAsset{ + &cluster.TerraformVariables{}, + &kubeconfig.Admin{}, + &tls.JournalCertKey{}, + &cluster.Cluster{}, + &cluster.Metadata{}, + } +) diff --git a/pkg/asset/templates/doc.go b/pkg/asset/templates/doc.go new file mode 100644 index 00000000000..2b53be5baf1 --- /dev/null +++ b/pkg/asset/templates/doc.go @@ -0,0 +1,2 @@ +// Package templates deals with creating template assets that will be used by other assets +package templates diff --git a/pkg/asset/templates/templates.go b/pkg/asset/templates/templates.go deleted file mode 100644 index 7821855b8b5..00000000000 --- a/pkg/asset/templates/templates.go +++ /dev/null @@ -1,33 +0,0 @@ -// Package templates deals with creating template assets that will be used by other assets -package templates - -import ( - "github.com/openshift/installer/pkg/asset" - "github.com/openshift/installer/pkg/asset/templates/content/bootkube" - "github.com/openshift/installer/pkg/asset/templates/content/openshift" -) - -// Templates are the targeted assets for generating the dependent unrendered -// template files. -var Templates = []asset.WritableAsset{ - &bootkube.KubeCloudConfig{}, - &bootkube.MachineConfigServerTLSSecret{}, - &bootkube.OpenshiftServiceCertSignerSecret{}, - &bootkube.Pull{}, - &bootkube.CVOOverrides{}, - &bootkube.HostEtcdServiceEndpointsKubeSystem{}, - &bootkube.KubeSystemConfigmapEtcdServingCA{}, - &bootkube.KubeSystemConfigmapRootCA{}, - &bootkube.KubeSystemSecretEtcdClient{}, - &bootkube.OpenshiftMachineConfigOperator{}, - &bootkube.OpenshiftClusterAPINamespace{}, - &bootkube.OpenshiftServiceCertSignerNamespace{}, - &bootkube.EtcdServiceKubeSystem{}, - &bootkube.HostEtcdServiceKubeSystem{}, - &openshift.BindingDiscovery{}, - &openshift.CloudCredsSecret{}, - &openshift.KubeadminPasswordSecret{}, - &openshift.RoleCloudCredsSecretReader{}, - &openshift.InfrastructureCRD{}, - &openshift.NetworkCRDs{}, -}