mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 20:24:09 +00:00
164 lines
5.1 KiB
Go
164 lines
5.1 KiB
Go
// Copyright 2019 The Kubernetes Authors.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package krusty
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
|
|
"sigs.k8s.io/kustomize/api/internal/builtins"
|
|
pLdr "sigs.k8s.io/kustomize/api/internal/plugins/loader"
|
|
"sigs.k8s.io/kustomize/api/internal/target"
|
|
"sigs.k8s.io/kustomize/api/internal/utils"
|
|
"sigs.k8s.io/kustomize/api/konfig"
|
|
fLdr "sigs.k8s.io/kustomize/api/loader"
|
|
"sigs.k8s.io/kustomize/api/provenance"
|
|
"sigs.k8s.io/kustomize/api/provider"
|
|
"sigs.k8s.io/kustomize/api/resmap"
|
|
"sigs.k8s.io/kustomize/api/types"
|
|
"sigs.k8s.io/kustomize/kyaml/errors"
|
|
"sigs.k8s.io/kustomize/kyaml/filesys"
|
|
"sigs.k8s.io/kustomize/kyaml/openapi"
|
|
)
|
|
|
|
// Kustomizer performs kustomizations.
|
|
//
|
|
// It's meant to behave similarly to the kustomize CLI, and can be
|
|
// used instead of performing an exec to a kustomize CLI subprocess.
|
|
// To use, load a filesystem with kustomization files (any
|
|
// number of overlays and bases), then make a Kustomizer
|
|
// injected with the given filesystem, then call Run.
|
|
type Kustomizer struct {
|
|
options *Options
|
|
depProvider *provider.DepProvider
|
|
}
|
|
|
|
// MakeKustomizer returns an instance of Kustomizer.
|
|
func MakeKustomizer(o *Options) *Kustomizer {
|
|
return &Kustomizer{
|
|
options: o,
|
|
depProvider: provider.NewDepProvider(),
|
|
}
|
|
}
|
|
|
|
// Run performs a kustomization.
|
|
//
|
|
// It reads given path from the given file system, interprets it as
|
|
// a kustomization.yaml file, perform the kustomization it represents,
|
|
// and return the resulting resources.
|
|
//
|
|
// Any files referenced by the kustomization must be present on the
|
|
// filesystem. One may call Run any number of times, on any number
|
|
// of internal paths (e.g. the filesystem may contain multiple overlays,
|
|
// and Run can be called on each of them).
|
|
func (b *Kustomizer) Run(
|
|
fSys filesys.FileSystem, path string) (resmap.ResMap, error) {
|
|
resmapFactory := resmap.NewFactory(b.depProvider.GetResourceFactory())
|
|
lr := fLdr.RestrictionNone
|
|
if b.options.LoadRestrictions == types.LoadRestrictionsRootOnly {
|
|
lr = fLdr.RestrictionRootOnly
|
|
}
|
|
ldr, err := fLdr.NewLoader(lr, path, fSys)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer ldr.Cleanup()
|
|
kt := target.NewKustTarget(
|
|
ldr,
|
|
b.depProvider.GetFieldValidator(),
|
|
resmapFactory,
|
|
// The plugin configs are always located on disk, regardless of the fSys passed in
|
|
pLdr.NewLoader(b.options.PluginConfig, resmapFactory, filesys.MakeFsOnDisk()),
|
|
)
|
|
err = kt.Load()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var bytes []byte
|
|
if openApiPath, exists := kt.Kustomization().OpenAPI["path"]; exists {
|
|
bytes, err = ldr.Load(openApiPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
err = openapi.SetSchema(kt.Kustomization().OpenAPI, bytes, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var m resmap.ResMap
|
|
m, err = kt.MakeCustomizedResMap()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
err = b.applySortOrder(m, kt)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if b.options.AddManagedbyLabel || utils.StringSliceContains(kt.Kustomization().BuildMetadata, types.ManagedByLabelOption) {
|
|
t := builtins.LabelTransformerPlugin{
|
|
Labels: map[string]string{
|
|
konfig.ManagedbyLabelKey: fmt.Sprintf("kustomize-%s", provenance.GetProvenance().Semver()),
|
|
},
|
|
FieldSpecs: []types.FieldSpec{{
|
|
Path: "metadata/labels",
|
|
CreateIfNotPresent: true,
|
|
}},
|
|
}
|
|
err = t.Transform(m)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
m.RemoveBuildAnnotations()
|
|
if !utils.StringSliceContains(kt.Kustomization().BuildMetadata, types.OriginAnnotations) {
|
|
err = m.RemoveOriginAnnotations()
|
|
if err != nil {
|
|
return nil, errors.WrapPrefixf(err, "failed to clean up origin tracking annotations")
|
|
}
|
|
}
|
|
if !utils.StringSliceContains(kt.Kustomization().BuildMetadata, types.TransformerAnnotations) {
|
|
err = m.RemoveTransformerAnnotations()
|
|
if err != nil {
|
|
return nil, errors.WrapPrefixf(err, "failed to clean up transformer annotations")
|
|
}
|
|
}
|
|
return m, nil
|
|
}
|
|
|
|
func (b *Kustomizer) applySortOrder(m resmap.ResMap, kt *target.KustTarget) error {
|
|
// Sort order can be defined in two places:
|
|
// - (new) kustomization file
|
|
// - (old) CLI flag
|
|
//
|
|
// We want the kustomization file to take precedence over the CLI flag.
|
|
// Eventually, we may want to move away from having a CLI flag altogether:
|
|
// https://github.com/kubernetes-sigs/kustomize/issues/3947
|
|
|
|
// Case 1: Sort order set in kustomization file.
|
|
if kt.Kustomization().SortOptions != nil {
|
|
// If set in CLI flag too, warn the user.
|
|
if b.options.Reorder != ReorderOptionUnspecified {
|
|
log.Println("Warning: Sorting order is set both in 'kustomization.yaml'" +
|
|
" ('sortOptions') and in a CLI flag ('--reorder'). Using the" +
|
|
" kustomization file over the CLI flag.")
|
|
}
|
|
pl := &builtins.SortOrderTransformerPlugin{
|
|
SortOptions: kt.Kustomization().SortOptions,
|
|
}
|
|
err := pl.Transform(m)
|
|
if err != nil {
|
|
return errors.Wrap(err)
|
|
}
|
|
} else if b.options.Reorder == ReorderOptionLegacy || b.options.Reorder == ReorderOptionUnspecified {
|
|
// Case 2: Sort order set in CLI flag only or not at all.
|
|
pl := &builtins.SortOrderTransformerPlugin{
|
|
SortOptions: &types.SortOptions{
|
|
Order: types.LegacySortOrder,
|
|
},
|
|
}
|
|
return errors.Wrap(pl.Transform(m))
|
|
}
|
|
return nil
|
|
}
|