github.com/openshift/installer@v1.4.17/pkg/asset/agent/joiner/addnodesconfig.go (about) 1 package joiner 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "os" 8 "path/filepath" 9 10 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 11 "k8s.io/apimachinery/pkg/util/validation/field" 12 "sigs.k8s.io/yaml" 13 14 "github.com/openshift/installer/pkg/asset" 15 "github.com/openshift/installer/pkg/types/agent" 16 "github.com/openshift/installer/pkg/validate" 17 ) 18 19 const ( 20 addNodesParamsFile = ".addnodesparams" 21 nodesConfigFilename = "nodes-config.yaml" 22 ) 23 24 // AddNodesConfig is used to store the current configuration 25 // for the command. 26 type AddNodesConfig struct { 27 Params Params 28 Config Config 29 } 30 31 var _ asset.WritableAsset = (*AddNodesConfig)(nil) 32 33 // Config defines the configuration for the nodes-config.yaml file 34 // used by the add-nodes command. 35 type Config struct { 36 metav1.TypeMeta `json:",inline"` 37 metav1.ObjectMeta `json:"metadata,omitempty"` 38 39 CPUArchitecture string `json:"cpuArchitecture,omitempty"` 40 SSHKey string `json:"sshKey,omitempty"` 41 Hosts []agent.Host `json:"hosts,omitempty"` 42 } 43 44 // Params is used to store the command line parameters. 45 type Params struct { 46 Kubeconfig string `json:"kubeconfig,omitempty"` 47 } 48 49 // Save stores the current parameters on disk. 50 func (p *Params) Save(assetsDir string) error { 51 data, err := json.Marshal(p) 52 if err != nil { 53 return err 54 } 55 56 fileName := filepath.Join(assetsDir, addNodesParamsFile) 57 return os.WriteFile(fileName, data, 0o600) 58 } 59 60 // Name returns the human-friendly name of the asset. 61 func (*AddNodesConfig) Name() string { 62 return "AddNodes Config" 63 } 64 65 // Dependencies returns all of the dependencies directly needed to generate 66 // the asset. 67 func (*AddNodesConfig) Dependencies() []asset.Asset { 68 return []asset.Asset{} 69 } 70 71 // Generate it's empty for this asset, always loaded from disk. 72 func (*AddNodesConfig) Generate(_ context.Context, dependencies asset.Parents) error { 73 return nil 74 } 75 76 // Files returns the files generated by the asset. 77 func (*AddNodesConfig) Files() []*asset.File { 78 return []*asset.File{} 79 } 80 81 // Load returns agent config asset from the disk. 82 func (a *AddNodesConfig) Load(f asset.FileFetcher) (bool, error) { 83 // Load params file. 84 file, err := f.FetchByName(addNodesParamsFile) 85 if err != nil { 86 if os.IsNotExist(err) { 87 return false, nil 88 } 89 return false, fmt.Errorf("failed to load %s file: %w", addNodesParamsFile, err) 90 } 91 92 params := &Params{} 93 if err = json.Unmarshal(file.Data, params); err != nil { 94 return false, fmt.Errorf("failed to unmarshal %s: %w", addNodesParamsFile, err) 95 } 96 a.Params = *params 97 98 // Load nodes-config.yaml file. 99 file, err = f.FetchByName(nodesConfigFilename) 100 if err != nil { 101 return false, fmt.Errorf("failed to load %s file: %w", nodesConfigFilename, err) 102 } 103 104 config := Config{} 105 if err = yaml.Unmarshal(file.Data, &config); err != nil { 106 return false, fmt.Errorf("failed to unmarshal %s: %w", nodesConfigFilename, err) 107 } 108 a.Config = config 109 110 err = a.finish() 111 if err != nil { 112 return false, err 113 } 114 return true, nil 115 } 116 117 func (a *AddNodesConfig) finish() error { 118 allErrs := field.ErrorList{} 119 120 if err := a.validateHosts(); err != nil { 121 allErrs = append(allErrs, err...) 122 } 123 if err := a.validateSSHKey(); err != nil { 124 allErrs = append(allErrs, err...) 125 } 126 127 return allErrs.ToAggregate() 128 } 129 130 func (a *AddNodesConfig) validateHosts() field.ErrorList { 131 var allErrs field.ErrorList 132 133 if len(a.Config.Hosts) == 0 { 134 fieldPath := field.NewPath("hosts") 135 allErrs = append(allErrs, field.Required(fieldPath, "at least one host must be defined")) 136 } 137 138 return allErrs 139 } 140 141 func (a *AddNodesConfig) validateSSHKey() field.ErrorList { 142 var allErrs field.ErrorList 143 144 if a.Config.SSHKey == "" { 145 return nil 146 } 147 148 if err := validate.SSHPublicKey(a.Config.SSHKey); err != nil { 149 allErrs = append(allErrs, field.Invalid(field.NewPath("sshKey"), a.Config.SSHKey, err.Error())) 150 } 151 return allErrs 152 }