Add --reorder flag.

This commit is contained in:
Jeffrey Regan
2019-06-11 11:02:29 -07:00
parent 15a77fd2bb
commit 0fa2d9c32c
12 changed files with 200 additions and 38 deletions

2
go.mod
View File

@@ -27,7 +27,7 @@ require (
github.com/spf13/cobra v0.0.2 github.com/spf13/cobra v0.0.2
github.com/spf13/pflag v1.0.1 github.com/spf13/pflag v1.0.1
github.com/stretchr/testify v1.3.0 // indirect github.com/stretchr/testify v1.3.0 // indirect
golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d // indirect golang.org/x/tools v0.0.0-20190608022120-eacb66d2a7c3 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.2.1 gopkg.in/yaml.v2 v2.2.1
k8s.io/api v0.0.0-20180510062335-53d615ae3f44 k8s.io/api v0.0.0-20180510062335-53d615ae3f44

2
go.sum
View File

@@ -75,6 +75,8 @@ golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d h1:bt+R27hbE7uVf7PY9S6wpNg9Xo2WRe/XQT0uGq9RQQw= golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d h1:bt+R27hbE7uVf7PY9S6wpNg9Xo2WRe/XQT0uGq9RQQw=
golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190608022120-eacb66d2a7c3 h1:sU3tSV6wDhWsvf9NjL0FzRjgAmYnQL5NEhdmcN16UEg=
golang.org/x/tools v0.0.0-20190608022120-eacb66d2a7c3/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=

View File

@@ -1,4 +1,4 @@
/// Copyright 2019 The Kubernetes Authors. // Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
package build package build
@@ -28,6 +28,7 @@ type Options struct {
kustomizationPath string kustomizationPath string
outputPath string outputPath string
loadRestrictor loader.LoadRestrictorFunc loadRestrictor loader.LoadRestrictorFunc
outOrder reorderOutput
} }
// NewOptions creates a Options object // NewOptions creates a Options object
@@ -40,18 +41,20 @@ func NewOptions(p, o string) *Options {
} }
var examples = ` var examples = `
Use the file somedir/kustomization.yaml to generate a set of api resources: To generate the resources specified in 'someDir/kustomization.yaml', run
build somedir
Use a url pointing to a remote directory/kustomization.yaml to generate a set of api resources: kustomize build someDir
build url
The url should follow hashicorp/go-getter URL format described in The default argument to 'build' is '.' (the current working directory).
The argument can be a URL resolving to a directory
with a kustomization.yaml file, e.g.
kustomize build \
github.com/kubernetes-sigs/kustomize//examples/multibases/dev/?ref=v1.0.6
The URL should be formulated as described at
https://github.com/hashicorp/go-getter#url-format https://github.com/hashicorp/go-getter#url-format
url examples:
sigs.k8s.io/kustomize//examples/multibases?ref=v1.0.6
github.com/Liujingfang1/mysql
github.com/Liujingfang1/kustomize//examples/helloWorld?ref=repoUrl2
` `
// NewCmdBuild creates a new build command. // NewCmdBuild creates a new build command.
@@ -65,8 +68,8 @@ func NewCmdBuild(
pl := plugins.NewLoader(pluginConfig, rf) pl := plugins.NewLoader(pluginConfig, rf)
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "build [path]", Use: "build {path}",
Short: "Print current configuration per contents of " + pgmconfig.KustomizationFileNames[0], Short: "Print configuration per contents of " + pgmconfig.KustomizationFileNames[0],
Example: examples, Example: examples,
SilenceUsage: true, SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
@@ -82,10 +85,10 @@ func NewCmdBuild(
&o.outputPath, &o.outputPath,
"output", "o", "", "output", "o", "",
"If specified, write the build output to this path.") "If specified, write the build output to this path.")
loader.AddLoadRestrictionsFlag(cmd.Flags()) loader.AddFlagLoadRestrictor(cmd.Flags())
plugins.AddEnablePluginsFlag( plugins.AddFlagEnablePlugins(
cmd.Flags(), &pluginConfig.Enabled) cmd.Flags(), &pluginConfig.Enabled)
addFlagReorderOutput(cmd.Flags())
cmd.AddCommand(NewCmdBuildPrune(out, v, fSys, rf, ptf, pl)) cmd.AddCommand(NewCmdBuildPrune(out, v, fSys, rf, ptf, pl))
return cmd return cmd
} }
@@ -101,7 +104,11 @@ func (o *Options) Validate(args []string) (err error) {
} else { } else {
o.kustomizationPath = args[0] o.kustomizationPath = args[0]
} }
o.loadRestrictor, err = loader.ValidateLoadRestrictorFlag() o.loadRestrictor, err = loader.ValidateFlagLoadRestrictor()
if err != nil {
return err
}
o.outOrder, err = validateFlagReorderOutput()
return return
} }
@@ -153,11 +160,13 @@ func (o *Options) emitResources(
if o.outputPath != "" && fSys.IsDir(o.outputPath) { if o.outputPath != "" && fSys.IsDir(o.outputPath) {
return writeIndividualFiles(fSys, o.outputPath, m) return writeIndividualFiles(fSys, o.outputPath, m)
} }
// Done this way just to prove that overall sorting if o.outOrder == legacy {
// can be performed by a plugin. This particular // Done this way just to show how overall sorting
// plugin doesn't require configuration; just make // can be performed by a plugin. This particular
// it and call transform. // plugin doesn't require configuration; just make
builtin.NewPreferredOrderTransformerPlugin().Transform(m) // it and call transform.
builtin.NewLegacyOrderTransformerPlugin().Transform(m)
}
res, err := m.AsYaml() res, err := m.AsYaml()
if err != nil { if err != nil {
return err return err

View File

@@ -0,0 +1,50 @@
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package build
import (
"fmt"
"github.com/spf13/pflag"
)
//go:generate stringer -type=reorderOutput
type reorderOutput int
const (
unspecified reorderOutput = iota
none
legacy
)
const (
flagReorderOutputName = "reorder"
)
var (
flagReorderOutputValue = legacy.String()
flagReorderOutputHelp = "Reorder the resources just before output. " +
"Use '" + legacy.String() + "' to apply a legacy reordering (Namespaces first, Webhooks last, etc). " +
"Use '" + none.String() + "' to suppress a final reordering."
)
func addFlagReorderOutput(set *pflag.FlagSet) {
set.StringVar(
&flagReorderOutputValue, flagReorderOutputName,
legacy.String(), flagReorderOutputHelp)
}
func validateFlagReorderOutput() (reorderOutput, error) {
switch flagReorderOutputValue {
case none.String():
return none, nil
case legacy.String():
return legacy, nil
default:
return unspecified, fmt.Errorf(
"illegal flag value --%s %s; legal values: %v",
flagReorderOutputName, flagReorderOutputValue,
[]string{legacy.String(), none.String()})
}
}

View File

@@ -0,0 +1,25 @@
// Code generated by "stringer -type=reorderOutput"; DO NOT EDIT.
package build
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[unspecified-0]
_ = x[none-1]
_ = x[legacy-2]
}
const _reorderOutput_name = "unspecifiednonelegacy"
var _reorderOutput_index = [...]uint8{0, 11, 15, 21}
func (i reorderOutput) String() string {
if i < 0 || i >= reorderOutput(len(_reorderOutput_index)-1) {
return "reorderOutput(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _reorderOutput_name[_reorderOutput_index[i]:_reorderOutput_index[i+1]]
}

View File

@@ -186,6 +186,16 @@ func hint(a, b string) string {
func (th *KustTestHarness) AssertActualEqualsExpected( func (th *KustTestHarness) AssertActualEqualsExpected(
m resmap.ResMap, expected string) { m resmap.ResMap, expected string) {
th.assertActualEqualsExpected(m, expected, true)
}
func (th *KustTestHarness) AssertActualEqualsExpectedNoSort(
m resmap.ResMap, expected string) {
th.assertActualEqualsExpected(m, expected, false)
}
func (th *KustTestHarness) assertActualEqualsExpected(
m resmap.ResMap, expected string, doLegacySort bool) {
if m == nil { if m == nil {
th.t.Fatalf("Map should not be nil.") th.t.Fatalf("Map should not be nil.")
} }
@@ -194,8 +204,9 @@ func (th *KustTestHarness) AssertActualEqualsExpected(
if len(expected) > 0 && expected[0] == 10 { if len(expected) > 0 && expected[0] == 10 {
expected = expected[1:] expected = expected[1:]
} }
// The tests currently expect a particular ordering. if doLegacySort {
builtin.NewPreferredOrderTransformerPlugin().Transform(m) builtin.NewLegacyOrderTransformerPlugin().Transform(m)
}
actual, err := m.AsYaml() actual, err := m.AsYaml()
if err != nil { if err != nil {
th.t.Fatalf("Unexpected err: %v", err) th.t.Fatalf("Unexpected err: %v", err)

View File

@@ -43,13 +43,13 @@ var (
"This does, however, break the relocatability of the kustomization." "This does, however, break the relocatability of the kustomization."
) )
func AddLoadRestrictionsFlag(set *pflag.FlagSet) { func AddFlagLoadRestrictor(set *pflag.FlagSet) {
set.StringVar( set.StringVar(
&flagValue, flagName, &flagValue, flagName,
rootOnly.String(), flagHelp) rootOnly.String(), flagHelp)
} }
func ValidateLoadRestrictorFlag() (LoadRestrictorFunc, error) { func ValidateFlagLoadRestrictor() (LoadRestrictorFunc, error) {
switch flagValue { switch flagValue {
case rootOnly.String(): case rootOnly.String():
return RestrictionRootOnly, nil return RestrictionRootOnly, nil

View File

@@ -46,7 +46,7 @@ func NotEnabledErr(name string) error {
flagEnablePluginsHelp) flagEnablePluginsHelp)
} }
func AddEnablePluginsFlag(set *pflag.FlagSet, v *bool) { func AddFlagEnablePlugins(set *pflag.FlagSet, v *bool) {
set.BoolVar( set.BoolVar(
v, flagEnablePluginsName, v, flagEnablePluginsName,
false, flagEnablePluginsHelp) false, flagEnablePluginsHelp)

View File

@@ -17,14 +17,79 @@ limitations under the License.
package target_test package target_test
import ( import (
"sigs.k8s.io/kustomize/pkg/plugins"
"strings" "strings"
"testing" "testing"
"sigs.k8s.io/kustomize/pkg/kusttest" "sigs.k8s.io/kustomize/pkg/kusttest"
"sigs.k8s.io/kustomize/pkg/loader" "sigs.k8s.io/kustomize/pkg/loader"
"sigs.k8s.io/kustomize/pkg/plugins"
) )
// TODO(monopole): Make prefixsuffixtransformer changes
// needed to enable this test.
func disabledTestOrderPreserved(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/prod")
th.WriteK("/app/base", `
namePrefix: b-
resources:
- namespace.yaml
- role.yaml
- service.yaml
- deployment.yaml
`)
th.WriteF("/app/base/service.yaml", `
apiVersion: v1
kind: Service
metadata:
name: myService
`)
th.WriteF("/app/base/namespace.yaml", `
apiVersion: v1
kind: Namespace
metadata:
name: myNs
`)
th.WriteF("/app/base/role.yaml", `
apiVersion: v1
kind: Role
metadata:
name: myRole
`)
th.WriteF("/app/base/deployment.yaml", `
apiVersion: v1
kind: Deployment
metadata:
name: myDep
`)
th.WriteK("/app/prod", `
namePrefix: p-
resources:
- ../base
- service.yaml
- namespace.yaml
`)
th.WriteF("/app/prod/service.yaml", `
apiVersion: v1
kind: Service
metadata:
name: myService2
`)
th.WriteF("/app/prod/namespace.yaml", `
apiVersion: v1
kind: Namespace
metadata:
name: myNs2
`)
m, err := th.MakeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
th.AssertActualEqualsExpectedNoSort(m, `
TBD
./tr `)
}
func TestBaseInResourceList(t *testing.T) { func TestBaseInResourceList(t *testing.T) {
th := kusttest_test.NewKustTestHarness(t, "/app/prod") th := kusttest_test.NewKustTestHarness(t, "/app/prod")
th.WriteK("/app/prod", ` th.WriteK("/app/prod", `

View File

@@ -1,4 +1,4 @@
// Code generated by pluginator on PreferredOrderTransformer; DO NOT EDIT. // Code generated by pluginator on LegacyOrderTransformer; DO NOT EDIT.
package builtin package builtin
import ( import (
@@ -13,19 +13,19 @@ import (
// dependencies (like Namespace, StorageClass, etc.) // dependencies (like Namespace, StorageClass, etc.)
// first, and resources with a high number of dependencies // first, and resources with a high number of dependencies
// (like ValidatingWebhookConfiguration) last. // (like ValidatingWebhookConfiguration) last.
type PreferredOrderTransformerPlugin struct{} type LegacyOrderTransformerPlugin struct{}
func NewPreferredOrderTransformerPlugin() *PreferredOrderTransformerPlugin { func NewLegacyOrderTransformerPlugin() *LegacyOrderTransformerPlugin {
return &PreferredOrderTransformerPlugin{} return &LegacyOrderTransformerPlugin{}
} }
// Nothing needed for configuration. // Nothing needed for configuration.
func (p *PreferredOrderTransformerPlugin) Config( func (p *LegacyOrderTransformerPlugin) Config(
ldr ifc.Loader, rf *resmap.Factory, c []byte) (err error) { ldr ifc.Loader, rf *resmap.Factory, c []byte) (err error) {
return nil return nil
} }
func (p *PreferredOrderTransformerPlugin) Transform(m resmap.ResMap) error { func (p *LegacyOrderTransformerPlugin) Transform(m resmap.ResMap) error {
resources := make([]*resource.Resource, m.Size()) resources := make([]*resource.Resource, m.Size())
ids := m.AllIds() ids := m.AllIds()
sort.Sort(resmap.IdSlice(ids)) sort.Sort(resmap.IdSlice(ids))

View File

@@ -10,17 +10,17 @@ import (
"sigs.k8s.io/kustomize/plugin" "sigs.k8s.io/kustomize/plugin"
) )
func TestPreferredOrderTransformer(t *testing.T) { func TestLegacyOrderTransformer(t *testing.T) {
tc := plugin.NewEnvForTest(t).Set() tc := plugin.NewEnvForTest(t).Set()
defer tc.Reset() defer tc.Reset()
tc.BuildGoPlugin( tc.BuildGoPlugin(
"builtin", "", "PreferredOrderTransformer") "builtin", "", "LegacyOrderTransformer")
th := kusttest_test.NewKustTestPluginHarness(t, "/app") th := kusttest_test.NewKustTestPluginHarness(t, "/app")
rm := th.LoadAndRunTransformer(` rm := th.LoadAndRunTransformer(`
apiVersion: builtin apiVersion: builtin
kind: PreferredOrderTransformer kind: LegacyOrderTransformer
metadata: metadata:
name: notImportantHere name: notImportantHere
`, ` `, `