1
0
mirror of https://github.com/openshift/installer.git synced 2026-02-06 00:48:45 +01:00

Merge pull request #388 from rajatchopra/state_file

Save assets in a state file on disk
This commit is contained in:
OpenShift Merge Robot
2018-10-12 05:43:16 -07:00
committed by GitHub
28 changed files with 260 additions and 180 deletions

View File

@@ -57,7 +57,6 @@ func runRootCmd(cmd *cobra.Command, args []string) error {
level, err := logrus.ParseLevel(rootOpts.logLevel)
if err != nil {
return errors.Wrap(err, "invalid log-level")
}
logrus.SetLevel(level)
return nil

View File

@@ -69,6 +69,10 @@ func newTargetsCmd() []*cobra.Command {
func runTargetCmd(targets ...asset.WritableAsset) func(cmd *cobra.Command, args []string) error {
return func(cmd *cobra.Command, args []string) error {
assetStore := &asset.StoreImpl{}
err := assetStore.Load(rootOpts.dir)
if err != nil {
logrus.Errorf("Could not load assets from state file: %v", err)
}
for _, a := range targets {
err := assetStore.Fetch(a)
if err != nil {
@@ -91,6 +95,11 @@ func runTargetCmd(targets ...asset.WritableAsset) func(cmd *cobra.Command, args
return err
}
}
err = assetStore.Save(rootOpts.dir)
if err != nil {
errors.Wrapf(err, "failed to write to state file")
return err
}
return nil
}
}

View File

@@ -26,11 +26,11 @@ func (a *persistAsset) Generate(Parents) error {
type writablePersistAsset struct {
persistAsset
files []*File
FileList []*File
}
func (a *writablePersistAsset) Files() []*File {
return a.files
return a.FileList
}
func TestPersistToFile(t *testing.T) {
@@ -64,12 +64,12 @@ func TestPersistToFile(t *testing.T) {
defer os.RemoveAll(dir)
asset := &writablePersistAsset{
files: make([]*File, len(tc.filenames)),
FileList: make([]*File, len(tc.filenames)),
}
expectedFiles := map[string][]byte{}
for i, filename := range tc.filenames {
data := []byte(fmt.Sprintf("data%d", i))
asset.files[i] = &File{
asset.FileList[i] = &File{
Filename: filename,
Data: data,
}

View File

@@ -28,7 +28,7 @@ const (
// Cluster uses the terraform executable to launch a cluster
// with the given terraform tfvar and generated templates.
type Cluster struct {
files []*asset.File
FileList []*asset.File
}
var _ asset.WritableAsset = (*Cluster)(nil)
@@ -67,7 +67,7 @@ func (c *Cluster) Generate(parents asset.Parents) (err error) {
return errors.Wrap(err, "failed to write terraform.tfvars file")
}
platform := terraformVariables.platform
platform := terraformVariables.Platform
if err := data.Unpack(tmpDir, platform); err != nil {
return err
}
@@ -78,7 +78,7 @@ func (c *Cluster) Generate(parents asset.Parents) (err error) {
defer func() {
if data, err2 := json.Marshal(metadata); err2 == nil {
c.files = append(c.files, &asset.File{
c.FileList = append(c.FileList, &asset.File{
Filename: MetadataFilename,
Data: data,
})
@@ -90,7 +90,7 @@ func (c *Cluster) Generate(parents asset.Parents) (err error) {
logrus.Error(err2)
}
}
// serialize metadata and stuff it into c.files
// serialize metadata and stuff it into c.FileList
}()
switch {
@@ -135,7 +135,7 @@ func (c *Cluster) Generate(parents asset.Parents) (err error) {
data, err2 := ioutil.ReadFile(stateFile)
if err2 == nil {
c.files = append(c.files, &asset.File{
c.FileList = append(c.FileList, &asset.File{
Filename: stateFileName,
Data: data,
})
@@ -151,7 +151,7 @@ func (c *Cluster) Generate(parents asset.Parents) (err error) {
return err
}
// Files returns the files generated by the asset.
// Files returns the FileList generated by the asset.
func (c *Cluster) Files() []*asset.File {
return c.files
return c.FileList
}

View File

@@ -17,8 +17,8 @@ const (
// TerraformVariables depends on InstallConfig and
// Ignition to generate the terrafor.tfvars.
type TerraformVariables struct {
platform string
file *asset.File
Platform string
File *asset.File
}
var _ asset.WritableAsset = (*TerraformVariables)(nil)
@@ -46,7 +46,7 @@ func (t *TerraformVariables) Generate(parents asset.Parents) error {
worker := &machine.Worker{}
parents.Get(installConfig, bootstrap, master, worker)
t.platform = installConfig.Config.Platform.Name()
t.Platform = installConfig.Config.Platform.Name()
bootstrapIgn := string(bootstrap.Files()[0].Data)
@@ -62,7 +62,7 @@ func (t *TerraformVariables) Generate(parents asset.Parents) error {
if err != nil {
return errors.Wrap(err, "failed to get Tfvars")
}
t.file = &asset.File{
t.File = &asset.File{
Filename: tfvarsFilename,
Data: data,
}
@@ -72,8 +72,8 @@ func (t *TerraformVariables) Generate(parents asset.Parents) error {
// Files returns the files generated by the asset.
func (t *TerraformVariables) Files() []*asset.File {
if t.file != nil {
return []*asset.File{t.file}
if t.File != nil {
return []*asset.File{t.File}
}
return []*asset.File{}
}

View File

@@ -46,8 +46,8 @@ type bootstrapTemplateData struct {
// Bootstrap is an asset that generates the ignition config for bootstrap nodes.
type Bootstrap struct {
config *igntypes.Config
file *asset.File
Config *igntypes.Config
File *asset.File
}
var _ asset.WritableAsset = (*Bootstrap)(nil)
@@ -89,7 +89,7 @@ func (a *Bootstrap) Generate(dependencies asset.Parents) error {
return errors.Wrap(err, "failed to get bootstrap templates")
}
a.config = &igntypes.Config{
a.Config = &igntypes.Config{
Ignition: igntypes.Ignition{
Version: igntypes.MaxVersion.String(),
},
@@ -100,23 +100,23 @@ func (a *Bootstrap) Generate(dependencies asset.Parents) error {
a.addTectonicFiles(dependencies, templateData)
a.addTLSCertFiles(dependencies)
a.config.Systemd.Units = append(
a.config.Systemd.Units,
a.Config.Systemd.Units = append(
a.Config.Systemd.Units,
igntypes.Unit{Name: "bootkube.service", Contents: content.BootkubeSystemdContents},
igntypes.Unit{Name: "tectonic.service", Contents: content.TectonicSystemdContents, Enabled: util.BoolToPtr(true)},
igntypes.Unit{Name: "kubelet.service", Contents: applyTemplateData(content.KubeletSystemdTemplate, templateData), Enabled: util.BoolToPtr(true)},
)
a.config.Passwd.Users = append(
a.config.Passwd.Users,
a.Config.Passwd.Users = append(
a.Config.Passwd.Users,
igntypes.PasswdUser{Name: "core", SSHAuthorizedKeys: []igntypes.SSHAuthorizedKey{igntypes.SSHAuthorizedKey(installConfig.Config.Admin.SSHKey)}},
)
data, err := json.Marshal(a.config)
data, err := json.Marshal(a.Config)
if err != nil {
return errors.Wrap(err, "failed to Marshal Ignition config")
}
a.file = &asset.File{
a.File = &asset.File{
Filename: "bootstrap.ign",
Data: data,
}
@@ -131,8 +131,8 @@ func (a *Bootstrap) Name() string {
// Files returns the files generated by the asset.
func (a *Bootstrap) Files() []*asset.File {
if a.file != nil {
return []*asset.File{a.file}
if a.File != nil {
return []*asset.File{a.File}
}
return []*asset.File{}
}
@@ -174,13 +174,13 @@ func (a *Bootstrap) addBootstrapFiles(dependencies asset.Parents) {
kubeCoreOperator := &manifests.KubeCoreOperator{}
dependencies.Get(kubeletKubeconfig, kubeCoreOperator)
a.config.Storage.Files = append(
a.config.Storage.Files,
a.Config.Storage.Files = append(
a.Config.Storage.Files,
ignition.FileFromBytes("/etc/kubernetes/kubeconfig", 0600, kubeletKubeconfig.Files()[0].Data),
ignition.FileFromBytes("/var/lib/kubelet/kubeconfig", 0600, kubeletKubeconfig.Files()[0].Data),
)
a.config.Storage.Files = append(
a.config.Storage.Files,
a.Config.Storage.Files = append(
a.Config.Storage.Files,
ignition.FilesFromAsset(rootDir, 0644, kubeCoreOperator)...,
)
}
@@ -190,16 +190,16 @@ func (a *Bootstrap) addBootkubeFiles(dependencies asset.Parents, templateData *b
manifests := &manifests.Manifests{}
dependencies.Get(adminKubeconfig, manifests)
a.config.Storage.Files = append(
a.config.Storage.Files,
a.Config.Storage.Files = append(
a.Config.Storage.Files,
ignition.FileFromString("/opt/tectonic/bootkube.sh", 0555, applyTemplateData(content.BootkubeShFileTemplate, templateData)),
)
a.config.Storage.Files = append(
a.config.Storage.Files,
a.Config.Storage.Files = append(
a.Config.Storage.Files,
ignition.FilesFromAsset(rootDir, 0600, adminKubeconfig)...,
)
a.config.Storage.Files = append(
a.config.Storage.Files,
a.Config.Storage.Files = append(
a.Config.Storage.Files,
ignition.FilesFromAsset(rootDir, 0644, manifests)...,
)
}
@@ -208,12 +208,12 @@ func (a *Bootstrap) addTectonicFiles(dependencies asset.Parents, templateData *b
tectonic := &manifests.Tectonic{}
dependencies.Get(tectonic)
a.config.Storage.Files = append(
a.config.Storage.Files,
a.Config.Storage.Files = append(
a.Config.Storage.Files,
ignition.FileFromString("/opt/tectonic/tectonic.sh", 0555, content.TectonicShFileContents),
)
a.config.Storage.Files = append(
a.config.Storage.Files,
a.Config.Storage.Files = append(
a.Config.Storage.Files,
ignition.FilesFromAsset(rootDir, 0644, tectonic)...,
)
}
@@ -236,13 +236,13 @@ func (a *Bootstrap) addTLSCertFiles(dependencies asset.Parents) {
&tls.ServiceAccountKeyPair{},
} {
dependencies.Get(asset)
a.config.Storage.Files = append(a.config.Storage.Files, ignition.FilesFromAsset(rootDir, 0600, asset)...)
a.Config.Storage.Files = append(a.Config.Storage.Files, ignition.FilesFromAsset(rootDir, 0600, asset)...)
}
etcdClientCertKey := &tls.EtcdClientCertKey{}
dependencies.Get(etcdClientCertKey)
a.config.Storage.Files = append(
a.config.Storage.Files,
a.Config.Storage.Files = append(
a.Config.Storage.Files,
ignition.FileFromBytes("/etc/ssl/etcd/ca.crt", 0600, etcdClientCertKey.Cert()),
)
}

View File

@@ -14,8 +14,8 @@ import (
// Master is an asset that generates the ignition config for master nodes.
type Master struct {
configs []*igntypes.Config
files []*asset.File
Configs []*igntypes.Config
FileList []*asset.File
}
var _ asset.WritableAsset = (*Master)(nil)
@@ -34,18 +34,18 @@ func (a *Master) Generate(dependencies asset.Parents) error {
rootCA := &tls.RootCA{}
dependencies.Get(installConfig, rootCA)
a.configs = make([]*igntypes.Config, installConfig.Config.MasterCount())
for i := range a.configs {
a.configs[i] = pointerIgnitionConfig(installConfig.Config, rootCA.Cert(), "master", fmt.Sprintf("etcd_index=%d", i))
a.Configs = make([]*igntypes.Config, installConfig.Config.MasterCount())
for i := range a.Configs {
a.Configs[i] = pointerIgnitionConfig(installConfig.Config, rootCA.Cert(), "master", fmt.Sprintf("etcd_index=%d", i))
}
a.files = make([]*asset.File, len(a.configs))
for i, c := range a.configs {
a.FileList = make([]*asset.File, len(a.Configs))
for i, c := range a.Configs {
data, err := json.Marshal(c)
if err != nil {
return errors.Wrap(err, "failed to marshal ignition config")
}
a.files[i] = &asset.File{
a.FileList[i] = &asset.File{
Filename: fmt.Sprintf("master-%d.ign", i),
Data: data,
}
@@ -61,5 +61,5 @@ func (a *Master) Name() string {
// Files returns the files generated by the asset.
func (a *Master) Files() []*asset.File {
return a.files
return a.FileList
}

View File

@@ -13,8 +13,8 @@ import (
// Worker is an asset that generates the ignition config for worker nodes.
type Worker struct {
config *igntypes.Config
file *asset.File
Config *igntypes.Config
File *asset.File
}
var _ asset.WritableAsset = (*Worker)(nil)
@@ -33,13 +33,13 @@ func (a *Worker) Generate(dependencies asset.Parents) error {
rootCA := &tls.RootCA{}
dependencies.Get(installConfig, rootCA)
a.config = pointerIgnitionConfig(installConfig.Config, rootCA.Cert(), "worker", "")
a.Config = pointerIgnitionConfig(installConfig.Config, rootCA.Cert(), "worker", "")
data, err := json.Marshal(a.config)
data, err := json.Marshal(a.Config)
if err != nil {
return errors.Wrap(err, "failed to get InstallConfig from parents")
}
a.file = &asset.File{
a.File = &asset.File{
Filename: "worker.ign",
Data: data,
}
@@ -54,8 +54,8 @@ func (a *Worker) Name() string {
// Files returns the files generated by the asset.
func (a *Worker) Files() []*asset.File {
if a.file != nil {
return []*asset.File{a.file}
if a.File != nil {
return []*asset.File{a.File}
}
return []*asset.File{}
}

View File

@@ -8,7 +8,7 @@ import (
)
type baseDomain struct {
baseDomain string
BaseDomain string
}
var _ asset.Asset = (*baseDomain)(nil)
@@ -33,7 +33,7 @@ func (a *baseDomain) Generate(asset.Parents) error {
},
"OPENSHIFT_INSTALL_BASE_DOMAIN",
)
a.baseDomain = bd
a.BaseDomain = bd
return err
}

View File

@@ -7,7 +7,7 @@ import (
)
type clusterID struct {
clusterID string
ClusterID string
}
var _ asset.Asset = (*clusterID)(nil)
@@ -19,7 +19,7 @@ func (a *clusterID) Dependencies() []asset.Asset {
// Generate generates a new UUID
func (a *clusterID) Generate(asset.Parents) error {
a.clusterID = uuid.New()
a.ClusterID = uuid.New()
return nil
}

View File

@@ -8,7 +8,7 @@ import (
)
type clusterName struct {
clusterName string
ClusterName string
}
var _ asset.Asset = (*clusterName)(nil)
@@ -33,7 +33,7 @@ func (a *clusterName) Generate(asset.Parents) error {
},
"OPENSHIFT_INSTALL_CLUSTER_NAME",
)
a.clusterName = n
a.ClusterName = n
return err
}

View File

@@ -8,7 +8,7 @@ import (
)
type emailAddress struct {
emailAddress string
EmailAddress string
}
var _ asset.Asset = (*emailAddress)(nil)
@@ -33,7 +33,7 @@ func (a *emailAddress) Generate(asset.Parents) error {
},
"OPENSHIFT_INSTALL_EMAIL_ADDRESS",
)
a.emailAddress = email
a.EmailAddress = email
return err
}

View File

@@ -24,8 +24,8 @@ var (
// InstallConfig generates the install-config.yml file.
type InstallConfig struct {
Config *types.InstallConfig
file *asset.File
Config *types.InstallConfig `json:"config"`
File *asset.File `json:"file"`
}
var _ asset.WritableAsset = (*InstallConfig)(nil)
@@ -68,15 +68,15 @@ func (a *InstallConfig) Generate(parents asset.Parents) error {
a.Config = &types.InstallConfig{
ObjectMeta: metav1.ObjectMeta{
Name: clusterName.clusterName,
Name: clusterName.ClusterName,
},
ClusterID: clusterID.clusterID,
ClusterID: clusterID.ClusterID,
Admin: types.Admin{
Email: emailAddress.emailAddress,
Password: password.password,
SSHKey: sshPublicKey.key,
Email: emailAddress.EmailAddress,
Password: password.Password,
SSHKey: sshPublicKey.Key,
},
BaseDomain: baseDomain.baseDomain,
BaseDomain: baseDomain.BaseDomain,
Networking: types.Networking{
// TODO(yifan): Flannel is the temporal default network type for now,
// Need to update it to the new types.
@@ -89,19 +89,19 @@ func (a *InstallConfig) Generate(parents asset.Parents) error {
IPNet: defaultPodCIDR,
},
},
PullSecret: pullSecret.pullSecret,
PullSecret: pullSecret.PullSecret,
}
numberOfMasters := int64(3)
numberOfWorkers := int64(3)
switch {
case platform.aws != nil:
a.Config.AWS = platform.aws
case platform.openstack != nil:
a.Config.OpenStack = platform.openstack
case platform.libvirt != nil:
a.Config.Libvirt = platform.libvirt
a.Config.Libvirt.Network.Name = clusterName.clusterName
case platform.AWS != nil:
a.Config.AWS = platform.AWS
case platform.Openstack != nil:
a.Config.OpenStack = platform.Openstack
case platform.Libvirt != nil:
a.Config.Libvirt = platform.Libvirt
a.Config.Libvirt.Network.Name = clusterName.ClusterName
numberOfMasters = 1
numberOfWorkers = 1
default:
@@ -123,7 +123,7 @@ func (a *InstallConfig) Generate(parents asset.Parents) error {
if err != nil {
return errors.Wrap(err, "failed to Marshal InstallConfig")
}
a.file = &asset.File{
a.File = &asset.File{
Filename: "install-config.yml",
Data: data,
}
@@ -138,8 +138,8 @@ func (a *InstallConfig) Name() string {
// Files returns the files generated by the asset.
func (a *InstallConfig) Files() []*asset.File {
if a.file != nil {
return []*asset.File{a.file}
if a.File != nil {
return []*asset.File{a.File}
}
return []*asset.File{}
}

View File

@@ -7,7 +7,7 @@ import (
)
type password struct {
password string
Password string
}
var _ asset.Asset = (*password)(nil)
@@ -29,7 +29,7 @@ func (a *password) Generate(asset.Parents) error {
},
"OPENSHIFT_INSTALL_PASSWORD",
)
a.password = p
a.Password = p
return err
}

View File

@@ -58,9 +58,9 @@ var (
// Platform is an asset that queries the user for the platform on which to install
// the cluster.
type platform struct {
aws *types.AWSPlatform
openstack *types.OpenStackPlatform
libvirt *types.LibvirtPlatform
AWS *types.AWSPlatform
Openstack *types.OpenStackPlatform
Libvirt *types.LibvirtPlatform
}
var _ asset.Asset = (*platform)(nil)
@@ -83,19 +83,19 @@ func (a *platform) Generate(asset.Parents) error {
if err != nil {
return err
}
a.aws = aws
a.AWS = aws
case OpenStackPlatformType:
openstack, err := a.openstackPlatform()
if err != nil {
return err
}
a.openstack = openstack
a.Openstack = openstack
case LibvirtPlatformType:
libvirt, err := a.libvirtPlatform()
if err != nil {
return err
}
a.libvirt = libvirt
a.Libvirt = libvirt
default:
return fmt.Errorf("unknown platform type %q", platform)
}

View File

@@ -8,7 +8,7 @@ import (
)
type pullSecret struct {
pullSecret string
PullSecret string
}
var _ asset.Asset = (*pullSecret)(nil)
@@ -34,7 +34,7 @@ func (a *pullSecret) Generate(asset.Parents) error {
"OPENSHIFT_INSTALL_PULL_SECRET",
"OPENSHIFT_INSTALL_PULL_SECRET_PATH",
)
a.pullSecret = s
a.PullSecret = s
return err
}

View File

@@ -20,7 +20,7 @@ const (
)
type sshPublicKey struct {
key string
Key string
}
var _ asset.Asset = (*sshPublicKey)(nil)
@@ -54,7 +54,7 @@ func (a *sshPublicKey) Generate(asset.Parents) error {
return errors.Wrap(err, "failed to validate public key")
}
}
a.key = value
a.Key = value
return nil
}
@@ -85,7 +85,7 @@ func (a *sshPublicKey) Generate(asset.Parents) error {
if len(pubKeys) == 1 {
for _, value := range pubKeys {
a.key = value
a.Key = value
}
return nil
}
@@ -113,7 +113,7 @@ func (a *sshPublicKey) Generate(asset.Parents) error {
return errors.Wrap(err, "failed UserInput for SSH public key")
}
a.key = pubKeys[path]
a.Key = pubKeys[path]
return nil
}

View File

@@ -14,8 +14,8 @@ import (
)
type kubeconfig struct {
config *clientcmd.Config
file *asset.File
Config *clientcmd.Config
File *asset.File
}
// generate generates the kubeconfig.
@@ -26,7 +26,7 @@ func (k *kubeconfig) generate(
userName string,
filename string,
) error {
k.config = &clientcmd.Config{
k.Config = &clientcmd.Config{
Clusters: []clientcmd.NamedCluster{
{
Name: installConfig.ObjectMeta.Name,
@@ -57,12 +57,12 @@ func (k *kubeconfig) generate(
CurrentContext: userName,
}
data, err := yaml.Marshal(k.config)
data, err := yaml.Marshal(k.Config)
if err != nil {
return errors.Wrap(err, "failed to Marshal kubeconfig")
}
k.file = &asset.File{
k.File = &asset.File{
Filename: filepath.Join("auth", filename),
Data: data,
}
@@ -72,8 +72,8 @@ func (k *kubeconfig) generate(
// Files returns the files generated by the asset.
func (k *kubeconfig) Files() []*asset.File {
if k.file != nil {
return []*asset.File{k.file}
if k.File != nil {
return []*asset.File{k.File}
}
return []*asset.File{}
}

View File

@@ -13,8 +13,8 @@ import (
// kubeAddonOperator generates the network-operator-*.yml files
type kubeAddonOperator struct {
config *kubeaddon.OperatorConfig
file *asset.File
Config *kubeaddon.OperatorConfig
File *asset.File
}
var _ asset.WritableAsset = (*kubeAddonOperator)(nil)
@@ -37,7 +37,7 @@ func (kao *kubeAddonOperator) Generate(dependencies asset.Parents) error {
installConfig := &installconfig.InstallConfig{}
dependencies.Get(installConfig)
kao.config = &kubeaddon.OperatorConfig{
kao.Config = &kubeaddon.OperatorConfig{
TypeMeta: metav1.TypeMeta{
APIVersion: kubeaddon.APIVersion,
Kind: kubeaddon.Kind,
@@ -49,12 +49,12 @@ func (kao *kubeAddonOperator) Generate(dependencies asset.Parents) error {
},
}
data, err := yaml.Marshal(kao.config)
data, err := yaml.Marshal(kao.Config)
if err != nil {
return errors.Wrapf(err, "failed to create %s config from InstallConfig", kao.Name())
}
kao.file = &asset.File{
kao.File = &asset.File{
Filename: "kube-addon-operator-config.yml",
Data: data,
}
@@ -64,8 +64,8 @@ func (kao *kubeAddonOperator) Generate(dependencies asset.Parents) error {
// Files returns the files generated by the asset.
func (kao *kubeAddonOperator) Files() []*asset.File {
if kao.file != nil {
return []*asset.File{kao.file}
if kao.File != nil {
return []*asset.File{kao.File}
}
return []*asset.File{}
}

View File

@@ -24,8 +24,8 @@ const (
// KubeCoreOperator generates the kube-core-operator.yaml files
type KubeCoreOperator struct {
config *kubecore.OperatorConfig
file *asset.File
Config *kubecore.OperatorConfig
File *asset.File
}
var _ asset.WritableAsset = (*KubeCoreOperator)(nil)
@@ -53,7 +53,7 @@ func (kco *KubeCoreOperator) Generate(dependencies asset.Parents) error {
return errors.Wrapf(err, "failed to create %s config from InstallConfig", kco.Name())
}
kco.config = &kubecore.OperatorConfig{
kco.Config = &kubecore.OperatorConfig{
TypeMeta: metav1.TypeMeta{
APIVersion: kubecore.APIVersion,
Kind: kubecore.Kind,
@@ -85,11 +85,11 @@ func (kco *KubeCoreOperator) Generate(dependencies asset.Parents) error {
},
}
data, err := yaml.Marshal(kco.config)
data, err := yaml.Marshal(kco.Config)
if err != nil {
return errors.Wrapf(err, "failed to create %s config from InstallConfig", kco.Name())
}
kco.file = &asset.File{
kco.File = &asset.File{
Filename: "kco-config.yaml",
Data: data,
}
@@ -99,8 +99,8 @@ func (kco *KubeCoreOperator) Generate(dependencies asset.Parents) error {
// Files returns the files generated by the asset.
func (kco *KubeCoreOperator) Files() []*asset.File {
if kco.file != nil {
return []*asset.File{kco.file}
if kco.File != nil {
return []*asset.File{kco.File}
}
return []*asset.File{}
}

View File

@@ -21,8 +21,8 @@ const (
// machineAPIOperator generates the network-operator-*.yml files
type machineAPIOperator struct {
config *maoOperatorConfig
file *asset.File
Config *maoOperatorConfig
File *asset.File
}
var _ asset.WritableAsset = (*machineAPIOperator)(nil)
@@ -83,7 +83,7 @@ func (mao *machineAPIOperator) Generate(dependencies asset.Parents) error {
aggregatorCA := &tls.AggregatorCA{}
dependencies.Get(installConfig, aggregatorCA)
mao.config = &maoOperatorConfig{
mao.Config = &maoOperatorConfig{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "machineAPIOperatorConfig",
@@ -102,7 +102,7 @@ func (mao *machineAPIOperator) Generate(dependencies asset.Parents) error {
return errors.Wrapf(err, "failed to get AMI for %s config", mao.Name())
}
mao.config.AWS = &awsConfig{
mao.Config.AWS = &awsConfig{
ClusterName: installConfig.Config.ObjectMeta.Name,
ClusterID: installConfig.Config.ClusterID,
Region: installConfig.Config.Platform.AWS.Region,
@@ -111,7 +111,7 @@ func (mao *machineAPIOperator) Generate(dependencies asset.Parents) error {
Replicas: int(*installConfig.Config.Machines[1].Replicas),
}
case installConfig.Config.Platform.Libvirt != nil:
mao.config.Libvirt = &libvirtConfig{
mao.Config.Libvirt = &libvirtConfig{
ClusterName: installConfig.Config.ObjectMeta.Name,
URI: installConfig.Config.Platform.Libvirt.URI,
NetworkName: installConfig.Config.Platform.Libvirt.Network.Name,
@@ -119,7 +119,7 @@ func (mao *machineAPIOperator) Generate(dependencies asset.Parents) error {
Replicas: int(*installConfig.Config.Machines[1].Replicas),
}
case installConfig.Config.Platform.OpenStack != nil:
mao.config.OpenStack = &openstackConfig{
mao.Config.OpenStack = &openstackConfig{
ClusterName: installConfig.Config.ObjectMeta.Name,
ClusterID: installConfig.Config.ClusterID,
Region: installConfig.Config.Platform.OpenStack.Region,
@@ -129,11 +129,11 @@ func (mao *machineAPIOperator) Generate(dependencies asset.Parents) error {
return errors.Errorf("unknown provider for machine-api-operator")
}
data, err := yaml.Marshal(mao.config)
data, err := yaml.Marshal(mao.Config)
if err != nil {
return errors.Wrapf(err, "failed to marshal %s config", mao.Name())
}
mao.file = &asset.File{
mao.File = &asset.File{
Filename: "machine-api-operator-config.yml",
Data: data,
}
@@ -143,5 +143,5 @@ func (mao *machineAPIOperator) Generate(dependencies asset.Parents) error {
// Files returns the files generated by the asset.
func (mao *machineAPIOperator) Files() []*asset.File {
return []*asset.File{mao.file}
return []*asset.File{mao.File}
}

View File

@@ -17,8 +17,8 @@ const (
// networkOperator generates the network-operator-*.yml files
type networkOperator struct {
config *tectonicnetwork.OperatorConfig
files []*asset.File
config *tectonicnetwork.OperatorConfig
FileList []*asset.File
}
var _ asset.WritableAsset = (*networkOperator)(nil)
@@ -57,7 +57,7 @@ func (no *networkOperator) Generate(dependencies asset.Parents) error {
if err != nil {
return errors.Wrapf(err, "failed to create %s manifests from InstallConfig", no.Name())
}
no.files = []*asset.File{
no.FileList = []*asset.File{
{
Filename: "network-operator-config.yml",
Data: configData,
@@ -73,5 +73,5 @@ func (no *networkOperator) Generate(dependencies asset.Parents) error {
// Files returns the files generated by the asset.
func (no *networkOperator) Files() []*asset.File {
return no.files
return no.FileList
}

View File

@@ -25,9 +25,9 @@ const (
// Manifests generates the dependent operator config.yaml files
type Manifests struct {
kubeSysConfig *configurationObject
tectonicConfig *configurationObject
files []*asset.File
KubeSysConfig *configurationObject
TectonicConfig *configurationObject
FileList []*asset.File
}
var _ asset.WritableAsset = (*Manifests)(nil)
@@ -78,27 +78,27 @@ func (m *Manifests) Generate(dependencies asset.Parents) error {
dependencies.Get(kco, no, addon, mao, installConfig)
// kco+no+mao go to kube-system config map
m.kubeSysConfig = configMap("kube-system", "cluster-config-v1", genericData{
m.KubeSysConfig = configMap("kube-system", "cluster-config-v1", genericData{
"kco-config": string(kco.Files()[0].Data),
"network-config": string(no.Files()[0].Data),
"install-config": string(installConfig.Files()[0].Data),
"mao-config": string(mao.Files()[0].Data),
})
kubeSysConfigData, err := yaml.Marshal(m.kubeSysConfig)
kubeSysConfigData, err := yaml.Marshal(m.KubeSysConfig)
if err != nil {
return errors.Wrap(err, "failed to create kube-system/cluster-config-v1 configmap")
}
// addon goes to openshift system
m.tectonicConfig = configMap("tectonic-system", "cluster-config-v1", genericData{
m.TectonicConfig = configMap("tectonic-system", "cluster-config-v1", genericData{
"addon-config": string(addon.Files()[0].Data),
})
tectonicConfigData, err := yaml.Marshal(m.tectonicConfig)
tectonicConfigData, err := yaml.Marshal(m.TectonicConfig)
if err != nil {
return errors.Wrap(err, "failed to create tectonic-system/cluster-config-v1 configmap")
}
m.files = []*asset.File{
m.FileList = []*asset.File{
{
Filename: filepath.Join(manifestDir, "cluster-config.yaml"),
Data: kubeSysConfigData,
@@ -108,14 +108,14 @@ func (m *Manifests) Generate(dependencies asset.Parents) error {
Data: tectonicConfigData,
},
}
m.files = append(m.files, m.generateBootKubeManifests(dependencies)...)
m.FileList = append(m.FileList, m.generateBootKubeManifests(dependencies)...)
return nil
}
// Files returns the files generated by the asset.
func (m *Manifests) Files() []*asset.File {
return m.files
return m.FileList
}
func (m *Manifests) generateBootKubeManifests(dependencies asset.Parents) []*asset.File {

View File

@@ -13,7 +13,7 @@ import (
// Tectonic generates the dependent resource manifests for tectonic (as against bootkube)
type Tectonic struct {
files []*asset.File
FileList []*asset.File
}
var _ asset.WritableAsset = (*Tectonic)(nil)
@@ -73,9 +73,9 @@ func (t *Tectonic) Generate(dependencies asset.Parents) error {
"99_tectonic-system-02-pull.json": applyTemplateData(content.PullTectonicSystem, templateData),
}
t.files = make([]*asset.File, 0, len(assetData))
t.FileList = make([]*asset.File, 0, len(assetData))
for name, data := range assetData {
t.files = append(t.files, &asset.File{
t.FileList = append(t.FileList, &asset.File{
Filename: filepath.Join("tectonic", name),
Data: data,
})
@@ -86,5 +86,5 @@ func (t *Tectonic) Generate(dependencies asset.Parents) error {
// Files returns the files generated by the asset.
func (t *Tectonic) Files() []*asset.File {
return t.files
return t.FileList
}

View File

@@ -1,12 +1,20 @@
package asset
import (
"encoding/json"
"io/ioutil"
"os"
"path/filepath"
"reflect"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
const (
stateFileName = ".openshift_install_state.json"
)
// Store is a store for the states of assets.
type Store interface {
// Fetch retrieves the state of the given asset, generating it and its
@@ -16,7 +24,8 @@ type Store interface {
// StoreImpl is the implementation of Store.
type StoreImpl struct {
assets map[reflect.Type]Asset
assets map[reflect.Type]Asset
stateFileAssets map[string]json.RawMessage
}
// Fetch retrieves the state of the given asset, generating it and its
@@ -25,6 +34,58 @@ func (s *StoreImpl) Fetch(asset Asset) error {
return s.fetch(asset, "")
}
// Load retrieves the state from the state file present in the given directory
// and returns the assets map
func (s *StoreImpl) Load(dir string) error {
path := filepath.Join(dir, stateFileName)
assets := make(map[string]json.RawMessage)
data, err := ioutil.ReadFile(path)
if err != nil {
if os.IsNotExist(err) {
return nil
}
return err
}
err = json.Unmarshal(data, &assets)
if err != nil {
return errors.Wrapf(err, "failed to unmarshal state file %s", path)
}
s.stateFileAssets = assets
return nil
}
// GetStateAsset renders the asset object arguments from the state file contents
// also returns a boolean indicating whether the object was found in the state file or not
func (s *StoreImpl) GetStateAsset(asset Asset) (bool, error) {
bytes, ok := s.stateFileAssets[reflect.TypeOf(asset).String()]
if !ok {
return false, nil
}
err := json.Unmarshal(bytes, asset)
return true, err
}
// Save dumps the entire state map into a file
func (s *StoreImpl) Save(dir string) error {
assetMap := make(map[string]Asset)
for k, v := range s.assets {
assetMap[k.String()] = v
}
data, err := json.MarshalIndent(&assetMap, "", " ")
if err != nil {
return err
}
path := filepath.Join(dir, stateFileName)
if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
return err
}
if err := ioutil.WriteFile(path, data, 0644); err != nil {
return err
}
return nil
}
func (s *StoreImpl) fetch(asset Asset, indent string) error {
logrus.Debugf("%sFetching %s...", indent, asset.Name())
storedAsset, ok := s.assets[reflect.TypeOf(asset)]
@@ -47,10 +108,21 @@ func (s *StoreImpl) fetch(asset Asset, indent string) error {
parents.Add(d)
}
logrus.Debugf("%sGenerating %s...", indent, asset.Name())
err := asset.Generate(parents)
// Before generating the asset, look if we have it all ready in the state file
// if yes, then use it instead
logrus.Debugf("%sLooking up asset from state file: %s", indent, reflect.TypeOf(asset).String())
ok, err := s.GetStateAsset(asset)
if err != nil {
return errors.Wrapf(err, "failed to generate asset %s", asset.Name())
return errors.Wrapf(err, "failed to unmarshal asset '%s' from state file '%s'", asset.Name(), stateFileName)
}
if ok {
logrus.Debugf("%sAsset found in state file", indent)
} else {
logrus.Debugf("%sAsset not found in state file. Generating %s...", indent, asset.Name())
err := asset.Generate(parents)
if err != nil {
return errors.Wrapf(err, "failed to generate asset %s", asset.Name())
}
}
if s.assets == nil {
s.assets = make(map[reflect.Type]Asset)

View File

@@ -32,19 +32,19 @@ type CertKeyInterface interface {
// CertKey contains the private key and the cert that's
// signed by the parent CA.
type CertKey struct {
cert []byte
key []byte
files []*asset.File
CertRaw []byte
KeyRaw []byte
FileList []*asset.File
}
// Cert returns the certificate.
func (c *CertKey) Cert() []byte {
return c.cert
return c.CertRaw
}
// Key returns the private key.
func (c *CertKey) Key() []byte {
return c.key
return c.KeyRaw
}
// Generate generates a cert/key pair signed by the specified parent CA.
@@ -73,11 +73,11 @@ func (c *CertKey) Generate(
return errors.Wrap(err, "failed to generate cert/key pair")
}
c.key = PrivateKeyToPem(key)
c.cert = CertToPem(crt)
c.KeyRaw = PrivateKeyToPem(key)
c.CertRaw = CertToPem(crt)
if appendParent {
c.cert = bytes.Join([][]byte{c.cert, CertToPem(caCert)}, []byte("\n"))
c.CertRaw = bytes.Join([][]byte{c.CertRaw, CertToPem(caCert)}, []byte("\n"))
}
c.generateFiles(filenameBase)
@@ -87,18 +87,18 @@ func (c *CertKey) Generate(
// Files returns the files generated by the asset.
func (c *CertKey) Files() []*asset.File {
return c.files
return c.FileList
}
func (c *CertKey) generateFiles(filenameBase string) {
c.files = []*asset.File{
c.FileList = []*asset.File{
{
Filename: assetFilePath(filenameBase + ".key"),
Data: c.key,
Data: c.KeyRaw,
},
{
Filename: assetFilePath(filenameBase + ".crt"),
Data: c.cert,
Data: c.CertRaw,
},
}
}

View File

@@ -15,9 +15,9 @@ type KeyPairInterface interface {
// KeyPair contains a private key and a public key.
type KeyPair struct {
private []byte
public []byte
files []*asset.File
Pvt []byte
Pub []byte
FileList []*asset.File
}
// Generate generates the rsa private / public key pair.
@@ -32,17 +32,17 @@ func (k *KeyPair) Generate(filenameBase string) error {
return errors.Wrap(err, "failed to get public key data from private key")
}
k.private = PrivateKeyToPem(key)
k.public = pubkeyData
k.Pvt = PrivateKeyToPem(key)
k.Pub = pubkeyData
k.files = []*asset.File{
k.FileList = []*asset.File{
{
Filename: assetFilePath(filenameBase + ".key"),
Data: k.private,
Data: k.Pvt,
},
{
Filename: assetFilePath(filenameBase + ".pub"),
Data: k.public,
Data: k.Pub,
},
}
@@ -51,15 +51,15 @@ func (k *KeyPair) Generate(filenameBase string) error {
// Public returns the public key.
func (k *KeyPair) Public() []byte {
return k.public
return k.Pub
}
// Private returns the private key.
func (k *KeyPair) Private() []byte {
return k.private
return k.Pvt
}
// Files returns the files generated by the asset.
func (k *KeyPair) Files() []*asset.File {
return k.files
return k.FileList
}

View File

@@ -35,8 +35,8 @@ func (c *RootCA) Generate(parents asset.Parents) error {
return errors.Wrap(err, "failed to generate RootCA")
}
c.key = PrivateKeyToPem(key)
c.cert = CertToPem(crt)
c.KeyRaw = PrivateKeyToPem(key)
c.CertRaw = CertToPem(crt)
c.generateFiles("root-ca")