diff --git a/pkg/addons/applier.go b/pkg/addons/applier.go index fdd048de8..55a04ba2f 100644 --- a/pkg/addons/applier.go +++ b/pkg/addons/applier.go @@ -17,7 +17,6 @@ limitations under the License. package addons import ( - "embed" "io/fs" "os" "path/filepath" @@ -25,7 +24,7 @@ import ( "github.com/MakeNowJust/heredoc/v2" "github.com/pkg/errors" - "k8c.io/kubeone/addons" + embeddedaddons "k8c.io/kubeone/addons" kubeoneapi "k8c.io/kubeone/pkg/apis/kubeone" "k8c.io/kubeone/pkg/certificate" "k8c.io/kubeone/pkg/credentials" @@ -47,7 +46,7 @@ var ( type applier struct { TemplateData templateData LocalFS fs.FS - EmbededFS embed.FS + EmbededFS fs.FS } // TemplateData is data available in the addons render template @@ -58,10 +57,12 @@ type templateData struct { MachineControllerCredentialsEnvVars string InternalImages *internalImages Resources map[string]string + Params map[string]string } func newAddonsApplier(s *state.State) (*applier, error) { var localFS fs.FS + if s.Cluster.Addons != nil && s.Cluster.Addons.Enable { addonsPath := s.Cluster.Addons.Path if !filepath.IsAbs(addonsPath) && s.ManifestFilePath != "" { @@ -84,6 +85,7 @@ func newAddonsApplier(s *state.State) (*applier, error) { if err != nil { return nil, errors.Wrap(err, "unable to fetch env var bindings for credentials") } + credsEnvVars, err := yaml.Marshal(envVars) if err != nil { return nil, errors.Wrap(err, "unable to convert env var bindings for credentials to yaml") @@ -105,7 +107,14 @@ func newAddonsApplier(s *state.State) (*applier, error) { return nil, err } - td := templateData{ + params := map[string]string{} + if s.Cluster.Addons != nil && s.Cluster.Addons.Enable { + for k, v := range s.Cluster.Addons.GlobalParams { + params[k] = v + } + } + + data := templateData{ Config: s.Cluster, Certificates: map[string]string{ "MachineControllerWebhookCert": certsMap[resources.MachineControllerWebhookCertName], @@ -119,12 +128,13 @@ func newAddonsApplier(s *state.State) (*applier, error) { resolver: s.Images.Get, }, Resources: resources.All(), + Params: params, } return &applier{ - TemplateData: td, + TemplateData: data, LocalFS: localFS, - EmbededFS: addons.F, + EmbededFS: embeddedaddons.F, }, nil } diff --git a/pkg/addons/ensure.go b/pkg/addons/ensure.go index 7e7b88084..68921adbc 100644 --- a/pkg/addons/ensure.go +++ b/pkg/addons/ensure.go @@ -58,6 +58,7 @@ func EnsureUserAddons(s *state.State) error { if err != nil { return err } + if applier.LocalFS == nil { s.Logger.Infoln("Skipping applying addons because addons are not enabled...") return nil @@ -70,18 +71,18 @@ func EnsureUserAddons(s *state.State) error { return errors.Wrap(err, "failed to read addons directory") } - for _, a := range addons { - if !a.IsDir() { + for _, useraddon := range addons { + if !useraddon.IsDir() { continue } - if _, ok := embeddedAddons[a.Name()]; ok { + if _, ok := embeddedAddons[useraddon.Name()]; ok { continue } - s.Logger.Infof("Applying addon %q...", a.Name()) + s.Logger.Infof("Applying addon %q...", useraddon.Name()) - if err := applier.loadAndApplyAddon(s, applier.LocalFS, a.Name()); err != nil { - return errors.Wrapf(err, "failed to load and apply the addon %q", a.Name()) + if err := applier.loadAndApplyAddon(s, applier.LocalFS, useraddon.Name()); err != nil { + return errors.Wrapf(err, "failed to load and apply the addon %q", useraddon.Name()) } } @@ -142,23 +143,24 @@ func EnsureAddonByName(s *state.State, addonName string) error { } // loadAndApplyAddon parses the addons manifests and runs kubectl apply. -func (a *applier) loadAndApplyAddon(s *state.State, f fs.FS, addonName string) error { - manifest, err := a.getManifestsFromDirectory(s, f, addonName) +func (a *applier) loadAndApplyAddon(s *state.State, fsys fs.FS, addonName string) error { + manifest, err := a.getManifestsFromDirectory(s, fsys, addonName) if err != nil { return errors.WithStack(err) } + if len(strings.TrimSpace(manifest)) == 0 { if len(addonName) != 0 { s.Logger.Warnf("Addon directory %q is empty, skipping...", addonName) } - return nil - } - if err := runKubectlApply(s, manifest, addonName); err != nil { - return errors.Wrap(err, "failed to apply addons") + return nil } - return nil + return errors.Wrap( + runKubectlApply(s, manifest, addonName), + "failed to apply addons", + ) } // runKubectlApply runs kubectl apply command diff --git a/pkg/addons/manifest.go b/pkg/addons/manifest.go index 02ec57e8f..db0e20fe5 100644 --- a/pkg/addons/manifest.go +++ b/pkg/addons/manifest.go @@ -40,13 +40,13 @@ import ( "sigs.k8s.io/yaml" ) -func (a *applier) getManifestsFromDirectory(s *state.State, f fs.FS, addonName string) (string, error) { +func (a *applier) getManifestsFromDirectory(s *state.State, fsys fs.FS, addonName string) (string, error) { overwriteRegistry := "" if s.Cluster.RegistryConfiguration != nil && s.Cluster.RegistryConfiguration.OverwriteRegistry != "" { overwriteRegistry = s.Cluster.RegistryConfiguration.OverwriteRegistry } - manifests, err := a.loadAddonsManifests(f, addonName, s.Logger, s.Verbose, overwriteRegistry) + manifests, err := a.loadAddonsManifests(fsys, addonName, s.Logger, s.Verbose, overwriteRegistry) if err != nil { return "", err } @@ -62,10 +62,16 @@ func (a *applier) getManifestsFromDirectory(s *state.State, f fs.FS, addonName s } // loadAddonsManifests loads all YAML files from a given directory and runs the templating logic -func (a *applier) loadAddonsManifests(f fs.FS, addonName string, logger logrus.FieldLogger, verbose bool, overwriteRegistry string) ([]runtime.RawExtension, error) { - manifests := []runtime.RawExtension{} - - files, err := fs.ReadDir(f, filepath.Join(".", addonName)) +func (a *applier) loadAddonsManifests( + fsys fs.FS, + addonName string, + logger logrus.FieldLogger, + verbose bool, + overwriteRegistry string, +) ([]runtime.RawExtension, error) { + var manifests []runtime.RawExtension + + files, err := fs.ReadDir(fsys, filepath.Join(".", addonName)) if err != nil { return nil, errors.Wrapf(err, "failed to read the addons directory %s", addonName) } @@ -75,6 +81,7 @@ func (a *applier) loadAddonsManifests(f fs.FS, addonName string, logger logrus.F if file.IsDir() { continue } + ext := strings.ToLower(filepath.Ext(file.Name())) // Only YAML, YML and JSON manifests are supported switch ext { @@ -85,11 +92,12 @@ func (a *applier) loadAddonsManifests(f fs.FS, addonName string, logger logrus.F } continue } + if verbose { logger.Infof("Parsing addons manifest '%s'\n", file.Name()) } - manifestBytes, err := fs.ReadFile(f, filePath) + manifestBytes, err := fs.ReadFile(fsys, filePath) if err != nil { return nil, errors.Wrapf(err, "failed to load addon %s", file.Name()) } @@ -98,6 +106,7 @@ func (a *applier) loadAddonsManifests(f fs.FS, addonName string, logger logrus.F if err != nil { return nil, errors.Wrapf(err, "failed to template addons manifest %s", file.Name()) } + buf := bytes.NewBuffer([]byte{}) if err := tpl.Execute(buf, a.TemplateData); err != nil { return nil, errors.Wrapf(err, "failed to template addons manifest %s", file.Name()) @@ -117,19 +126,23 @@ func (a *applier) loadAddonsManifests(f fs.FS, addonName string, logger logrus.F } return nil, errors.Wrapf(err, "failed reading from YAML reader for manifest %s", file.Name()) } + b = bytes.TrimSpace(b) if len(b) == 0 { continue } + decoder := kyaml.NewYAMLToJSONDecoder(bytes.NewBuffer(b)) raw := runtime.RawExtension{} if err := decoder.Decode(&raw); err != nil { return nil, errors.Wrapf(err, "failed to decode manifest %s", file.Name()) } + if len(raw.Raw) == 0 { // This can happen if the manifest contains only comments continue } + manifests = append(manifests, raw) } }