Unverified Commit 371d8663 authored by Phillip Wittrock's avatar Phillip Wittrock Committed by GitHub

Revert "Enable kustomize in kubectl"

parent 3287dec0
...@@ -4115,106 +4115,6 @@ ...@@ -4115,106 +4115,6 @@
"Rev": "8e7ff06bf0e2d3289061230af203e430a15b6dcc" "Rev": "8e7ff06bf0e2d3289061230af203e430a15b6dcc"
}, },
{ {
"ImportPath": "sigs.k8s.io/kustomize/pkg/commands/build",
"Comment": "v1.0.10-69-gef51cceff55b17",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/constants",
"Comment": "v1.0.10-69-gef51cceff55b17",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/expansion",
"Comment": "v1.0.10-69-gef51cceff55b17",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/factory",
"Comment": "v1.0.10-69-gef51cceff55b17",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/fs",
"Comment": "v1.0.10-69-gef51cceff55b17",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/gvk",
"Comment": "v1.0.10-69-gef51cceff55b17",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/ifc",
"Comment": "v1.0.10-69-gef51cceff55b17",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/ifc/transformer",
"Comment": "v1.0.10-69-gef51cceff55b17",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/internal/error",
"Comment": "v1.0.10-69-gef51cceff55b17",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/loader",
"Comment": "v1.0.10-69-gef51cceff55b17",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/patch",
"Comment": "v1.0.10-69-gef51cceff55b17",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/patch/transformer",
"Comment": "v1.0.10-69-gef51cceff55b17",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/resid",
"Comment": "v1.0.10-69-gef51cceff55b17",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/resmap",
"Comment": "v1.0.10-69-gef51cceff55b17",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/resource",
"Comment": "v1.0.10-69-gef51cceff55b17",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/target",
"Comment": "v1.0.10-69-gef51cceff55b17",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/transformers",
"Comment": "v1.0.10-69-gef51cceff55b17",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/transformers/config",
"Comment": "v1.0.10-69-gef51cceff55b17",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig",
"Comment": "v1.0.10-69-gef51cceff55b17",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/types",
"Comment": "v1.0.10-69-gef51cceff55b17",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/yaml", "ImportPath": "sigs.k8s.io/yaml",
"Comment": "v1.1.0", "Comment": "v1.1.0",
"Rev": "fd68e9863619f6ec2fdd8625fe1f02e7c877e480" "Rev": "fd68e9863619f6ec2fdd8625fe1f02e7c877e480"
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
- k8s.io/api/core/v1 - k8s.io/api/core/v1
- k8s.io/cli-runtime/pkg/genericclioptions/printers - k8s.io/cli-runtime/pkg/genericclioptions/printers
- k8s.io/cli-runtime/pkg/genericclioptions/resource - k8s.io/cli-runtime/pkg/genericclioptions/resource
- k8s.io/cli-runtime/pkg/kustomize/k8sdeps
- baseImportPath: "./vendor/k8s.io/apimachinery/" - baseImportPath: "./vendor/k8s.io/apimachinery/"
allowedImports: allowedImports:
......
...@@ -113,7 +113,6 @@ filegroup( ...@@ -113,7 +113,6 @@ filegroup(
"//staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook:all-srcs", "//staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook:all-srcs",
"//staging/src/k8s.io/cli-runtime/artifacts:all-srcs", "//staging/src/k8s.io/cli-runtime/artifacts:all-srcs",
"//staging/src/k8s.io/cli-runtime/pkg/genericclioptions:all-srcs", "//staging/src/k8s.io/cli-runtime/pkg/genericclioptions:all-srcs",
"//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps:all-srcs",
"//staging/src/k8s.io/client-go/deprecated-dynamic:all-srcs", "//staging/src/k8s.io/client-go/deprecated-dynamic:all-srcs",
"//staging/src/k8s.io/client-go/discovery:all-srcs", "//staging/src/k8s.io/client-go/discovery:all-srcs",
"//staging/src/k8s.io/client-go/dynamic:all-srcs", "//staging/src/k8s.io/client-go/dynamic:all-srcs",
......
...@@ -7,50 +7,14 @@ ...@@ -7,50 +7,14 @@
], ],
"Deps": [ "Deps": [
{ {
"ImportPath": "github.com/PuerkitoBio/purell",
"Rev": "8a290539e2e8629dbc4e6bad948158f790ec31f4"
},
{
"ImportPath": "github.com/PuerkitoBio/urlesc",
"Rev": "5bd2802263f21d8788851d5305584c82a5c75d7e"
},
{
"ImportPath": "github.com/davecgh/go-spew/spew", "ImportPath": "github.com/davecgh/go-spew/spew",
"Rev": "782f4967f2dc4564575ca782fe2d04090b5faca8" "Rev": "782f4967f2dc4564575ca782fe2d04090b5faca8"
}, },
{ {
"ImportPath": "github.com/emicklei/go-restful",
"Rev": "ff4f55a206334ef123e4f79bbf348980da81ca46"
},
{
"ImportPath": "github.com/emicklei/go-restful/log",
"Rev": "ff4f55a206334ef123e4f79bbf348980da81ca46"
},
{
"ImportPath": "github.com/evanphx/json-patch", "ImportPath": "github.com/evanphx/json-patch",
"Rev": "36442dbdb585210f8d5a1b45e67aa323c197d5c4" "Rev": "36442dbdb585210f8d5a1b45e67aa323c197d5c4"
}, },
{ {
"ImportPath": "github.com/ghodss/yaml",
"Rev": "c7ce16629ff4cd059ed96ed06419dd3856fd3577"
},
{
"ImportPath": "github.com/go-openapi/jsonpointer",
"Rev": "ef5f0afec364d3b9396b7b77b43dbe26bf1f8004"
},
{
"ImportPath": "github.com/go-openapi/jsonreference",
"Rev": "8483a886a90412cd6858df4ea3483dce9c8e35a3"
},
{
"ImportPath": "github.com/go-openapi/spec",
"Rev": "5bae59e25b21498baea7f9d46e9c147ec106a42e"
},
{
"ImportPath": "github.com/go-openapi/swag",
"Rev": "5899d5c5e619fda5fa86e14795a835f473ca284c"
},
{
"ImportPath": "github.com/gogo/protobuf/proto", "ImportPath": "github.com/gogo/protobuf/proto",
"Rev": "342cbe0a04158f6dcb03ca0079991a51a4248c02" "Rev": "342cbe0a04158f6dcb03ca0079991a51a4248c02"
}, },
...@@ -119,18 +83,6 @@ ...@@ -119,18 +83,6 @@
"Rev": "ab8a2e0c74be9d3be70b3184d9acc634935ded82" "Rev": "ab8a2e0c74be9d3be70b3184d9acc634935ded82"
}, },
{ {
"ImportPath": "github.com/mailru/easyjson/buffer",
"Rev": "2f5df55504ebc322e4d52d34df6a1f5b503bf26d"
},
{
"ImportPath": "github.com/mailru/easyjson/jlexer",
"Rev": "2f5df55504ebc322e4d52d34df6a1f5b503bf26d"
},
{
"ImportPath": "github.com/mailru/easyjson/jwriter",
"Rev": "2f5df55504ebc322e4d52d34df6a1f5b503bf26d"
},
{
"ImportPath": "github.com/modern-go/concurrent", "ImportPath": "github.com/modern-go/concurrent",
"Rev": "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" "Rev": "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94"
}, },
...@@ -143,10 +95,6 @@ ...@@ -143,10 +95,6 @@
"Rev": "5f041e8faa004a95c88a202771f4cc3e991971e6" "Rev": "5f041e8faa004a95c88a202771f4cc3e991971e6"
}, },
{ {
"ImportPath": "github.com/pkg/errors",
"Rev": "645ef00459ed84a119197bfb8d8205042c6df63d"
},
{
"ImportPath": "github.com/pmezard/go-difflib/difflib", "ImportPath": "github.com/pmezard/go-difflib/difflib",
"Rev": "d8ed2627bdf02c080bf22230dbb337003b7aba2d" "Rev": "d8ed2627bdf02c080bf22230dbb337003b7aba2d"
}, },
...@@ -243,10 +191,6 @@ ...@@ -243,10 +191,6 @@
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/width",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/time/rate", "ImportPath": "golang.org/x/time/rate",
"Rev": "f51c12702a4d776e4c1fa9b0fabab841babae631" "Rev": "f51c12702a4d776e4c1fa9b0fabab841babae631"
}, },
...@@ -411,10 +355,6 @@ ...@@ -411,10 +355,6 @@
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/api/validation",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1", "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
...@@ -427,10 +367,6 @@ ...@@ -427,10 +367,6 @@
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/validation",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1beta1", "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1beta1",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
...@@ -511,10 +447,6 @@ ...@@ -511,10 +447,6 @@
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/mergepatch",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/naming", "ImportPath": "k8s.io/apimachinery/pkg/util/naming",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
...@@ -531,10 +463,6 @@ ...@@ -531,10 +463,6 @@
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/strategicpatch",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/validation", "ImportPath": "k8s.io/apimachinery/pkg/util/validation",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
...@@ -555,10 +483,6 @@ ...@@ -555,10 +483,6 @@
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/json",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect", "ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
...@@ -651,14 +575,6 @@ ...@@ -651,14 +575,6 @@
"Rev": "8139d8cb77af419532b33dfa7dd09fbc5f1d344f" "Rev": "8139d8cb77af419532b33dfa7dd09fbc5f1d344f"
}, },
{ {
"ImportPath": "k8s.io/kube-openapi/pkg/common",
"Rev": "c59034cc13d587f5ef4e85ca0ade0c1866ae8e1d"
},
{
"ImportPath": "k8s.io/kube-openapi/pkg/util/proto",
"Rev": "c59034cc13d587f5ef4e85ca0ade0c1866ae8e1d"
},
{
"ImportPath": "k8s.io/client-go/discovery", "ImportPath": "k8s.io/client-go/discovery",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
...@@ -703,86 +619,6 @@ ...@@ -703,86 +619,6 @@
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
{ {
"ImportPath": "sigs.k8s.io/kustomize/pkg/commands/build",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/constants",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/expansion",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/factory",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/fs",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/gvk",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/ifc",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/ifc/transformer",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/internal/error",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/loader",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/patch",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/patch/transformer",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/resid",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/resmap",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/resource",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/target",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/transformers",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/transformers/config",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/types",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/yaml", "ImportPath": "sigs.k8s.io/yaml",
"Rev": "fd68e9863619f6ec2fdd8625fe1f02e7c877e480" "Rev": "fd68e9863619f6ec2fdd8625fe1f02e7c877e480"
} }
......
apiVersion: v1
kind: ConfigMap
metadata:
name: the-map
data:
altGreeting: "Good Morning!"
enableRisky: "false"
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
nameprefix: test-
resources:
- deployment.yaml
- service.yaml
- configMap.yaml
kind: Service
apiVersion: v1
metadata:
name: the-service
spec:
selector:
deployment: hello
type: LoadBalancer
ports:
- protocol: TCP
port: 8666
targetPort: 8080
\ No newline at end of file
...@@ -35,16 +35,12 @@ go_library( ...@@ -35,16 +35,12 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/yaml:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library",
"//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps:go_default_library",
"//staging/src/k8s.io/client-go/discovery:go_default_library", "//staging/src/k8s.io/client-go/discovery:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/scheme:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/scheme:go_default_library",
"//staging/src/k8s.io/client-go/rest:go_default_library", "//staging/src/k8s.io/client-go/rest:go_default_library",
"//staging/src/k8s.io/client-go/restmapper:go_default_library", "//staging/src/k8s.io/client-go/restmapper:go_default_library",
"//vendor/golang.org/x/text/encoding/unicode:go_default_library", "//vendor/golang.org/x/text/encoding/unicode:go_default_library",
"//vendor/golang.org/x/text/transform:go_default_library", "//vendor/golang.org/x/text/transform:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/commands/build:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/constants:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/fs:go_default_library",
], ],
) )
......
...@@ -465,49 +465,28 @@ func TestPathBuilderWithMultipleInvalid(t *testing.T) { ...@@ -465,49 +465,28 @@ func TestPathBuilderWithMultipleInvalid(t *testing.T) {
} }
func TestDirectoryBuilder(t *testing.T) { func TestDirectoryBuilder(t *testing.T) {
tests := []struct {
directories []string
singleItem bool
number int
expectedNames []string
}{
{[]string{"../../../artifacts/guestbook"}, false, 3, []string{"redis-master"}},
{[]string{"../../../artifacts/kustomization"}, true, 3, []string{"test-the-deployment"}},
{[]string{"../../../artifacts/guestbook", "../../../artifacts/kustomization"}, false, 6, []string{"redis-master", "test-the-deployment"}},
}
for _, tt := range tests {
b := newDefaultBuilder(). b := newDefaultBuilder().
FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: tt.directories}). FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{"../../../artifacts/guestbook"}}).
NamespaceParam("test").DefaultNamespace() NamespaceParam("test").DefaultNamespace()
test := &testVisitor{} test := &testVisitor{}
singleItemImplied := false singleItemImplied := false
err := b.Do().IntoSingleItemImplied(&singleItemImplied).Visit(test.Handle) err := b.Do().IntoSingleItemImplied(&singleItemImplied).Visit(test.Handle)
if err != nil || singleItemImplied != tt.singleItem || len(test.Infos) < tt.number { if err != nil || singleItemImplied || len(test.Infos) < 3 {
t.Fatalf("unexpected response: %v %t %#v", err, singleItemImplied, test.Infos) t.Fatalf("unexpected response: %v %t %#v", err, singleItemImplied, test.Infos)
} }
contained := func(name string) bool { found := false
for _, info := range test.Infos { for _, info := range test.Infos {
if info.Name == name && info.Namespace == "test" && info.Object != nil { if info.Name == "redis-master" && info.Namespace == "test" && info.Object != nil {
return true found = true
break
} }
} }
return false if !found {
}
allFound := true
for _, name := range tt.expectedNames {
if !contained(name) {
allFound = false
}
}
if !allFound {
t.Errorf("unexpected responses: %#v", test.Infos) t.Errorf("unexpected responses: %#v", test.Infos)
} }
}
} }
func TestNamespaceOverride(t *testing.T) { func TestNamespaceOverride(t *testing.T) {
......
...@@ -20,7 +20,6 @@ import ( ...@@ -20,7 +20,6 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"net/http" "net/http"
"net/url" "net/url"
"os" "os"
...@@ -39,10 +38,6 @@ import ( ...@@ -39,10 +38,6 @@ import (
utilerrors "k8s.io/apimachinery/pkg/util/errors" utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apimachinery/pkg/util/yaml" "k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/apimachinery/pkg/watch" "k8s.io/apimachinery/pkg/watch"
"k8s.io/cli-runtime/pkg/kustomize/k8sdeps"
"sigs.k8s.io/kustomize/pkg/commands/build"
"sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/fs"
) )
const ( const (
...@@ -457,10 +452,7 @@ func ExpandPathsToFileVisitors(mapper *mapper, paths string, recursive bool, ext ...@@ -457,10 +452,7 @@ func ExpandPathsToFileVisitors(mapper *mapper, paths string, recursive bool, ext
if err != nil { if err != nil {
return err return err
} }
if isKustomizationDir(path) {
visitors = append(visitors, NewKustomizationVisitor(mapper, path, schema))
return filepath.SkipDir
}
if fi.IsDir() { if fi.IsDir() {
if path != paths && !recursive { if path != paths && !recursive {
return filepath.SkipDir return filepath.SkipDir
...@@ -471,10 +463,7 @@ func ExpandPathsToFileVisitors(mapper *mapper, paths string, recursive bool, ext ...@@ -471,10 +463,7 @@ func ExpandPathsToFileVisitors(mapper *mapper, paths string, recursive bool, ext
if path != paths && ignoreFile(path, extensions) { if path != paths && ignoreFile(path, extensions) {
return nil return nil
} }
if filepath.Base(path) == constants.KustomizationFileName {
visitors = append(visitors, NewKustomizationVisitor(mapper, filepath.Dir(path), schema))
return nil
}
visitor := &FileVisitor{ visitor := &FileVisitor{
Path: path, Path: path,
StreamVisitor: NewStreamVisitor(nil, mapper, path, schema), StreamVisitor: NewStreamVisitor(nil, mapper, path, schema),
...@@ -490,13 +479,6 @@ func ExpandPathsToFileVisitors(mapper *mapper, paths string, recursive bool, ext ...@@ -490,13 +479,6 @@ func ExpandPathsToFileVisitors(mapper *mapper, paths string, recursive bool, ext
return visitors, nil return visitors, nil
} }
func isKustomizationDir(path string) bool {
if _, err := os.Stat(filepath.Join(path, constants.KustomizationFileName)); err == nil {
return true
}
return false
}
// FileVisitor is wrapping around a StreamVisitor, to handle open/close files // FileVisitor is wrapping around a StreamVisitor, to handle open/close files
type FileVisitor struct { type FileVisitor struct {
Path string Path string
...@@ -525,37 +507,6 @@ func (v *FileVisitor) Visit(fn VisitorFunc) error { ...@@ -525,37 +507,6 @@ func (v *FileVisitor) Visit(fn VisitorFunc) error {
return v.StreamVisitor.Visit(fn) return v.StreamVisitor.Visit(fn)
} }
// KustomizationVisitor prorvides the output of kustomization build
type KustomizationVisitor struct {
Path string
*StreamVisitor
}
// Visit in a KustomizationVisitor build the kustomization output
func (v *KustomizationVisitor) Visit(fn VisitorFunc) error {
fSys := fs.MakeRealFS()
f := k8sdeps.NewFactory()
var out bytes.Buffer
cmd := build.NewCmdBuild(&out, fSys, f.ResmapF, f.TransformerF)
cmd.SetArgs([]string{v.Path})
// we want to silence usage, error output, and any future output from cobra
// we will get error output as a golang error from execute
cmd.SetOutput(ioutil.Discard)
_, err := cmd.ExecuteC()
if err != nil {
return err
}
v.StreamVisitor.Reader = bytes.NewReader(out.Bytes())
return v.StreamVisitor.Visit(fn)
}
func NewKustomizationVisitor(mapper *mapper, path string, schema ContentValidator) *KustomizationVisitor {
return &KustomizationVisitor{
Path: path,
StreamVisitor: NewStreamVisitor(nil, mapper, path, schema),
}
}
// StreamVisitor reads objects from an io.Reader and walks them. A stream visitor can only be // StreamVisitor reads objects from an io.Reader and walks them. A stream visitor can only be
// visited once. // visited once.
// TODO: depends on objects being in JSON format before being passed to decode - need to implement // TODO: depends on objects being in JSON format before being passed to decode - need to implement
......
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"factory.go",
],
importmap = "k8s.io/kubernetes/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps",
importpath = "k8s.io/cli-runtime/pkg/kustomize/k8sdeps",
visibility = ["//visibility:public"],
deps = [
"//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct:go_default_library",
"//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer:go_default_library",
"//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/validator:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/factory:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret:all-srcs",
"//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct:all-srcs",
"//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer:all-srcs",
"//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/validator:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"configmapfactory.go",
"kv.go",
"secretfactory.go",
],
importmap = "k8s.io/kubernetes/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret",
importpath = "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret",
visibility = ["//visibility:public"],
deps = [
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/fs:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/ifc:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/types:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = [
"configmapfactory_test.go",
"kv_test.go",
],
embed = [":go_default_library"],
deps = [
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/fs:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/loader:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/types:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package configmapandsecret generates configmaps and secrets per generator rules.
package configmapandsecret
import (
"fmt"
"path"
"strings"
"github.com/pkg/errors"
"k8s.io/api/core/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/util/validation"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/types"
)
// ConfigMapFactory makes ConfigMaps.
type ConfigMapFactory struct {
fSys fs.FileSystem
ldr ifc.Loader
}
// NewConfigMapFactory returns a new ConfigMapFactory.
func NewConfigMapFactory(
fSys fs.FileSystem, l ifc.Loader) *ConfigMapFactory {
return &ConfigMapFactory{fSys: fSys, ldr: l}
}
func (f *ConfigMapFactory) makeFreshConfigMap(
args *types.ConfigMapArgs) *corev1.ConfigMap {
cm := &corev1.ConfigMap{}
cm.APIVersion = "v1"
cm.Kind = "ConfigMap"
cm.Name = args.Name
cm.Data = map[string]string{}
return cm
}
// MakeConfigMap returns a new ConfigMap, or nil and an error.
func (f *ConfigMapFactory) MakeConfigMap(
args *types.ConfigMapArgs, options *types.GeneratorOptions) (*corev1.ConfigMap, error) {
var all []kvPair
var err error
cm := f.makeFreshConfigMap(args)
pairs, err := keyValuesFromEnvFile(f.ldr, args.EnvSource)
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf(
"env source file: %s",
args.EnvSource))
}
all = append(all, pairs...)
pairs, err = keyValuesFromLiteralSources(args.LiteralSources)
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf(
"literal sources %v", args.LiteralSources))
}
all = append(all, pairs...)
pairs, err = keyValuesFromFileSources(f.ldr, args.FileSources)
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf(
"file sources: %v", args.FileSources))
}
all = append(all, pairs...)
for _, kv := range all {
err = addKvToConfigMap(cm, kv.key, kv.value)
if err != nil {
return nil, err
}
}
if options != nil {
cm.SetLabels(options.Labels)
cm.SetAnnotations(options.Annotations)
}
return cm, nil
}
func keyValuesFromLiteralSources(sources []string) ([]kvPair, error) {
var kvs []kvPair
for _, s := range sources {
k, v, err := parseLiteralSource(s)
if err != nil {
return nil, err
}
kvs = append(kvs, kvPair{key: k, value: v})
}
return kvs, nil
}
func keyValuesFromFileSources(ldr ifc.Loader, sources []string) ([]kvPair, error) {
var kvs []kvPair
for _, s := range sources {
k, fPath, err := parseFileSource(s)
if err != nil {
return nil, err
}
content, err := ldr.Load(fPath)
if err != nil {
return nil, err
}
kvs = append(kvs, kvPair{key: k, value: string(content)})
}
return kvs, nil
}
func keyValuesFromEnvFile(l ifc.Loader, path string) ([]kvPair, error) {
if path == "" {
return nil, nil
}
content, err := l.Load(path)
if err != nil {
return nil, err
}
return keyValuesFromLines(content)
}
// addKvToConfigMap adds the given key and data to the given config map.
// Error if key invalid, or already exists.
func addKvToConfigMap(configMap *v1.ConfigMap, keyName, data string) error {
// Note, the rules for ConfigMap keys are the exact same as the ones for SecretKeys.
if errs := validation.IsConfigMapKey(keyName); len(errs) != 0 {
return fmt.Errorf("%q is not a valid key name for a ConfigMap: %s", keyName, strings.Join(errs, ";"))
}
if _, entryExists := configMap.Data[keyName]; entryExists {
return fmt.Errorf("cannot add key %s, another key by that name already exists: %v", keyName, configMap.Data)
}
configMap.Data[keyName] = data
return nil
}
// parseFileSource parses the source given.
//
// Acceptable formats include:
// 1. source-path: the basename will become the key name
// 2. source-name=source-path: the source-name will become the key name and
// source-path is the path to the key file.
//
// Key names cannot include '='.
func parseFileSource(source string) (keyName, filePath string, err error) {
numSeparators := strings.Count(source, "=")
switch {
case numSeparators == 0:
return path.Base(source), source, nil
case numSeparators == 1 && strings.HasPrefix(source, "="):
return "", "", fmt.Errorf("key name for file path %v missing", strings.TrimPrefix(source, "="))
case numSeparators == 1 && strings.HasSuffix(source, "="):
return "", "", fmt.Errorf("file path for key name %v missing", strings.TrimSuffix(source, "="))
case numSeparators > 1:
return "", "", errors.New("key names or file paths cannot contain '='")
default:
components := strings.Split(source, "=")
return components[0], components[1], nil
}
}
// parseLiteralSource parses the source key=val pair into its component pieces.
// This functionality is distinguished from strings.SplitN(source, "=", 2) since
// it returns an error in the case of empty keys, values, or a missing equals sign.
func parseLiteralSource(source string) (keyName, value string, err error) {
// leading equal is invalid
if strings.Index(source, "=") == 0 {
return "", "", fmt.Errorf("invalid literal source %v, expected key=value", source)
}
// split after the first equal (so values can have the = character)
items := strings.SplitN(source, "=", 2)
if len(items) != 2 {
return "", "", fmt.Errorf("invalid literal source %v, expected key=value", source)
}
return items[0], strings.Trim(items[1], "\"'"), nil
}
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package configmapandsecret
import (
"reflect"
"testing"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/loader"
"sigs.k8s.io/kustomize/pkg/types"
)
func makeEnvConfigMap(name string) *corev1.ConfigMap {
return &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "ConfigMap",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Data: map[string]string{
"DB_USERNAME": "admin",
"DB_PASSWORD": "somepw",
},
}
}
func makeFileConfigMap(name string) *corev1.ConfigMap {
return &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "ConfigMap",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Data: map[string]string{
"app-init.ini": `FOO=bar
BAR=baz
`,
},
}
}
func makeLiteralConfigMap(name string) *corev1.ConfigMap {
cm := &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "ConfigMap",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Data: map[string]string{
"a": "x",
"b": "y",
"c": "Hello World",
"d": "true",
},
}
cm.SetLabels(map[string]string{"foo": "bar"})
return cm
}
func TestConstructConfigMap(t *testing.T) {
type testCase struct {
description string
input types.ConfigMapArgs
options *types.GeneratorOptions
expected *corev1.ConfigMap
}
testCases := []testCase{
{
description: "construct config map from env",
input: types.ConfigMapArgs{
Name: "envConfigMap",
DataSources: types.DataSources{
EnvSource: "configmap/app.env",
},
},
options: nil,
expected: makeEnvConfigMap("envConfigMap"),
},
{
description: "construct config map from file",
input: types.ConfigMapArgs{
Name: "fileConfigMap",
DataSources: types.DataSources{
FileSources: []string{"configmap/app-init.ini"},
},
},
options: nil,
expected: makeFileConfigMap("fileConfigMap"),
},
{
description: "construct config map from literal",
input: types.ConfigMapArgs{
Name: "literalConfigMap",
DataSources: types.DataSources{
LiteralSources: []string{"a=x", "b=y", "c=\"Hello World\"", "d='true'"},
},
},
options: &types.GeneratorOptions{
Labels: map[string]string{
"foo": "bar",
},
},
expected: makeLiteralConfigMap("literalConfigMap"),
},
}
fSys := fs.MakeFakeFS()
fSys.WriteFile("/configmap/app.env", []byte("DB_USERNAME=admin\nDB_PASSWORD=somepw\n"))
fSys.WriteFile("/configmap/app-init.ini", []byte("FOO=bar\nBAR=baz\n"))
f := NewConfigMapFactory(fSys, loader.NewFileLoaderAtRoot(fSys))
for _, tc := range testCases {
cm, err := f.MakeConfigMap(&tc.input, tc.options)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if !reflect.DeepEqual(*cm, *tc.expected) {
t.Fatalf("in testcase: %q updated:\n%#v\ndoesn't match expected:\n%#v\n", tc.description, *cm, tc.expected)
}
}
}
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package configmapandsecret
import (
"bufio"
"bytes"
"fmt"
"os"
"strings"
"unicode"
"unicode/utf8"
"k8s.io/apimachinery/pkg/util/validation"
)
// kvPair represents a key value pair.
type kvPair struct {
key string
value string
}
var utf8bom = []byte{0xEF, 0xBB, 0xBF}
// keyValuesFromLines parses given content in to a list of key-value pairs.
func keyValuesFromLines(content []byte) ([]kvPair, error) {
var kvs []kvPair
scanner := bufio.NewScanner(bytes.NewReader(content))
currentLine := 0
for scanner.Scan() {
// Process the current line, retrieving a key/value pair if
// possible.
scannedBytes := scanner.Bytes()
kv, err := kvFromLine(scannedBytes, currentLine)
if err != nil {
return nil, err
}
currentLine++
if len(kv.key) == 0 {
// no key means line was empty or a comment
continue
}
kvs = append(kvs, kv)
}
return kvs, nil
}
// kvFromLine returns a kv with blank key if the line is empty or a comment.
// The value will be retrieved from the environment if necessary.
func kvFromLine(line []byte, currentLine int) (kvPair, error) {
kv := kvPair{}
if !utf8.Valid(line) {
return kv, fmt.Errorf("line %d has invalid utf8 bytes : %v", line, string(line))
}
// We trim UTF8 BOM from the first line of the file but no others
if currentLine == 0 {
line = bytes.TrimPrefix(line, utf8bom)
}
// trim the line from all leading whitespace first
line = bytes.TrimLeftFunc(line, unicode.IsSpace)
// If the line is empty or a comment, we return a blank key/value pair.
if len(line) == 0 || line[0] == '#' {
return kv, nil
}
data := strings.SplitN(string(line), "=", 2)
key := data[0]
if errs := validation.IsEnvVarName(key); len(errs) != 0 {
return kv, fmt.Errorf("%q is not a valid key name: %s", key, strings.Join(errs, ";"))
}
if len(data) == 2 {
kv.value = data[1]
} else {
// No value (no `=` in the line) is a signal to obtain the value
// from the environment.
kv.value = os.Getenv(key)
}
kv.key = key
return kv, nil
}
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package configmapandsecret
import (
"reflect"
"testing"
)
func TestKeyValuesFromLines(t *testing.T) {
tests := []struct {
desc string
content string
expectedPairs []kvPair
expectedErr bool
}{
{
desc: "valid kv content parse",
content: `
k1=v1
k2=v2
`,
expectedPairs: []kvPair{
{key: "k1", value: "v1"},
{key: "k2", value: "v2"},
},
expectedErr: false,
},
{
desc: "content with comments",
content: `
k1=v1
#k2=v2
`,
expectedPairs: []kvPair{
{key: "k1", value: "v1"},
},
expectedErr: false,
},
// TODO: add negative testcases
}
for _, test := range tests {
pairs, err := keyValuesFromLines([]byte(test.content))
if test.expectedErr && err == nil {
t.Fatalf("%s should not return error", test.desc)
}
if !reflect.DeepEqual(pairs, test.expectedPairs) {
t.Errorf("%s should succeed, got:%v exptected:%v", test.desc, pairs, test.expectedPairs)
}
}
}
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package configmapandsecret
import (
"context"
"fmt"
"log"
"os/exec"
"path/filepath"
"strings"
"time"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/util/validation"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/types"
)
const (
defaultCommandTimeout = 5 * time.Second
)
// SecretFactory makes Secrets.
type SecretFactory struct {
fSys fs.FileSystem
wd string
}
// NewSecretFactory returns a new SecretFactory.
func NewSecretFactory(fSys fs.FileSystem, wd string) *SecretFactory {
return &SecretFactory{fSys: fSys, wd: wd}
}
func (f *SecretFactory) makeFreshSecret(args *types.SecretArgs) *corev1.Secret {
s := &corev1.Secret{}
s.APIVersion = "v1"
s.Kind = "Secret"
s.Name = args.Name
s.Type = corev1.SecretType(args.Type)
if s.Type == "" {
s.Type = corev1.SecretTypeOpaque
}
s.Data = map[string][]byte{}
return s
}
// MakeSecret returns a new secret.
func (f *SecretFactory) MakeSecret(args *types.SecretArgs, options *types.GeneratorOptions) (*corev1.Secret, error) {
var all []kvPair
var err error
s := f.makeFreshSecret(args)
timeout := defaultCommandTimeout
if args.TimeoutSeconds != nil {
log.Println("SecretArgs.TimeoutSeconds will be deprected in next release. Please use GeneratorOptions.TimeoutSeconds instread.")
timeout = time.Duration(*args.TimeoutSeconds) * time.Second
}
pairs, err := f.keyValuesFromEnvFileCommand(args.EnvCommand, timeout, options)
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf(
"env source file: %s",
args.EnvCommand))
}
all = append(all, pairs...)
pairs, err = f.keyValuesFromCommands(args.Commands, timeout, options)
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf(
"commands %v", args.Commands))
}
all = append(all, pairs...)
for _, kv := range all {
err = addKvToSecret(s, kv.key, kv.value)
if err != nil {
return nil, err
}
}
if options != nil {
s.SetLabels(options.Labels)
s.SetAnnotations(options.Annotations)
}
return s, nil
}
func addKvToSecret(secret *corev1.Secret, keyName, data string) error {
// Note, the rules for SecretKeys keys are the exact same as the ones for ConfigMap.
if errs := validation.IsConfigMapKey(keyName); len(errs) != 0 {
return fmt.Errorf("%q is not a valid key name for a Secret: %s", keyName, strings.Join(errs, ";"))
}
if _, entryExists := secret.Data[keyName]; entryExists {
return fmt.Errorf("cannot add key %s, another key by that name already exists", keyName)
}
secret.Data[keyName] = []byte(data)
return nil
}
func (f *SecretFactory) keyValuesFromEnvFileCommand(cmd string, timeout time.Duration, options *types.GeneratorOptions) ([]kvPair, error) {
content, err := f.createSecretKey(cmd, timeout, options)
if err != nil {
return nil, err
}
return keyValuesFromLines(content)
}
func (f *SecretFactory) keyValuesFromCommands(sources map[string]string, timeout time.Duration, options *types.GeneratorOptions) ([]kvPair, error) {
var kvs []kvPair
for k, cmd := range sources {
content, err := f.createSecretKey(cmd, timeout, options)
if err != nil {
return nil, err
}
kvs = append(kvs, kvPair{key: k, value: string(content)})
}
return kvs, nil
}
// Run a command, return its output as the secret.
func (f *SecretFactory) createSecretKey(command string, timeout time.Duration, options *types.GeneratorOptions) ([]byte, error) {
if !f.fSys.IsDir(f.wd) {
f.wd = filepath.Dir(f.wd)
if !f.fSys.IsDir(f.wd) {
return nil, errors.New("not a directory: " + f.wd)
}
}
if options != nil && options.TimeoutSeconds != nil {
t := time.Duration(*options.TimeoutSeconds) * time.Second
if t > timeout {
timeout = t
}
}
var commands []string
if options == nil || len(options.Shell) == 0 {
commands = []string{"sh", "-c", command}
} else {
commands = append(options.Shell, command)
}
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
cmd := exec.CommandContext(ctx, commands[0], commands[1:]...)
cmd.Dir = f.wd
return cmd.Output()
}
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// It's possible that kustomize's features will be vendored into
// the kubernetes/kubernetes repo and made available to kubectl
// commands, while at the same time the kustomize program will
// continue to exist as an independent CLI. Vendoring snapshots
// would be taken just before a kubectl release.
//
// This creates a problem in that freestanding-kustomize depends on
// (for example):
//
// https://github.com/kubernetes/apimachinery/
// tree/master/pkg/util/yaml
//
// It vendors that package into
// sigs.k8s.io/kustomize/vendor/k8s.io/apimachinery/
//
// Whereas kubectl-kustomize would have to depend on the "staging"
// version of this code, located at
//
// https://github.com/kubernetes/kubernetes/
// blob/master/staging/src/k8s.io/apimachinery/pkg/util/yaml
//
// which is "vendored" via symlinks:
// k8s.io/kubernetes/vendor/k8s.io/apimachinery
// is a symlink to
// ../../staging/src/k8s.io/apimachinery
//
// The staging version is the canonical, under-development
// version of the code that kubectl depends on, whereas the packages
// at kubernetes/apimachinery are periodic snapshots of staging made
// for outside tools to depend on.
//
// apimachinery isn't the only package that poses this problem, just
// using it as a specific example.
//
// The kubectl binary cannot vendor in kustomize code that in
// turn vendors in the non-staging packages.
//
// One way to fix some of this would be to copy code - a hard fork.
// This has all the problems associated with a hard forking.
//
// Another way would be to break the kustomize repo into three:
//
// (1) kustomize - repo with the main() function,
// vendoring (2) and (3).
//
// (2) kustomize-libs - packages used by (1) with no
// apimachinery dependence.
//
// (3) kustomize-k8sdeps - A thin code layer that depends
// on (vendors) apimachinery to provide thin implementations
// to interfaces used in (2).
//
// The kubectl repo would then vendor from (2) only, and have
// a local implementation of (3). With that in mind, it's clear
// that (3) doesn't have to be a repo; the kustomize version of
// the thin layer can live directly in (1).
//
// This package is the code in (3), meant for kustomize.
package k8sdeps
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package k8sdeps provides kustomize factory with k8s dependencies
package k8sdeps
import (
"k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct"
"k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer"
"k8s.io/cli-runtime/pkg/kustomize/k8sdeps/validator"
"sigs.k8s.io/kustomize/pkg/factory"
)
// NewFactory creates an instance of KustFactory using k8sdeps factories
func NewFactory() *factory.KustFactory {
return factory.NewKustFactory(
kunstruct.NewKunstructuredFactoryImpl(),
validator.NewKustValidator(),
transformer.NewFactoryImpl(),
)
}
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"factory.go",
"helper.go",
"kunstruct.go",
],
importmap = "k8s.io/kubernetes/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct",
importpath = "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct",
visibility = ["//visibility:public"],
deps = [
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
"//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/fs:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/gvk:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/ifc:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/types:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = [
"factory_test.go",
"kunstruct_test.go",
],
embed = [":go_default_library"],
deps = ["//vendor/sigs.k8s.io/kustomize/pkg/ifc:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package kunstruct
import (
"bytes"
"fmt"
"io"
"strings"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/types"
)
// KunstructuredFactoryImpl hides construction using apimachinery types.
type KunstructuredFactoryImpl struct {
cmFactory *configmapandsecret.ConfigMapFactory
secretFactory *configmapandsecret.SecretFactory
}
var _ ifc.KunstructuredFactory = &KunstructuredFactoryImpl{}
// NewKunstructuredFactoryImpl returns a factory.
func NewKunstructuredFactoryImpl() ifc.KunstructuredFactory {
return &KunstructuredFactoryImpl{}
}
// SliceFromBytes returns a slice of Kunstructured.
func (kf *KunstructuredFactoryImpl) SliceFromBytes(
in []byte) ([]ifc.Kunstructured, error) {
decoder := yaml.NewYAMLOrJSONDecoder(bytes.NewReader(in), 1024)
var result []ifc.Kunstructured
var err error
for err == nil || isEmptyYamlError(err) {
var out unstructured.Unstructured
err = decoder.Decode(&out)
if err == nil {
err = kf.validate(out)
if err != nil {
return nil, err
}
result = append(result, &UnstructAdapter{Unstructured: out})
}
}
if err != io.EOF {
return nil, err
}
return result, nil
}
func isEmptyYamlError(err error) bool {
return strings.Contains(err.Error(), "is missing in 'null'")
}
// FromMap returns an instance of Kunstructured.
func (kf *KunstructuredFactoryImpl) FromMap(
m map[string]interface{}) ifc.Kunstructured {
return &UnstructAdapter{Unstructured: unstructured.Unstructured{Object: m}}
}
// MakeConfigMap returns an instance of Kunstructured for ConfigMap
func (kf *KunstructuredFactoryImpl) MakeConfigMap(args *types.ConfigMapArgs, options *types.GeneratorOptions) (ifc.Kunstructured, error) {
cm, err := kf.cmFactory.MakeConfigMap(args, options)
if err != nil {
return nil, err
}
return NewKunstructuredFromObject(cm)
}
// MakeSecret returns an instance of Kunstructured for Secret
func (kf *KunstructuredFactoryImpl) MakeSecret(args *types.SecretArgs, options *types.GeneratorOptions) (ifc.Kunstructured, error) {
sec, err := kf.secretFactory.MakeSecret(args, options)
if err != nil {
return nil, err
}
return NewKunstructuredFromObject(sec)
}
// Set sets loader, filesystem and workdirectory
func (kf *KunstructuredFactoryImpl) Set(fs fs.FileSystem, ldr ifc.Loader) {
kf.cmFactory = configmapandsecret.NewConfigMapFactory(fs, ldr)
kf.secretFactory = configmapandsecret.NewSecretFactory(fs, ldr.Root())
}
// validate validates that u has kind and name
func (kf *KunstructuredFactoryImpl) validate(u unstructured.Unstructured) error {
if u.GetName() == "" {
return fmt.Errorf("Missing metadata.name in object %v", u)
}
if u.GetKind() == "" {
return fmt.Errorf("Missing kind in object %v", u)
}
return nil
}
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package kunstruct
import (
"reflect"
"testing"
"sigs.k8s.io/kustomize/pkg/ifc"
)
func TestSliceFromBytes(t *testing.T) {
factory := NewKunstructuredFactoryImpl()
testConfigMap := factory.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "winnie",
},
})
tests := []struct {
name string
input []byte
expectedOut []ifc.Kunstructured
expectedErr bool
}{
{
name: "garbage",
input: []byte("garbageIn: garbageOut"),
expectedOut: []ifc.Kunstructured{},
expectedErr: true,
},
{
name: "noBytes",
input: []byte{},
expectedOut: []ifc.Kunstructured{},
expectedErr: false,
},
{
name: "goodJson",
input: []byte(`
{"apiVersion":"v1","kind":"ConfigMap","metadata":{"name":"winnie"}}
`),
expectedOut: []ifc.Kunstructured{testConfigMap},
expectedErr: false,
},
{
name: "goodYaml1",
input: []byte(`
apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
`),
expectedOut: []ifc.Kunstructured{testConfigMap},
expectedErr: false,
},
{
name: "goodYaml2",
input: []byte(`
apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
---
apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
`),
expectedOut: []ifc.Kunstructured{testConfigMap, testConfigMap},
expectedErr: false,
},
{
name: "garbageInOneOfTwoObjects",
input: []byte(`
apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
---
WOOOOOOOOOOOOOOOOOOOOOOOOT: woot
`),
expectedOut: []ifc.Kunstructured{},
expectedErr: true,
},
{
name: "Missing .metadata.name in object",
input: []byte(`
apiVersion: v1
kind: Namespace
metadata:
annotations:
foo: bar
`),
expectedOut: nil,
expectedErr: true,
},
}
for _, test := range tests {
rs, err := factory.SliceFromBytes(test.input)
if test.expectedErr && err == nil {
t.Fatalf("%v: should return error", test.name)
}
if !test.expectedErr && err != nil {
t.Fatalf("%v: unexpected error: %s", test.name, err)
}
if len(rs) != len(test.expectedOut) {
t.Fatalf("%s: length mismatch %d != %d",
test.name, len(rs), len(test.expectedOut))
}
for i := range rs {
if !reflect.DeepEqual(test.expectedOut[i], rs[i]) {
t.Fatalf("%s: Got: %v\nexpected:%v",
test.name, test.expectedOut[i], rs[i])
}
}
}
}
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package kunstruct provides unstructured from api machinery and factory for creating unstructured
package kunstruct
import (
"fmt"
"strings"
)
func parseFields(path string) ([]string, error) {
if !strings.Contains(path, "[") {
return strings.Split(path, "."), nil
}
var fields []string
start := 0
insideParentheses := false
for i := range path {
switch path[i] {
case '.':
if !insideParentheses {
fields = append(fields, path[start:i])
start = i + 1
}
case '[':
if !insideParentheses {
if i == start {
start = i + 1
} else {
fields = append(fields, path[start:i])
start = i + 1
}
insideParentheses = true
} else {
return nil, fmt.Errorf("nested parentheses are not allowed: %s", path)
}
case ']':
if insideParentheses {
fields = append(fields, path[start:i])
start = i + 1
insideParentheses = false
} else {
return nil, fmt.Errorf("Invalid field path %s", path)
}
}
}
if start < len(path)-1 {
fields = append(fields, path[start:])
}
for i, f := range fields {
if strings.HasPrefix(f, "\"") || strings.HasPrefix(f, "'") {
fields[i] = strings.Trim(f, "\"'")
}
}
return fields, nil
}
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package kunstruct provides unstructured from api machinery and factory for creating unstructured
package kunstruct
import (
"encoding/json"
"fmt"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"sigs.k8s.io/kustomize/pkg/gvk"
"sigs.k8s.io/kustomize/pkg/ifc"
)
var _ ifc.Kunstructured = &UnstructAdapter{}
// UnstructAdapter wraps unstructured.Unstructured from
// https://github.com/kubernetes/apimachinery/blob/master/
// pkg/apis/meta/v1/unstructured/unstructured.go
// to isolate dependence on apimachinery.
type UnstructAdapter struct {
unstructured.Unstructured
}
// NewKunstructuredFromObject returns a new instance of Kunstructured.
func NewKunstructuredFromObject(obj runtime.Object) (ifc.Kunstructured, error) {
// Convert obj to a byte stream, then convert that to JSON (Unstructured).
marshaled, err := json.Marshal(obj)
if err != nil {
return &UnstructAdapter{}, err
}
var u unstructured.Unstructured
err = u.UnmarshalJSON(marshaled)
// creationTimestamp always 'null', remove it
u.SetCreationTimestamp(metav1.Time{})
return &UnstructAdapter{Unstructured: u}, err
}
// GetGvk returns the Gvk name of the object.
func (fs *UnstructAdapter) GetGvk() gvk.Gvk {
x := fs.GroupVersionKind()
return gvk.Gvk{
Group: x.Group,
Version: x.Version,
Kind: x.Kind,
}
}
// Copy provides a copy behind an interface.
func (fs *UnstructAdapter) Copy() ifc.Kunstructured {
return &UnstructAdapter{*fs.DeepCopy()}
}
// Map returns the unstructured content map.
func (fs *UnstructAdapter) Map() map[string]interface{} {
return fs.Object
}
// SetMap overrides the unstructured content map.
func (fs *UnstructAdapter) SetMap(m map[string]interface{}) {
fs.Object = m
}
// GetFieldValue returns value at the given fieldpath.
func (fs *UnstructAdapter) GetFieldValue(path string) (string, error) {
fields, err := parseFields(path)
if err != nil {
return "", err
}
s, found, err := unstructured.NestedString(
fs.UnstructuredContent(), fields...)
if found || err != nil {
return s, err
}
return "", fmt.Errorf("no field named '%s'", path)
}
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package kunstruct
import (
"testing"
)
func TestGetFieldValue(t *testing.T) {
factory := NewKunstructuredFactoryImpl()
kunstructured := factory.FromMap(map[string]interface{}{
"Kind": "Service",
"metadata": map[string]interface{}{
"labels": map[string]string{
"app": "application-name",
},
"name": "service-name",
},
"spec": map[string]interface{}{
"ports": map[string]interface{}{
"port": "80",
},
},
"this": map[string]interface{}{
"is": map[string]interface{}{
"aNumber": 1000,
"aNilValue": nil,
"anEmptyMap": map[string]interface{}{},
"unrecognizable": testing.InternalExample{
Name: "fooBar",
},
},
},
})
tests := []struct {
name string
pathToField string
expectedValue string
errorExpected bool
errorMsg string
}{
{
name: "oneField",
pathToField: "Kind",
expectedValue: "Service",
errorExpected: false,
},
{
name: "twoFields",
pathToField: "metadata.name",
expectedValue: "service-name",
errorExpected: false,
},
{
name: "threeFields",
pathToField: "spec.ports.port",
expectedValue: "80",
errorExpected: false,
},
{
name: "empty",
pathToField: "",
errorExpected: true,
errorMsg: "no field named ''",
},
{
name: "emptyDotEmpty",
pathToField: ".",
errorExpected: true,
errorMsg: "no field named '.'",
},
{
name: "twoFieldsOneMissing",
pathToField: "metadata.banana",
errorExpected: true,
errorMsg: "no field named 'metadata.banana'",
},
{
name: "deeperMissingField",
pathToField: "this.is.aDeep.field.that.does.not.exist",
errorExpected: true,
errorMsg: "no field named 'this.is.aDeep.field.that.does.not.exist'",
},
{
name: "emptyMap",
pathToField: "this.is.anEmptyMap",
errorExpected: true,
errorMsg: ".this.is.anEmptyMap accessor error: map[] is of the type map[string]interface {}, expected string",
},
{
name: "numberAsValue",
pathToField: "this.is.aNumber",
errorExpected: true,
errorMsg: ".this.is.aNumber accessor error: 1000 is of the type int, expected string",
},
{
name: "nilAsValue",
pathToField: "this.is.aNilValue",
errorExpected: true,
errorMsg: ".this.is.aNilValue accessor error: <nil> is of the type <nil>, expected string",
},
{
name: "unrecognizable",
pathToField: "this.is.unrecognizable.Name",
errorExpected: true,
errorMsg: ".this.is.unrecognizable.Name accessor error: {fooBar <nil> false} is of the type testing.InternalExample, expected map[string]interface{}",
},
}
for _, test := range tests {
s, err := kunstructured.GetFieldValue(test.pathToField)
if test.errorExpected {
if err == nil {
t.Fatalf("%q; path %q - should return error, but no error returned",
test.name, test.pathToField)
}
if test.errorMsg != err.Error() {
t.Fatalf("%q; path %q - expected error: \"%s\", got error: \"%v\"",
test.name, test.pathToField, test.errorMsg, err.Error())
}
continue
}
if err != nil {
t.Fatalf("%q; path %q - unexpected error %v",
test.name, test.pathToField, err)
}
if test.expectedValue != s {
t.Fatalf("%q; Got: %s expected: %s",
test.name, s, test.expectedValue)
}
}
}
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["factory.go"],
importmap = "k8s.io/kubernetes/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer",
importpath = "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer",
visibility = ["//visibility:public"],
deps = [
"//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash:go_default_library",
"//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/resource:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/transformers:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash:all-srcs",
"//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package transformer provides transformer factory
package transformer
import (
"k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash"
"k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch"
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/pkg/transformers"
)
// FactoryImpl makes patch transformer and name hash transformer
type FactoryImpl struct{}
// NewFactoryImpl makes a new factoryImpl instance
func NewFactoryImpl() *FactoryImpl {
return &FactoryImpl{}
}
// MakePatchTransformer makes a new patch transformer
func (p *FactoryImpl) MakePatchTransformer(slice []*resource.Resource, rf *resource.Factory) (transformers.Transformer, error) {
return patch.NewPatchTransformer(slice, rf)
}
// MakeHashTransformer makes a new name hash transformer
func (p *FactoryImpl) MakeHashTransformer() transformers.Transformer {
return hash.NewNameHashTransformer()
}
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"hash.go",
"namehash.go",
],
importmap = "k8s.io/kubernetes/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash",
importpath = "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash",
visibility = ["//visibility:public"],
deps = [
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/resmap:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/transformers:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = [
"hash_test.go",
"namehash_test.go",
],
embed = [":go_default_library"],
deps = [
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/gvk:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/ifc:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/resid:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/resmap:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/resource:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package hash
import (
"crypto/sha256"
"encoding/json"
"fmt"
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
// KustHash compute hash for unstructured objects
type KustHash struct{}
// NewKustHash returns a KustHash object
func NewKustHash() *KustHash {
return &KustHash{}
}
// Hash returns a hash of either a ConfigMap or a Secret
func (h *KustHash) Hash(m map[string]interface{}) (string, error) {
u := unstructured.Unstructured{
Object: m,
}
kind := u.GetKind()
switch kind {
case "ConfigMap":
cm, err := unstructuredToConfigmap(u)
if err != nil {
return "", err
}
return ConfigMapHash(cm)
case "Secret":
sec, err := unstructuredToSecret(u)
if err != nil {
return "", err
}
return SecretHash(sec)
default:
return "", fmt.Errorf("type %s is supported for hashing in %v", kind, m)
}
}
// ConfigMapHash returns a hash of the ConfigMap.
// The Data, Kind, and Name are taken into account.
func ConfigMapHash(cm *v1.ConfigMap) (string, error) {
encoded, err := encodeConfigMap(cm)
if err != nil {
return "", err
}
h, err := encodeHash(hash(encoded))
if err != nil {
return "", err
}
return h, nil
}
// SecretHash returns a hash of the Secret.
// The Data, Kind, Name, and Type are taken into account.
func SecretHash(sec *v1.Secret) (string, error) {
encoded, err := encodeSecret(sec)
if err != nil {
return "", err
}
h, err := encodeHash(hash(encoded))
if err != nil {
return "", err
}
return h, nil
}
// encodeConfigMap encodes a ConfigMap.
// Data, Kind, and Name are taken into account.
func encodeConfigMap(cm *v1.ConfigMap) (string, error) {
// json.Marshal sorts the keys in a stable order in the encoding
m := map[string]interface{}{"kind": "ConfigMap", "name": cm.Name, "data": cm.Data}
if len(cm.BinaryData) > 0 {
m["binaryData"] = cm.BinaryData
}
data, err := json.Marshal(m)
if err != nil {
return "", err
}
return string(data), nil
}
// encodeSecret encodes a Secret.
// Data, Kind, Name, and Type are taken into account.
func encodeSecret(sec *v1.Secret) (string, error) {
// json.Marshal sorts the keys in a stable order in the encoding
data, err := json.Marshal(map[string]interface{}{"kind": "Secret", "type": sec.Type, "name": sec.Name, "data": sec.Data})
if err != nil {
return "", err
}
return string(data), nil
}
// encodeHash extracts the first 40 bits of the hash from the hex string
// (1 hex char represents 4 bits), and then maps vowels and vowel-like hex
// characters to consonants to prevent bad words from being formed (the theory
// is that no vowels makes it really hard to make bad words). Since the string
// is hex, the only vowels it can contain are 'a' and 'e'.
// We picked some arbitrary consonants to map to from the same character set as GenerateName.
// See: https://github.com/kubernetes/apimachinery/blob/dc1f89aff9a7509782bde3b68824c8043a3e58cc/pkg/util/rand/rand.go#L75
// If the hex string contains fewer than ten characters, returns an error.
func encodeHash(hex string) (string, error) {
if len(hex) < 10 {
return "", fmt.Errorf("the hex string must contain at least 10 characters")
}
enc := []rune(hex[:10])
for i := range enc {
switch enc[i] {
case '0':
enc[i] = 'g'
case '1':
enc[i] = 'h'
case '3':
enc[i] = 'k'
case 'a':
enc[i] = 'm'
case 'e':
enc[i] = 't'
}
}
return string(enc), nil
}
// hash hashes `data` with sha256 and returns the hex string
func hash(data string) string {
return fmt.Sprintf("%x", sha256.Sum256([]byte(data)))
}
func unstructuredToConfigmap(u unstructured.Unstructured) (*v1.ConfigMap, error) {
marshaled, err := json.Marshal(u.Object)
if err != nil {
return nil, err
}
var out v1.ConfigMap
err = json.Unmarshal(marshaled, &out)
return &out, err
}
func unstructuredToSecret(u unstructured.Unstructured) (*v1.Secret, error) {
marshaled, err := json.Marshal(u.Object)
if err != nil {
return nil, err
}
var out v1.Secret
err = json.Unmarshal(marshaled, &out)
return &out, err
}
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package hash
import (
"reflect"
"strings"
"testing"
"k8s.io/api/core/v1"
"sigs.k8s.io/kustomize/pkg/gvk"
)
var service = gvk.Gvk{Version: "v1", Kind: "Service"}
var secret = gvk.Gvk{Version: "v1", Kind: "Secret"}
var cmap = gvk.Gvk{Version: "v1", Kind: "ConfigMap"}
var deploy = gvk.Gvk{Group: "apps", Version: "v1", Kind: "Deployment"}
func TestConfigMapHash(t *testing.T) {
cases := []struct {
desc string
cm *v1.ConfigMap
hash string
err string
}{
// empty map
{"empty data", &v1.ConfigMap{Data: map[string]string{}, BinaryData: map[string][]byte{}}, "42745tchd9", ""},
// one key
{"one key", &v1.ConfigMap{Data: map[string]string{"one": ""}}, "9g67k2htb6", ""},
// three keys (tests sorting order)
{"three keys", &v1.ConfigMap{Data: map[string]string{"two": "2", "one": "", "three": "3"}}, "f5h7t85m9b", ""},
// empty binary data map
{"empty binary data", &v1.ConfigMap{BinaryData: map[string][]byte{}}, "dk855m5d49", ""},
// one key with binary data
{"one key with binary data", &v1.ConfigMap{BinaryData: map[string][]byte{"one": []byte("")}}, "mk79584b8c", ""},
// three keys with binary data (tests sorting order)
{"three keys with binary data", &v1.ConfigMap{BinaryData: map[string][]byte{"two": []byte("2"), "one": []byte(""), "three": []byte("3")}}, "t458mc6db2", ""},
// two keys, one with string and another with binary data
{"two keys with one each", &v1.ConfigMap{Data: map[string]string{"one": ""}, BinaryData: map[string][]byte{"two": []byte("")}}, "698h7c7t9m", ""},
}
for _, c := range cases {
h, err := ConfigMapHash(c.cm)
if SkipRest(t, c.desc, err, c.err) {
continue
}
if c.hash != h {
t.Errorf("case %q, expect hash %q but got %q", c.desc, c.hash, h)
}
}
}
func TestSecretHash(t *testing.T) {
cases := []struct {
desc string
secret *v1.Secret
hash string
err string
}{
// empty map
{"empty data", &v1.Secret{Type: "my-type", Data: map[string][]byte{}}, "t75bgf6ctb", ""},
// one key
{"one key", &v1.Secret{Type: "my-type", Data: map[string][]byte{"one": []byte("")}}, "74bd68bm66", ""},
// three keys (tests sorting order)
{"three keys", &v1.Secret{Type: "my-type", Data: map[string][]byte{"two": []byte("2"), "one": []byte(""), "three": []byte("3")}}, "dgcb6h9tmk", ""},
}
for _, c := range cases {
h, err := SecretHash(c.secret)
if SkipRest(t, c.desc, err, c.err) {
continue
}
if c.hash != h {
t.Errorf("case %q, expect hash %q but got %q", c.desc, c.hash, h)
}
}
}
func TestEncodeConfigMap(t *testing.T) {
cases := []struct {
desc string
cm *v1.ConfigMap
expect string
err string
}{
// empty map
{"empty data", &v1.ConfigMap{Data: map[string]string{}}, `{"data":{},"kind":"ConfigMap","name":""}`, ""},
// one key
{"one key", &v1.ConfigMap{Data: map[string]string{"one": ""}}, `{"data":{"one":""},"kind":"ConfigMap","name":""}`, ""},
// three keys (tests sorting order)
{"three keys", &v1.ConfigMap{Data: map[string]string{"two": "2", "one": "", "three": "3"}},
`{"data":{"one":"","three":"3","two":"2"},"kind":"ConfigMap","name":""}`, ""},
// empty binary map
{"empty data", &v1.ConfigMap{BinaryData: map[string][]byte{}}, `{"data":null,"kind":"ConfigMap","name":""}`, ""},
// one key with binary data
{"one key", &v1.ConfigMap{BinaryData: map[string][]byte{"one": []byte("")}},
`{"binaryData":{"one":""},"data":null,"kind":"ConfigMap","name":""}`, ""},
// three keys with binary data (tests sorting order)
{"three keys", &v1.ConfigMap{BinaryData: map[string][]byte{"two": []byte("2"), "one": []byte(""), "three": []byte("3")}},
`{"binaryData":{"one":"","three":"Mw==","two":"Mg=="},"data":null,"kind":"ConfigMap","name":""}`, ""},
// two keys, one string and one binary values
{"two keys with one each", &v1.ConfigMap{Data: map[string]string{"one": ""}, BinaryData: map[string][]byte{"two": []byte("")}},
`{"binaryData":{"two":""},"data":{"one":""},"kind":"ConfigMap","name":""}`, ""},
}
for _, c := range cases {
s, err := encodeConfigMap(c.cm)
if SkipRest(t, c.desc, err, c.err) {
continue
}
if s != c.expect {
t.Errorf("case %q, expect %q but got %q from encode %#v", c.desc, c.expect, s, c.cm)
}
}
}
func TestEncodeSecret(t *testing.T) {
cases := []struct {
desc string
secret *v1.Secret
expect string
err string
}{
// empty map
{"empty data", &v1.Secret{Type: "my-type", Data: map[string][]byte{}}, `{"data":{},"kind":"Secret","name":"","type":"my-type"}`, ""},
// one key
{"one key", &v1.Secret{Type: "my-type", Data: map[string][]byte{"one": []byte("")}}, `{"data":{"one":""},"kind":"Secret","name":"","type":"my-type"}`, ""},
// three keys (tests sorting order) - note json.Marshal base64 encodes the values because they come in as []byte
{"three keys", &v1.Secret{
Type: "my-type",
Data: map[string][]byte{"two": []byte("2"), "one": []byte(""), "three": []byte("3")},
},
`{"data":{"one":"","three":"Mw==","two":"Mg=="},"kind":"Secret","name":"","type":"my-type"}`, ""},
}
for _, c := range cases {
s, err := encodeSecret(c.secret)
if SkipRest(t, c.desc, err, c.err) {
continue
}
if s != c.expect {
t.Errorf("case %q, expect %q but got %q from encode %#v", c.desc, c.expect, s, c.secret)
}
}
}
func TestHash(t *testing.T) {
// hash the empty string to be sure that sha256 is being used
expect := "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
sum := hash("")
if expect != sum {
t.Errorf("expected hash %q but got %q", expect, sum)
}
}
// warn devs who change types that they might have to update a hash function
// not perfect, as it only checks the number of top-level fields
func TestTypeStability(t *testing.T) {
errfmt := `case %q, expected %d fields but got %d
Depending on the field(s) you added, you may need to modify the hash function for this type.
To guide you: the hash function targets fields that comprise the contents of objects,
not their metadata (e.g. the Data of a ConfigMap, but nothing in ObjectMeta).
`
cases := []struct {
typeName string
obj interface{}
expect int
}{
{"ConfigMap", v1.ConfigMap{}, 4},
{"Secret", v1.Secret{}, 5},
}
for _, c := range cases {
val := reflect.ValueOf(c.obj)
if num := val.NumField(); c.expect != num {
t.Errorf(errfmt, c.typeName, c.expect, num)
}
}
}
// SkipRest returns true if there was a non-nil error or if we expected an error that didn't happen,
// and logs the appropriate error on the test object.
// The return value indicates whether we should skip the rest of the test case due to the error result.
func SkipRest(t *testing.T, desc string, err error, contains string) bool {
if err != nil {
if len(contains) == 0 {
t.Errorf("case %q, expect nil error but got %q", desc, err.Error())
} else if !strings.Contains(err.Error(), contains) {
t.Errorf("case %q, expect error to contain %q but got %q", desc, contains, err.Error())
}
return true
} else if len(contains) > 0 {
t.Errorf("case %q, expect error to contain %q but got nil error", desc, contains)
return true
}
return false
}
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package hash
import (
"fmt"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/transformers"
)
type nameHashTransformer struct{}
var _ transformers.Transformer = &nameHashTransformer{}
// NewNameHashTransformer construct a nameHashTransformer.
func NewNameHashTransformer() transformers.Transformer {
return &nameHashTransformer{}
}
// Transform appends hash to generated resources.
func (o *nameHashTransformer) Transform(m resmap.ResMap) error {
for _, res := range m {
if res.IsGenerated() {
h, err := NewKustHash().Hash(res.Map())
if err != nil {
return err
}
res.SetName(fmt.Sprintf("%s-%s", res.GetName(), h))
}
}
return nil
}
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package hash
import (
"reflect"
"testing"
"k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/resid"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/resource"
)
func TestNameHashTransformer(t *testing.T) {
rf := resource.NewFactory(
kunstruct.NewKunstructuredFactoryImpl())
objs := resmap.ResMap{
resid.NewResId(cmap, "cm1"): rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "cm1",
},
}),
resid.NewResId(deploy, "deploy1"): rf.FromMap(
map[string]interface{}{
"group": "apps",
"apiVersion": "v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "deploy1",
},
"spec": map[string]interface{}{
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"old-label": "old-value",
},
},
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"image": "nginx:1.7.9",
},
},
},
},
},
}),
resid.NewResId(service, "svc1"): rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "Service",
"metadata": map[string]interface{}{
"name": "svc1",
},
"spec": map[string]interface{}{
"ports": []interface{}{
map[string]interface{}{
"name": "port1",
"port": "12345",
},
},
},
}),
resid.NewResId(secret, "secret1"): rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "Secret",
"metadata": map[string]interface{}{
"name": "secret1",
},
}).SetBehavior(ifc.BehaviorCreate),
}
expected := resmap.ResMap{
resid.NewResId(cmap, "cm1"): rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "cm1",
},
}),
resid.NewResId(deploy, "deploy1"): rf.FromMap(
map[string]interface{}{
"group": "apps",
"apiVersion": "v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "deploy1",
},
"spec": map[string]interface{}{
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"old-label": "old-value",
},
},
"spec": map[string]interface{}{
"containers": []interface{}{
map[string]interface{}{
"name": "nginx",
"image": "nginx:1.7.9",
},
},
},
},
},
}),
resid.NewResId(service, "svc1"): rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "Service",
"metadata": map[string]interface{}{
"name": "svc1",
},
"spec": map[string]interface{}{
"ports": []interface{}{
map[string]interface{}{
"name": "port1",
"port": "12345",
},
},
},
}),
resid.NewResId(secret, "secret1"): rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "Secret",
"metadata": map[string]interface{}{
"name": "secret1-7kc45hd5f7",
},
}).SetBehavior(ifc.BehaviorCreate),
}
tran := NewNameHashTransformer()
tran.Transform(objs)
if !reflect.DeepEqual(objs, expected) {
err := expected.ErrorIfNotEqual(objs)
t.Fatalf("actual doesn't match expected: %v", err)
}
}
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"patch.go",
"patchconflictdetector.go",
],
importmap = "k8s.io/kubernetes/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch",
importpath = "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch",
visibility = ["//visibility:public"],
deps = [
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/mergepatch:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/scheme:go_default_library",
"//vendor/github.com/evanphx/json-patch:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/gvk:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/resmap:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/resource:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/transformers:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = ["patch_test.go"],
embed = [":go_default_library"],
deps = [
"//staging/src/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/gvk:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/resid:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/resmap:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/resource:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package patch
import (
"encoding/json"
"fmt"
"github.com/evanphx/json-patch"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/strategicpatch"
"k8s.io/client-go/kubernetes/scheme"
"sigs.k8s.io/kustomize/pkg/gvk"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/pkg/transformers"
)
// patchTransformer applies patches.
type patchTransformer struct {
patches []*resource.Resource
rf *resource.Factory
}
var _ transformers.Transformer = &patchTransformer{}
// NewPatchTransformer constructs a patchTransformer.
func NewPatchTransformer(
slice []*resource.Resource, rf *resource.Factory) (transformers.Transformer, error) {
if len(slice) == 0 {
return transformers.NewNoOpTransformer(), nil
}
return &patchTransformer{patches: slice, rf: rf}, nil
}
// Transform apply the patches on top of the base resources.
func (pt *patchTransformer) Transform(baseResourceMap resmap.ResMap) error {
// Merge and then index the patches by Id.
patches, err := pt.mergePatches()
if err != nil {
return err
}
// Strategic merge the resources exist in both base and patches.
for _, patch := range patches {
// Merge patches with base resource.
id := patch.Id()
matchedIds := baseResourceMap.FindByGVKN(id)
if len(matchedIds) == 0 {
return fmt.Errorf("failed to find an object with %#v to apply the patch", id.Gvk())
}
if len(matchedIds) > 1 {
return fmt.Errorf("found multiple objects %#v targeted by patch %#v (ambiguous)", matchedIds, id)
}
id = matchedIds[0]
base := baseResourceMap[id]
merged := map[string]interface{}{}
versionedObj, err := scheme.Scheme.New(toSchemaGvk(id.Gvk()))
baseName := base.GetName()
switch {
case runtime.IsNotRegisteredError(err):
// Use JSON merge patch to handle types w/o schema
baseBytes, err := json.Marshal(base.Map())
if err != nil {
return err
}
patchBytes, err := json.Marshal(patch.Map())
if err != nil {
return err
}
mergedBytes, err := jsonpatch.MergePatch(baseBytes, patchBytes)
if err != nil {
return err
}
err = json.Unmarshal(mergedBytes, &merged)
if err != nil {
return err
}
case err != nil:
return err
default:
// Use Strategic-Merge-Patch to handle types w/ schema
// TODO: Change this to use the new Merge package.
// Store the name of the base object, because this name may have been munged.
// Apply this name to the patched object.
lookupPatchMeta, err := strategicpatch.NewPatchMetaFromStruct(versionedObj)
if err != nil {
return err
}
merged, err = strategicpatch.StrategicMergeMapPatchUsingLookupPatchMeta(
base.Map(),
patch.Map(),
lookupPatchMeta)
if err != nil {
return err
}
}
base.SetName(baseName)
baseResourceMap[id].SetMap(merged)
}
return nil
}
// mergePatches merge and index patches by Id.
// It errors out if there is conflict between patches.
func (pt *patchTransformer) mergePatches() (resmap.ResMap, error) {
rc := resmap.ResMap{}
for ix, patch := range pt.patches {
id := patch.Id()
existing, found := rc[id]
if !found {
rc[id] = patch
continue
}
versionedObj, err := scheme.Scheme.New(toSchemaGvk(id.Gvk()))
if err != nil && !runtime.IsNotRegisteredError(err) {
return nil, err
}
var cd conflictDetector
if err != nil {
cd = newJMPConflictDetector(pt.rf)
} else {
cd, err = newSMPConflictDetector(versionedObj, pt.rf)
if err != nil {
return nil, err
}
}
conflict, err := cd.hasConflict(existing, patch)
if err != nil {
return nil, err
}
if conflict {
conflictingPatch, err := cd.findConflict(ix, pt.patches)
if err != nil {
return nil, err
}
return nil, fmt.Errorf(
"conflict between %#v and %#v",
conflictingPatch.Map(), patch.Map())
}
merged, err := cd.mergePatches(existing, patch)
if err != nil {
return nil, err
}
rc[id] = merged
}
return rc, nil
}
// toSchemaGvk converts to a schema.GroupVersionKind.
func toSchemaGvk(x gvk.Gvk) schema.GroupVersionKind {
return schema.GroupVersionKind{
Group: x.Group,
Version: x.Version,
Kind: x.Kind,
}
}
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package patch
import (
"encoding/json"
"github.com/evanphx/json-patch"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/mergepatch"
"k8s.io/apimachinery/pkg/util/strategicpatch"
"sigs.k8s.io/kustomize/pkg/resource"
)
type conflictDetector interface {
hasConflict(patch1, patch2 *resource.Resource) (bool, error)
findConflict(conflictingPatchIdx int, patches []*resource.Resource) (*resource.Resource, error)
mergePatches(patch1, patch2 *resource.Resource) (*resource.Resource, error)
}
type jsonMergePatch struct {
rf *resource.Factory
}
var _ conflictDetector = &jsonMergePatch{}
func newJMPConflictDetector(rf *resource.Factory) conflictDetector {
return &jsonMergePatch{rf: rf}
}
func (jmp *jsonMergePatch) hasConflict(
patch1, patch2 *resource.Resource) (bool, error) {
return mergepatch.HasConflicts(patch1.Map(), patch2.Map())
}
func (jmp *jsonMergePatch) findConflict(
conflictingPatchIdx int, patches []*resource.Resource) (*resource.Resource, error) {
for i, patch := range patches {
if i == conflictingPatchIdx {
continue
}
if !patches[conflictingPatchIdx].Id().GvknEquals(patch.Id()) {
continue
}
conflict, err := mergepatch.HasConflicts(
patch.Map(),
patches[conflictingPatchIdx].Map())
if err != nil {
return nil, err
}
if conflict {
return patch, nil
}
}
return nil, nil
}
func (jmp *jsonMergePatch) mergePatches(
patch1, patch2 *resource.Resource) (*resource.Resource, error) {
baseBytes, err := json.Marshal(patch1.Map())
if err != nil {
return nil, err
}
patchBytes, err := json.Marshal(patch2.Map())
if err != nil {
return nil, err
}
mergedBytes, err := jsonpatch.MergeMergePatches(baseBytes, patchBytes)
if err != nil {
return nil, err
}
mergedMap := make(map[string]interface{})
err = json.Unmarshal(mergedBytes, &mergedMap)
return jmp.rf.FromMap(mergedMap), err
}
type strategicMergePatch struct {
lookupPatchMeta strategicpatch.LookupPatchMeta
rf *resource.Factory
}
var _ conflictDetector = &strategicMergePatch{}
func newSMPConflictDetector(
versionedObj runtime.Object,
rf *resource.Factory) (conflictDetector, error) {
lookupPatchMeta, err := strategicpatch.NewPatchMetaFromStruct(versionedObj)
return &strategicMergePatch{lookupPatchMeta: lookupPatchMeta, rf: rf}, err
}
func (smp *strategicMergePatch) hasConflict(p1, p2 *resource.Resource) (bool, error) {
return strategicpatch.MergingMapsHaveConflicts(
p1.Map(), p2.Map(), smp.lookupPatchMeta)
}
func (smp *strategicMergePatch) findConflict(
conflictingPatchIdx int, patches []*resource.Resource) (*resource.Resource, error) {
for i, patch := range patches {
if i == conflictingPatchIdx {
continue
}
if !patches[conflictingPatchIdx].Id().GvknEquals(patch.Id()) {
continue
}
conflict, err := strategicpatch.MergingMapsHaveConflicts(
patch.Map(),
patches[conflictingPatchIdx].Map(),
smp.lookupPatchMeta)
if err != nil {
return nil, err
}
if conflict {
return patch, nil
}
}
return nil, nil
}
func (smp *strategicMergePatch) mergePatches(patch1, patch2 *resource.Resource) (*resource.Resource, error) {
mergeJSONMap, err := strategicpatch.MergeStrategicMergeMapPatchUsingLookupPatchMeta(
smp.lookupPatchMeta, patch1.Map(), patch2.Map())
return smp.rf.FromMap(mergeJSONMap), err
}
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["validators.go"],
importmap = "k8s.io/kubernetes/vendor/k8s.io/cli-runtime/pkg/kustomize/k8sdeps/validator",
importpath = "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/validator",
visibility = ["//visibility:public"],
deps = [
"//staging/src/k8s.io/apimachinery/pkg/api/validation:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/validation:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package validator provides functions to validate labels, annotations, namespace using apimachinery
package validator
import (
"errors"
apivalidation "k8s.io/apimachinery/pkg/api/validation"
v1validation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
"k8s.io/apimachinery/pkg/util/validation"
"k8s.io/apimachinery/pkg/util/validation/field"
)
// KustValidator validates Labels and annotations by apimachinery
type KustValidator struct{}
// NewKustValidator returns a KustValidator object
func NewKustValidator() *KustValidator {
return &KustValidator{}
}
// MakeAnnotationValidator returns a MapValidatorFunc using apimachinery.
func (v *KustValidator) MakeAnnotationValidator() func(map[string]string) error {
return func(x map[string]string) error {
errs := apivalidation.ValidateAnnotations(x, field.NewPath("field"))
if len(errs) > 0 {
return errors.New(errs.ToAggregate().Error())
}
return nil
}
}
// MakeLabelValidator returns a MapValidatorFunc using apimachinery.
func (v *KustValidator) MakeLabelValidator() func(map[string]string) error {
return func(x map[string]string) error {
errs := v1validation.ValidateLabels(x, field.NewPath("field"))
if len(errs) > 0 {
return errors.New(errs.ToAggregate().Error())
}
return nil
}
}
// ValidateNamespace validates a string is a valid namespace using apimachinery.
func (v *KustValidator) ValidateNamespace(s string) []string {
return validation.IsDNS1123Label(s)
}
...@@ -7,50 +7,10 @@ ...@@ -7,50 +7,10 @@
], ],
"Deps": [ "Deps": [
{ {
"ImportPath": "github.com/PuerkitoBio/purell",
"Rev": "8a290539e2e8629dbc4e6bad948158f790ec31f4"
},
{
"ImportPath": "github.com/PuerkitoBio/urlesc",
"Rev": "5bd2802263f21d8788851d5305584c82a5c75d7e"
},
{
"ImportPath": "github.com/davecgh/go-spew/spew",
"Rev": "782f4967f2dc4564575ca782fe2d04090b5faca8"
},
{
"ImportPath": "github.com/emicklei/go-restful",
"Rev": "ff4f55a206334ef123e4f79bbf348980da81ca46"
},
{
"ImportPath": "github.com/emicklei/go-restful/log",
"Rev": "ff4f55a206334ef123e4f79bbf348980da81ca46"
},
{
"ImportPath": "github.com/evanphx/json-patch", "ImportPath": "github.com/evanphx/json-patch",
"Rev": "36442dbdb585210f8d5a1b45e67aa323c197d5c4" "Rev": "36442dbdb585210f8d5a1b45e67aa323c197d5c4"
}, },
{ {
"ImportPath": "github.com/ghodss/yaml",
"Rev": "c7ce16629ff4cd059ed96ed06419dd3856fd3577"
},
{
"ImportPath": "github.com/go-openapi/jsonpointer",
"Rev": "ef5f0afec364d3b9396b7b77b43dbe26bf1f8004"
},
{
"ImportPath": "github.com/go-openapi/jsonreference",
"Rev": "8483a886a90412cd6858df4ea3483dce9c8e35a3"
},
{
"ImportPath": "github.com/go-openapi/spec",
"Rev": "5bae59e25b21498baea7f9d46e9c147ec106a42e"
},
{
"ImportPath": "github.com/go-openapi/swag",
"Rev": "5899d5c5e619fda5fa86e14795a835f473ca284c"
},
{
"ImportPath": "github.com/gogo/protobuf/proto", "ImportPath": "github.com/gogo/protobuf/proto",
"Rev": "342cbe0a04158f6dcb03ca0079991a51a4248c02" "Rev": "342cbe0a04158f6dcb03ca0079991a51a4248c02"
}, },
...@@ -119,18 +79,6 @@ ...@@ -119,18 +79,6 @@
"Rev": "ab8a2e0c74be9d3be70b3184d9acc634935ded82" "Rev": "ab8a2e0c74be9d3be70b3184d9acc634935ded82"
}, },
{ {
"ImportPath": "github.com/mailru/easyjson/buffer",
"Rev": "2f5df55504ebc322e4d52d34df6a1f5b503bf26d"
},
{
"ImportPath": "github.com/mailru/easyjson/jlexer",
"Rev": "2f5df55504ebc322e4d52d34df6a1f5b503bf26d"
},
{
"ImportPath": "github.com/mailru/easyjson/jwriter",
"Rev": "2f5df55504ebc322e4d52d34df6a1f5b503bf26d"
},
{
"ImportPath": "github.com/modern-go/concurrent", "ImportPath": "github.com/modern-go/concurrent",
"Rev": "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" "Rev": "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94"
}, },
...@@ -143,10 +91,6 @@ ...@@ -143,10 +91,6 @@
"Rev": "5f041e8faa004a95c88a202771f4cc3e991971e6" "Rev": "5f041e8faa004a95c88a202771f4cc3e991971e6"
}, },
{ {
"ImportPath": "github.com/pkg/errors",
"Rev": "645ef00459ed84a119197bfb8d8205042c6df63d"
},
{
"ImportPath": "github.com/spf13/cobra", "ImportPath": "github.com/spf13/cobra",
"Rev": "c439c4fa093711d42e1b01acb1235b52004753c1" "Rev": "c439c4fa093711d42e1b01acb1235b52004753c1"
}, },
...@@ -195,10 +139,6 @@ ...@@ -195,10 +139,6 @@
"Rev": "95c6576299259db960f6c5b9b69ea52422860fce" "Rev": "95c6576299259db960f6c5b9b69ea52422860fce"
}, },
{ {
"ImportPath": "golang.org/x/text/cases",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/encoding", "ImportPath": "golang.org/x/text/encoding",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
...@@ -215,22 +155,10 @@ ...@@ -215,22 +155,10 @@
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/internal",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/internal/tag",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/internal/utf8internal", "ImportPath": "golang.org/x/text/internal/utf8internal",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/language",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/runes", "ImportPath": "golang.org/x/text/runes",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
...@@ -239,10 +167,6 @@ ...@@ -239,10 +167,6 @@
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/precis",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/transform", "ImportPath": "golang.org/x/text/transform",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
...@@ -255,10 +179,6 @@ ...@@ -255,10 +179,6 @@
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
}, },
{ {
"ImportPath": "golang.org/x/text/width",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/time/rate", "ImportPath": "golang.org/x/time/rate",
"Rev": "f51c12702a4d776e4c1fa9b0fabab841babae631" "Rev": "f51c12702a4d776e4c1fa9b0fabab841babae631"
}, },
...@@ -403,10 +323,6 @@ ...@@ -403,10 +323,6 @@
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/api/equality",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/errors", "ImportPath": "k8s.io/apimachinery/pkg/api/errors",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
...@@ -419,10 +335,6 @@ ...@@ -419,10 +335,6 @@
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/api/validation",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1", "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
...@@ -435,10 +347,6 @@ ...@@ -435,10 +347,6 @@
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/validation",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1beta1", "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1beta1",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
...@@ -519,10 +427,6 @@ ...@@ -519,10 +427,6 @@
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/mergepatch",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/naming", "ImportPath": "k8s.io/apimachinery/pkg/util/naming",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
...@@ -539,10 +443,6 @@ ...@@ -539,10 +443,6 @@
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/pkg/util/strategicpatch",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/validation", "ImportPath": "k8s.io/apimachinery/pkg/util/validation",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
...@@ -563,10 +463,6 @@ ...@@ -563,10 +463,6 @@
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
{ {
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/json",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect", "ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
...@@ -583,34 +479,6 @@ ...@@ -583,34 +479,6 @@
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
{ {
"ImportPath": "k8s.io/cli-runtime/pkg/kustomize/k8sdeps",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/configmapandsecret",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kunstruct",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/cli-runtime/pkg/kustomize/k8sdeps/validator",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/client-go/discovery", "ImportPath": "k8s.io/client-go/discovery",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
...@@ -711,94 +579,6 @@ ...@@ -711,94 +579,6 @@
"Rev": "8139d8cb77af419532b33dfa7dd09fbc5f1d344f" "Rev": "8139d8cb77af419532b33dfa7dd09fbc5f1d344f"
}, },
{ {
"ImportPath": "k8s.io/kube-openapi/pkg/common",
"Rev": "c59034cc13d587f5ef4e85ca0ade0c1866ae8e1d"
},
{
"ImportPath": "k8s.io/kube-openapi/pkg/util/proto",
"Rev": "c59034cc13d587f5ef4e85ca0ade0c1866ae8e1d"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/commands/build",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/constants",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/expansion",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/factory",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/fs",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/gvk",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/ifc",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/ifc/transformer",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/internal/error",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/loader",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/patch",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/patch/transformer",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/resid",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/resmap",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/resource",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/target",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/transformers",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/transformers/config",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/kustomize/pkg/types",
"Rev": "ef51cceff55b17542fc91d6c4e30ea0bbb9641f7"
},
{
"ImportPath": "sigs.k8s.io/yaml", "ImportPath": "sigs.k8s.io/yaml",
"Rev": "fd68e9863619f6ec2fdd8625fe1f02e7c877e480" "Rev": "fd68e9863619f6ec2fdd8625fe1f02e7c877e480"
} }
......
...@@ -472,22 +472,6 @@ filegroup( ...@@ -472,22 +472,6 @@ filegroup(
"//vendor/k8s.io/utils/clock:all-srcs", "//vendor/k8s.io/utils/clock:all-srcs",
"//vendor/k8s.io/utils/exec:all-srcs", "//vendor/k8s.io/utils/exec:all-srcs",
"//vendor/k8s.io/utils/pointer:all-srcs", "//vendor/k8s.io/utils/pointer:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/commands/build:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/constants:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/expansion:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/factory:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/fs:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/gvk:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/ifc:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/internal/error:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/loader:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/patch:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/resid:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/resmap:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/resource:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/target:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/transformers:all-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/types:all-srcs",
"//vendor/sigs.k8s.io/yaml:all-srcs", "//vendor/sigs.k8s.io/yaml:all-srcs",
"//vendor/vbom.ml/util/sortorder:all-srcs", "//vendor/vbom.ml/util/sortorder:all-srcs",
], ],
......
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["build.go"],
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/commands/build",
importpath = "sigs.k8s.io/kustomize/pkg/commands/build",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/github.com/spf13/cobra:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/constants:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/fs:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/ifc/transformer:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/loader:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/resmap:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/target:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package build
import (
"io"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/ifc/transformer"
"sigs.k8s.io/kustomize/pkg/loader"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/target"
)
type buildOptions struct {
kustomizationPath string
outputPath string
}
var examples = `
Use the file somedir/kustomization.yaml to generate a set of api resources:
build somedir
Use a url pointing to a remote directory/kustomization.yaml to generate a set of api resources:
build url
The url should follow hashicorp/go-getter URL format described in
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.
func NewCmdBuild(
out io.Writer, fs fs.FileSystem,
rf *resmap.Factory,
ptf transformer.Factory) *cobra.Command {
var o buildOptions
cmd := &cobra.Command{
Use: "build [path]",
Short: "Print current configuration per contents of " + constants.KustomizationFileName,
Example: examples,
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
err := o.Validate(args)
if err != nil {
return err
}
return o.RunBuild(out, fs, rf, ptf)
},
}
cmd.Flags().StringVarP(
&o.outputPath,
"output", "o", "",
"If specified, write the build output to this path.")
return cmd
}
// Validate validates build command.
func (o *buildOptions) Validate(args []string) error {
if len(args) > 1 {
return errors.New("specify one path to " + constants.KustomizationFileName)
}
if len(args) == 0 {
o.kustomizationPath = "./"
} else {
o.kustomizationPath = args[0]
}
return nil
}
// RunBuild runs build command.
func (o *buildOptions) RunBuild(
out io.Writer, fSys fs.FileSystem,
rf *resmap.Factory, ptf transformer.Factory) error {
ldr, err := loader.NewLoader(o.kustomizationPath, fSys)
if err != nil {
return err
}
defer ldr.Cleanup()
kt, err := target.NewKustTarget(ldr, fSys, rf, ptf)
if err != nil {
return err
}
allResources, err := kt.MakeCustomizedResMap()
if err != nil {
return err
}
// Output the objects.
res, err := allResources.EncodeAsYaml()
if err != nil {
return err
}
if o.outputPath != "" {
return fSys.WriteFile(o.outputPath, res)
}
_, err = out.Write(res)
return err
}
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["constants.go"],
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/constants",
importpath = "sigs.k8s.io/kustomize/pkg/constants",
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package constants holds global constants for the kustomize tool.
package constants
// KustomizationFileSuffix is expected suffix for KustomizationFileName.
const KustomizationFileSuffix = ".yaml"
// SecondaryKustomizationFileSuffix is the second expected suffix when KustomizationFileSuffix is not found
const SecondaryKustomizationFileSuffix = ".yml"
// KustomizationFileName is the Well-Known File Name for a kustomize configuration file.
const KustomizationFileName = "kustomization" + KustomizationFileSuffix
// SecondaryKustomizationFileName is the secondary File Name for a kustomize configuration file when
// KustomizationFileName is not found
const SecondaryKustomizationFileName = "kustomization" + SecondaryKustomizationFileSuffix
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["expand.go"],
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/expansion",
importpath = "sigs.k8s.io/kustomize/pkg/expansion",
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package expansion provides functions find and replace $(FOO) style variables in strings.
package expansion
import (
"bytes"
)
const (
operator = '$'
referenceOpener = '('
referenceCloser = ')'
)
// syntaxWrap returns the input string wrapped by the expansion syntax.
func syntaxWrap(input string) string {
return string(operator) + string(referenceOpener) + input + string(referenceCloser)
}
// MappingFuncFor returns a mapping function for use with Expand that
// implements the expansion semantics defined in the expansion spec; it
// returns the input string wrapped in the expansion syntax if no mapping
// for the input is found.
func MappingFuncFor(context ...map[string]string) func(string) string {
return func(input string) string {
for _, vars := range context {
val, ok := vars[input]
if ok {
return val
}
}
return syntaxWrap(input)
}
}
// Expand replaces variable references in the input string according to
// the expansion spec using the given mapping function to resolve the
// values of variables.
func Expand(input string, mapping func(string) string) string {
var buf bytes.Buffer
checkpoint := 0
for cursor := 0; cursor < len(input); cursor++ {
if input[cursor] == operator && cursor+1 < len(input) {
// Copy the portion of the input string since the last
// checkpoint into the buffer
buf.WriteString(input[checkpoint:cursor])
// Attempt to read the variable name as defined by the
// syntax from the input string
read, isVar, advance := tryReadVariableName(input[cursor+1:])
if isVar {
// We were able to read a variable name correctly;
// apply the mapping to the variable name and copy the
// bytes into the buffer
buf.WriteString(mapping(read))
} else {
// Not a variable name; copy the read bytes into the buffer
buf.WriteString(read)
}
// Advance the cursor in the input string to account for
// bytes consumed to read the variable name expression
cursor += advance
// Advance the checkpoint in the input string
checkpoint = cursor + 1
}
}
// Return the buffer and any remaining unwritten bytes in the
// input string.
return buf.String() + input[checkpoint:]
}
// tryReadVariableName attempts to read a variable name from the input
// string and returns the content read from the input, whether that content
// represents a variable name to perform mapping on, and the number of bytes
// consumed in the input string.
//
// The input string is assumed not to contain the initial operator.
func tryReadVariableName(input string) (string, bool, int) {
switch input[0] {
case operator:
// Escaped operator; return it.
return input[0:1], false, 1
case referenceOpener:
// Scan to expression closer
for i := 1; i < len(input); i++ {
if input[i] == referenceCloser {
return input[1:i], true, i + 1
}
}
// Incomplete reference; return it.
return string(operator) + string(referenceOpener), false, 1
default:
// Not the beginning of an expression, ie, an operator
// that doesn't begin an expression. Return the operator
// and the first rune in the string.
return string(operator) + string(input[0]), false, 1
}
}
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["factory.go"],
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/factory",
importpath = "sigs.k8s.io/kustomize/pkg/factory",
visibility = ["//visibility:public"],
deps = [
"//vendor/sigs.k8s.io/kustomize/pkg/ifc:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/ifc/transformer:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/resmap:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/resource:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package factory provides factories for kustomize.
package factory
import (
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/ifc/transformer"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/resource"
)
// KustFactory provides different factories for kustomize
type KustFactory struct {
ResmapF *resmap.Factory
TransformerF transformer.Factory
ValidatorF ifc.Validator
UnstructF ifc.KunstructuredFactory
}
// NewKustFactory creats a KustFactory instance
func NewKustFactory(u ifc.KunstructuredFactory, v ifc.Validator, t transformer.Factory) *KustFactory {
return &KustFactory{
ResmapF: resmap.NewFactory(resource.NewFactory(u)),
TransformerF: t,
ValidatorF: v,
UnstructF: u,
}
}
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"fakefile.go",
"fakefileinfo.go",
"fakefs.go",
"fs.go",
"realfile.go",
"realfs.go",
],
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/fs",
importpath = "sigs.k8s.io/kustomize/pkg/fs",
visibility = ["//visibility:public"],
deps = ["//vendor/sigs.k8s.io/kustomize/pkg/constants:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fs
import (
"bytes"
"os"
)
var _ File = &FakeFile{}
// FakeFile implements File in-memory for tests.
type FakeFile struct {
name string
content []byte
dir bool
open bool
}
// makeDir makes a fake directory.
func makeDir(name string) *FakeFile {
return &FakeFile{name: name, dir: true}
}
// Close marks the fake file closed.
func (f *FakeFile) Close() error {
f.open = false
return nil
}
// Read never fails, and doesn't mutate p.
func (f *FakeFile) Read(p []byte) (n int, err error) {
return len(p), nil
}
// Write saves the contents of the argument to memory.
func (f *FakeFile) Write(p []byte) (n int, err error) {
f.content = p
return len(p), nil
}
// ContentMatches returns true if v matches fake file's content.
func (f *FakeFile) ContentMatches(v []byte) bool {
return bytes.Equal(v, f.content)
}
// GetContent the content of a fake file.
func (f *FakeFile) GetContent() []byte {
return f.content
}
// Stat returns nil.
func (f *FakeFile) Stat() (os.FileInfo, error) {
return nil, nil
}
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fs
import (
"os"
"time"
)
var _ os.FileInfo = &Fakefileinfo{}
// Fakefileinfo implements Fakefileinfo using a fake in-memory filesystem.
type Fakefileinfo struct {
*FakeFile
}
// Name returns the name of the file
func (fi *Fakefileinfo) Name() string { return fi.name }
// Size returns the size of the file
func (fi *Fakefileinfo) Size() int64 { return int64(len(fi.content)) }
// Mode returns the file mode
func (fi *Fakefileinfo) Mode() os.FileMode { return 0777 }
// ModTime returns the modification time
func (fi *Fakefileinfo) ModTime() time.Time { return time.Time{} }
// IsDir returns if it is a directory
func (fi *Fakefileinfo) IsDir() bool { return fi.dir }
// Sys should return underlying data source, but it now returns nil
func (fi *Fakefileinfo) Sys() interface{} { return nil }
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fs
import (
"fmt"
"path/filepath"
"sort"
"strings"
"sigs.k8s.io/kustomize/pkg/constants"
)
var _ FileSystem = &fakeFs{}
// fakeFs implements FileSystem using a fake in-memory filesystem.
type fakeFs struct {
m map[string]*FakeFile
}
// MakeFakeFS returns an instance of fakeFs with no files in it.
func MakeFakeFS() *fakeFs {
result := &fakeFs{m: map[string]*FakeFile{}}
result.Mkdir("/")
return result
}
// kustomizationContent is used in tests.
const kustomizationContent = `namePrefix: some-prefix
nameSuffix: some-suffix
# Labels to add to all objects and selectors.
# These labels would also be used to form the selector for apply --prune
# Named differently than “labels” to avoid confusion with metadata for this object
commonLabels:
app: helloworld
commonAnnotations:
note: This is an example annotation
resources: []
#- service.yaml
#- ../some-dir/
# There could also be configmaps in Base, which would make these overlays
configMapGenerator: []
# There could be secrets in Base, if just using a fork/rebase workflow
secretGenerator: []
`
// Create assures a fake file appears in the in-memory file system.
func (fs *fakeFs) Create(name string) (File, error) {
f := &FakeFile{}
f.open = true
fs.m[name] = f
return fs.m[name], nil
}
// Mkdir assures a fake directory appears in the in-memory file system.
func (fs *fakeFs) Mkdir(name string) error {
fs.m[name] = makeDir(name)
return nil
}
// MkdirAll delegates to Mkdir
func (fs *fakeFs) MkdirAll(name string) error {
return fs.Mkdir(name)
}
// RemoveAll presumably does rm -r on a path.
// There's no error.
func (fs *fakeFs) RemoveAll(name string) error {
var toRemove []string
for k := range fs.m {
if strings.HasPrefix(k, name) {
toRemove = append(toRemove, k)
}
}
for _, k := range toRemove {
delete(fs.m, k)
}
return nil
}
// Open returns a fake file in the open state.
func (fs *fakeFs) Open(name string) (File, error) {
if _, found := fs.m[name]; !found {
return nil, fmt.Errorf("file %q cannot be opened", name)
}
return fs.m[name], nil
}
// Exists returns true if file is known.
func (fs *fakeFs) Exists(name string) bool {
_, found := fs.m[name]
return found
}
// Glob returns the list of matching files
func (fs *fakeFs) Glob(pattern string) ([]string, error) {
var result []string
for p := range fs.m {
if fs.pathMatch(p, pattern) {
result = append(result, p)
}
}
sort.Strings(result)
return result, nil
}
// IsDir returns true if the file exists and is a directory.
func (fs *fakeFs) IsDir(name string) bool {
f, found := fs.m[name]
if found && f.dir {
return true
}
if !strings.HasSuffix(name, "/") {
name = name + "/"
}
for k := range fs.m {
if strings.HasPrefix(k, name) {
return true
}
}
return false
}
// ReadFile always returns an empty bytes and error depending on content of m.
func (fs *fakeFs) ReadFile(name string) ([]byte, error) {
if ff, found := fs.m[name]; found {
return ff.content, nil
}
return nil, fmt.Errorf("cannot read file %q", name)
}
func (fs *fakeFs) ReadTestKustomization() ([]byte, error) {
return fs.ReadFile(constants.KustomizationFileName)
}
// WriteFile always succeeds and does nothing.
func (fs *fakeFs) WriteFile(name string, c []byte) error {
ff := &FakeFile{}
ff.Write(c)
fs.m[name] = ff
return nil
}
// WriteTestKustomization writes a standard test file.
func (fs *fakeFs) WriteTestKustomization() {
fs.WriteTestKustomizationWith([]byte(kustomizationContent))
}
// WriteTestKustomizationWith writes a standard test file.
func (fs *fakeFs) WriteTestKustomizationWith(bytes []byte) {
fs.WriteFile(constants.KustomizationFileName, bytes)
}
func (fs *fakeFs) pathMatch(path, pattern string) bool {
match, _ := filepath.Match(pattern, path)
return match
}
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package fs provides a file system abstraction layer.
package fs
import (
"io"
"os"
)
// FileSystem groups basic os filesystem methods.
type FileSystem interface {
Create(name string) (File, error)
Mkdir(name string) error
MkdirAll(name string) error
RemoveAll(name string) error
Open(name string) (File, error)
IsDir(name string) bool
Exists(name string) bool
Glob(pattern string) ([]string, error)
ReadFile(name string) ([]byte, error)
WriteFile(name string, data []byte) error
}
// File groups the basic os.File methods.
type File interface {
io.ReadWriteCloser
Stat() (os.FileInfo, error)
}
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fs
import (
"os"
)
var _ File = &realFile{}
// realFile implements File using the local filesystem.
type realFile struct {
file *os.File
}
// Close closes a file.
func (f *realFile) Close() error { return f.file.Close() }
// Read reads a file's content.
func (f *realFile) Read(p []byte) (n int, err error) { return f.file.Read(p) }
// Write writes bytes to a file
func (f *realFile) Write(p []byte) (n int, err error) { return f.file.Write(p) }
// Stat returns an interface which has all the information regarding the file.
func (f *realFile) Stat() (os.FileInfo, error) { return f.file.Stat() }
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fs
import (
"io/ioutil"
"os"
"path/filepath"
)
var _ FileSystem = realFS{}
// realFS implements FileSystem using the local filesystem.
type realFS struct{}
// MakeRealFS makes an instance of realFS.
func MakeRealFS() FileSystem {
return realFS{}
}
// Create delegates to os.Create.
func (realFS) Create(name string) (File, error) { return os.Create(name) }
// Mkdir delegates to os.Mkdir.
func (realFS) Mkdir(name string) error {
return os.Mkdir(name, 0777|os.ModeDir)
}
// MkdirAll delegates to os.MkdirAll.
func (realFS) MkdirAll(name string) error {
return os.MkdirAll(name, 0777|os.ModeDir)
}
// RemoveAll delegates to os.RemoveAll.
func (realFS) RemoveAll(name string) error {
return os.RemoveAll(name)
}
// Open delegates to os.Open.
func (realFS) Open(name string) (File, error) { return os.Open(name) }
// Exists returns true if os.Stat succeeds.
func (realFS) Exists(name string) bool {
_, err := os.Stat(name)
return err == nil
}
// Glob returns the list of matching files
func (realFS) Glob(pattern string) ([]string, error) {
return filepath.Glob(pattern)
}
// IsDir delegates to os.Stat and FileInfo.IsDir
func (realFS) IsDir(name string) bool {
info, err := os.Stat(name)
if err != nil {
return false
}
return info.IsDir()
}
// ReadFile delegates to ioutil.ReadFile.
func (realFS) ReadFile(name string) ([]byte, error) { return ioutil.ReadFile(name) }
// WriteFile delegates to ioutil.WriteFile with read/write permissions.
func (realFS) WriteFile(name string, c []byte) error {
return ioutil.WriteFile(name, c, 0666)
}
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["gvk.go"],
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/gvk",
importpath = "sigs.k8s.io/kustomize/pkg/gvk",
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package gvk
import (
"strings"
)
// Gvk identifies a Kubernetes API type.
// https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md
type Gvk struct {
Group string `json:"group,omitempty" yaml:"group,omitempty"`
Version string `json:"version,omitempty" yaml:"version,omitempty"`
Kind string `json:"kind,omitempty" yaml:"kind,omitempty"`
}
// FromKind makes a Gvk with only the kind specified.
func FromKind(k string) Gvk {
return Gvk{
Kind: k,
}
}
const (
noGroup = "noGroup"
noVersion = "noVersion"
noKind = "noKind"
separator = "_"
)
// String returns a string representation of the GVK.
func (x Gvk) String() string {
g := x.Group
if g == "" {
g = noGroup
}
v := x.Version
if v == "" {
v = noVersion
}
k := x.Kind
if k == "" {
k = noKind
}
return strings.Join([]string{g, v, k}, separator)
}
// Equals returns true if the Gvk's have equal fields.
func (x Gvk) Equals(o Gvk) bool {
return x.Group == o.Group && x.Version == o.Version && x.Kind == o.Kind
}
// An attempt to order things to help k8s, e.g.
// a Service should come before things that refer to it.
// Namespace should be first.
// In some cases order just specified to provide determinism.
var order = []string{
"Namespace",
"StorageClass",
"CustomResourceDefinition",
"ServiceAccount",
"Role",
"ClusterRole",
"RoleBinding",
"ClusterRoleBinding",
"ConfigMap",
"Secret",
"Service",
"Deployment",
"StatefulSet",
"CronJob",
"PodDisruptionBudget",
}
var typeOrders = func() map[string]int {
m := map[string]int{}
for i, n := range order {
m[n] = i
}
return m
}()
// IsLessThan returns true if self is less than the argument.
func (x Gvk) IsLessThan(o Gvk) bool {
indexI, foundI := typeOrders[x.Kind]
indexJ, foundJ := typeOrders[o.Kind]
if foundI && foundJ {
if indexI != indexJ {
return indexI < indexJ
}
}
if foundI && !foundJ {
return true
}
if !foundI && foundJ {
return false
}
return x.String() < o.String()
}
// IsSelected returns true if `selector` selects `x`; otherwise, false.
// If `selector` and `x` are the same, return true.
// If `selector` is nil, it is considered as a wildcard and always return true.
// e.g. selector <Group: "", Version: "", Kind: "Deployment"> CAN select
// <Group: "extensions", Version: "v1beta1", Kind: "Deployment">.
// selector <Group: "apps", Version: "", Kind: "Deployment"> CANNOT select
// <Group: "extensions", Version: "v1beta1", Kind: "Deployment">.
func (x Gvk) IsSelected(selector *Gvk) bool {
if selector == nil {
return true
}
if len(selector.Group) > 0 {
if x.Group != selector.Group {
return false
}
}
if len(selector.Version) > 0 {
if x.Version != selector.Version {
return false
}
}
if len(selector.Kind) > 0 {
if x.Kind != selector.Kind {
return false
}
}
return true
}
var clusterLevelKinds = []string{
"ClusterRoleBinding",
"ClusterRole",
"CustomResourceDefinition",
"Namespace",
"PersistentVolume",
}
// IsClusterKind returns true if x is a cluster-level Gvk
func (x Gvk) IsClusterKind() bool {
for _, k := range clusterLevelKinds {
if k == x.Kind {
return true
}
}
return false
}
// ClusterLevelGvks returns a slice of cluster-level Gvks
func ClusterLevelGvks() []Gvk {
var result []Gvk
for _, k := range clusterLevelKinds {
result = append(result, Gvk{Kind: k})
}
return result
}
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"generationbehavior.go",
"ifc.go",
],
importmap = "k8s.io/kubernetes/vendor/sigs.k8s.io/kustomize/pkg/ifc",
importpath = "sigs.k8s.io/kustomize/pkg/ifc",
visibility = ["//visibility:public"],
deps = [
"//vendor/sigs.k8s.io/kustomize/pkg/fs:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/gvk:go_default_library",
"//vendor/sigs.k8s.io/kustomize/pkg/types:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//vendor/sigs.k8s.io/kustomize/pkg/ifc/transformer:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package ifc
// GenerationBehavior specifies generation behavior of configmaps, secrets and maybe other resources.
type GenerationBehavior int
const (
// BehaviorUnspecified is an Unspecified behavior; typically treated as a Create.
BehaviorUnspecified GenerationBehavior = iota
// BehaviorCreate makes a new resource.
BehaviorCreate
// BehaviorReplace replaces a resource.
BehaviorReplace
// BehaviorMerge attempts to merge a new resource with an existing resource.
BehaviorMerge
)
// String converts a GenerationBehavior to a string.
func (b GenerationBehavior) String() string {
switch b {
case BehaviorReplace:
return "replace"
case BehaviorMerge:
return "merge"
case BehaviorCreate:
return "create"
default:
return "unspecified"
}
}
// NewGenerationBehavior converts a string to a GenerationBehavior.
func NewGenerationBehavior(s string) GenerationBehavior {
switch s {
case "replace":
return BehaviorReplace
case "merge":
return BehaviorMerge
case "create":
return BehaviorCreate
default:
return BehaviorUnspecified
}
}
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package ifc holds miscellaneous interfaces used by kustomize.
package ifc
import (
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/gvk"
"sigs.k8s.io/kustomize/pkg/types"
)
// Validator provides functions to validate annotations and labels
type Validator interface {
MakeAnnotationValidator() func(map[string]string) error
MakeLabelValidator() func(map[string]string) error
ValidateNamespace(string) []string
}
// Loader interface exposes methods to read bytes.
type Loader interface {
// Root returns the root location for this Loader.
Root() string
// New returns Loader located at newRoot.
New(newRoot string) (Loader, error)
// Load returns the bytes read from the location or an error.
Load(location string) ([]byte, error)
// Cleanup cleans the loader
Cleanup() error
}
// Kunstructured allows manipulation of k8s objects
// that do not have Golang structs.
type Kunstructured interface {
Map() map[string]interface{}
SetMap(map[string]interface{})
Copy() Kunstructured
GetFieldValue(string) (string, error)
MarshalJSON() ([]byte, error)
UnmarshalJSON([]byte) error
GetGvk() gvk.Gvk
GetKind() string
GetName() string
SetName(string)
GetLabels() map[string]string
SetLabels(map[string]string)
GetAnnotations() map[string]string
SetAnnotations(map[string]string)
}
// KunstructuredFactory makes instances of Kunstructured.
type KunstructuredFactory interface {
SliceFromBytes([]byte) ([]Kunstructured, error)
FromMap(m map[string]interface{}) Kunstructured
MakeConfigMap(args *types.ConfigMapArgs, options *types.GeneratorOptions) (Kunstructured, error)
MakeSecret(args *types.SecretArgs, options *types.GeneratorOptions) (Kunstructured, error)
Set(fs fs.FileSystem, ldr Loader)
}
// See core.v1.SecretTypeOpaque
const SecretTypeOpaque = "Opaque"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment