mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-05-18 03:45:12 +00:00
* api: Add new types for customizeable resource ordering Signed-off-by: Yannis Zarkadas <yanniszark@arrikto.com> * plugins: Implement SortOrderTransformer plugin Implement the SortOrderTransformer plugin. This plugin allows the user to customize the order that kustomize will output resources in. The API for the plugin is the following: sortOptions: order: legacy | fifo legacySortOptions: orderFirst: - {GVK} orderLast: - {GVK} Signed-off-by: Yannis Zarkadas <yanniszark@arrikto.com> * plugins: Add boilerplate and generate code for new SortOrderTransformer Signed-off-by: Yannis Zarkadas <yanniszark@arrikto.com> * build: Add option to denote if the reorder flag was set by the user We want to take different actions if the reorder flag was set by the user or filled by the default value. Thus, we propagate this information from build to the krusty options. Signed-off-by: Yannis Zarkadas <yanniszark@gmail.com> * api/krusty: Ensure sort ordering works with CLI flag and kustomization 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 AND in CLI flag. Print a warning and let the kustomization file take precedence. Case 2: Sort order set in CLI flag only or not at all. Follow the CLI flag (defaults to legacy) and reorder at the end. Case 3: Sort order set in kustomization file only. Simply build the kustomization. Signed-off-by: Yannis Zarkadas <yanniszark@gmail.com> * krusty: Add e2e test for SortOrderTransformer Signed-off-by: Yannis Zarkadas <yanniszark@arrikto.com> * plugins: Purge LegacyOrderTransformer Signed-off-by: Yannis Zarkadas <yanniszark@gmail.com> * Update go.work.sum Signed-off-by: Yannis Zarkadas <yanniszark@gmail.com> * review: Make review changes Signed-off-by: Yannis Zarkadas <yanniszark@gmail.com> Signed-off-by: Yannis Zarkadas <yanniszark@arrikto.com> Signed-off-by: Yannis Zarkadas <yanniszark@gmail.com>
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
|
|
}
|