add -k flag to FilenameFlags in cli-runtime

pull/564/head
Jingfang Liu 2019-02-25 16:29:27 -08:00
parent 34699f3ff0
commit 46f4378bd9
9 changed files with 224 additions and 0 deletions

View File

@ -0,0 +1,7 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: the-map
data:
altGreeting: "Good Morning!"
enableRisky: "false"

View File

@ -0,0 +1,30 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: the-deployment
spec:
replicas: 3
template:
metadata:
labels:
deployment: hello
spec:
containers:
- name: the-container
image: monopole/hello:1
command: ["/hello",
"--port=8080",
"--enableRiskyFeature=$(ENABLE_RISKY)"]
ports:
- containerPort: 8080
env:
- name: ALT_GREETING
valueFrom:
configMapKeyRef:
name: the-map
key: altGreeting
- name: ENABLE_RISKY
valueFrom:
configMapKeyRef:
name: the-map
key: enableRisky

View File

@ -0,0 +1,5 @@
nameprefix: test-
resources:
- deployment.yaml
- service.yaml
- configMap.yaml

View File

@ -0,0 +1,12 @@
kind: Service
apiVersion: v1
metadata:
name: the-service
spec:
selector:
deployment: hello
type: LoadBalancer
ports:
- protocol: TCP
port: 8666
targetPort: 8080

View File

@ -0,0 +1,7 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: should-not-create-map
data:
altGreeting: "Good Morning!"
enableRisky: "false"

View File

@ -0,0 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
nameprefix: test-
resources:
- deployment.yaml
- service.yaml
- configMap.yaml

View File

@ -32,6 +32,7 @@ type FileNameFlags struct {
Usage string
Filenames *[]string
Kustomize *string
Recursive *bool
}
@ -48,6 +49,9 @@ func (o *FileNameFlags) ToOptions() resource.FilenameOptions {
if o.Filenames != nil {
options.Filenames = *o.Filenames
}
if o.Kustomize != nil {
options.Kustomize = *o.Kustomize
}
return options
}
@ -68,4 +72,8 @@ func (o *FileNameFlags) AddFlags(flags *pflag.FlagSet) {
}
flags.SetAnnotation("filename", cobra.BashCompFilenameExt, annotations)
}
if o.Kustomize != nil {
flags.StringVarP(o.Kustomize, "kustomize", "k", *o.Kustomize,
"Process a kustomization directory. This flag can't be used together with -f or -R.")
}
}

View File

@ -130,9 +130,28 @@ func IsUsageError(err error) bool {
type FilenameOptions struct {
Filenames []string
Kustomize string
Recursive bool
}
func (o *FilenameOptions) validate() []error {
var errs []error
if len(o.Filenames) > 0 && len(o.Kustomize) > 0 {
errs = append(errs, fmt.Errorf("only one of -f or -k can be specified"))
}
if len(o.Kustomize) > 0 && o.Recursive {
errs = append(errs, fmt.Errorf("-R is not allowed to work with -k"))
}
return errs
}
func (o *FilenameOptions) RequireFilenameOrKustomize() error {
if len(o.Filenames) == 0 && len(o.Kustomize) == 0 {
return fmt.Errorf("must specify one of -f and -k")
}
return nil
}
type resourceTuple struct {
Resource string
Name string
@ -195,6 +214,10 @@ func (b *Builder) AddError(err error) *Builder {
// If ContinueOnError() is set prior to this method, objects on the path that are not
// recognized will be ignored (but logged at V(2)).
func (b *Builder) FilenameParam(enforceNamespace bool, filenameOptions *FilenameOptions) *Builder {
if errs := filenameOptions.validate(); len(errs) > 0 {
b.errs = append(b.errs, errs...)
return b
}
recursive := filenameOptions.Recursive
paths := filenameOptions.Filenames
for _, s := range paths {
@ -215,6 +238,10 @@ func (b *Builder) FilenameParam(enforceNamespace bool, filenameOptions *Filename
b.Path(recursive, s)
}
}
if filenameOptions.Kustomize != "" {
b.paths = append(b.paths, &KustomizeVisitor{filenameOptions.Kustomize,
NewStreamVisitor(nil, b.mapper, filenameOptions.Kustomize, b.schema)})
}
if enforceNamespace {
b.RequireNamespace()

View File

@ -374,6 +374,62 @@ func writeTestFile(t *testing.T, path string, contents string) {
}
}
func TestFilenameOptionsValidate(t *testing.T) {
testcases := []struct {
filenames []string
kustomize string
recursive bool
errExp bool
msgExp string
}{
{
filenames: []string{"file"},
kustomize: "dir",
errExp: true,
msgExp: "only one of -f or -k can be specified",
},
{
kustomize: "dir",
recursive: true,
errExp: true,
msgExp: "-R is not allowed to work with -k",
},
{
filenames: []string{"file"},
errExp: false,
},
{
filenames: []string{"dir"},
recursive: true,
errExp: false,
},
{
kustomize: "dir",
errExp: false,
},
}
for _, testcase := range testcases {
o := &FilenameOptions{
Kustomize: testcase.kustomize,
Filenames: testcase.filenames,
Recursive: testcase.recursive,
}
errs := o.validate()
if testcase.errExp {
if len(errs) == 0 {
t.Fatalf("expected error not happened")
}
if errs[0].Error() != testcase.msgExp {
t.Fatalf("expected %s, but got %#v", testcase.msgExp, errs[0])
}
} else {
if len(errs) > 0 {
t.Fatalf("Unexpected error %#v", errs)
}
}
}
}
func TestPathBuilderWithMultiple(t *testing.T) {
// create test dirs
tmpDir, err := utiltesting.MkTmpdir("recursive_test_multiple")
@ -513,6 +569,70 @@ func TestDirectoryBuilder(t *testing.T) {
}
}
func TestKustomizeDirectoryBuilder(t *testing.T) {
tests := []struct {
directory string
expectErr bool
errMsg string
number int
expectedNames []string
}{
{
directory: "../../../artifacts/guestbook",
expectErr: true,
errMsg: "No kustomization file found",
},
// TODO(Liujingfang1): Fix this test in bazel test
//{
// directory: "../../../artifacts/kustomization",
// expectErr: false,
// expectedNames: []string{"test-the-map", "test-the-deployment", "test-the-service"},
//},
{
directory: "../../../artifacts/kustomization/should-not-load.yaml",
expectErr: true,
errMsg: "must be a directory to be a root",
},
}
for _, tt := range tests {
b := newDefaultBuilder().
FilenameParam(false, &FilenameOptions{Kustomize: tt.directory}).
NamespaceParam("test").DefaultNamespace()
test := &testVisitor{}
err := b.Do().Visit(test.Handle)
if tt.expectErr {
if err == nil {
t.Fatalf("expected error unhappened")
}
if !strings.Contains(err.Error(), tt.errMsg) {
t.Fatalf("expected %s but got %s", tt.errMsg, err.Error())
}
} else {
if err != nil || len(test.Infos) < tt.number {
t.Fatalf("unexpected response: %v %#v", err, test.Infos)
}
contained := func(name string) bool {
for _, info := range test.Infos {
if info.Name == name && info.Namespace == "test" && info.Object != nil {
return true
}
}
return false
}
allFound := true
for _, name := range tt.expectedNames {
if !contained(name) {
allFound = false
}
}
if !allFound {
t.Errorf("unexpected responses: %#v", test.Infos)
}
}
}
}
func TestNamespaceOverride(t *testing.T) {
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
w.WriteHeader(http.StatusOK)