mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-26 16:28:17 +00:00
Compare commits
70 Commits
kyaml/v0.9
...
api/v0.6.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b736b81167 | ||
|
|
0a04b1bb78 | ||
|
|
f7ebaae39e | ||
|
|
08099f0cea | ||
|
|
6fd04dd253 | ||
|
|
9ac97ef91f | ||
|
|
cfbf426174 | ||
|
|
9aafc61c5b | ||
|
|
cd2ebd3046 | ||
|
|
b20e5d7f84 | ||
|
|
13c9a2873e | ||
|
|
fc06283905 | ||
|
|
119d7cadf5 | ||
|
|
cdc6d1fc28 | ||
|
|
49dced2e01 | ||
|
|
76a8f034cb | ||
|
|
52060ac480 | ||
|
|
719532e4df | ||
|
|
70dcc79bf4 | ||
|
|
55b4448862 | ||
|
|
bcaac6f8c1 | ||
|
|
ba4b44db6b | ||
|
|
fd280d0c0b | ||
|
|
1dbf490146 | ||
|
|
62e4df72d3 | ||
|
|
bb77a7c86d | ||
|
|
41abeb85be | ||
|
|
3c86d37148 | ||
|
|
287b38cc87 | ||
|
|
d8d727b1ca | ||
|
|
a81a3d40ce | ||
|
|
52e682489c | ||
|
|
8714ca5a58 | ||
|
|
0490ca163f | ||
|
|
b4947fe8a0 | ||
|
|
9c7b4fddf9 | ||
|
|
5d5b1c2c38 | ||
|
|
cf1aafb121 | ||
|
|
2d4e406a86 | ||
|
|
2a8edd2859 | ||
|
|
a3bc13847c | ||
|
|
944b19ff7c | ||
|
|
f75274bae7 | ||
|
|
62a8a8c57d | ||
|
|
9514f9cd3a | ||
|
|
c1c2725360 | ||
|
|
e9ff26bb1b | ||
|
|
14dc3dfb81 | ||
|
|
44619d5ca2 | ||
|
|
a458ed84f9 | ||
|
|
108f44377d | ||
|
|
dc8439fbfa | ||
|
|
f5353fafa1 | ||
|
|
3d1376bbbc | ||
|
|
b1ea25e86a | ||
|
|
495f6df973 | ||
|
|
a4f1f0841e | ||
|
|
9d0fba81f0 | ||
|
|
92826c6a1e | ||
|
|
7e04be9ec6 | ||
|
|
d954c39ef7 | ||
|
|
176ac5b4fa | ||
|
|
dd696b5cb4 | ||
|
|
501404e403 | ||
|
|
232da9e12b | ||
|
|
8b9ce8eacb | ||
|
|
a6a061215f | ||
|
|
ccca424234 | ||
|
|
58092bf66d | ||
|
|
747323efce |
6
Makefile
6
Makefile
@@ -72,6 +72,11 @@ $(MYGOBIN)/pluginator:
|
||||
cd cmd/pluginator; \
|
||||
go install .
|
||||
|
||||
# Build from local source.
|
||||
$(MYGOBIN)/prchecker:
|
||||
cd cmd/prchecker; \
|
||||
go install .
|
||||
|
||||
# Build from local source.
|
||||
$(MYGOBIN)/kustomize:
|
||||
cd kustomize; \
|
||||
@@ -85,6 +90,7 @@ install-tools: \
|
||||
$(MYGOBIN)/gorepomod \
|
||||
$(MYGOBIN)/mdrip \
|
||||
$(MYGOBIN)/pluginator \
|
||||
$(MYGOBIN)/prchecker \
|
||||
$(MYGOBIN)/stringer
|
||||
|
||||
### Begin kustomize plugin rules.
|
||||
|
||||
@@ -7,9 +7,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"sigs.k8s.io/kustomize/api/filters/namespace"
|
||||
"sigs.k8s.io/kustomize/api/resid"
|
||||
"sigs.k8s.io/kustomize/api/resmap"
|
||||
"sigs.k8s.io/kustomize/api/resource"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
"sigs.k8s.io/kustomize/kyaml/filtersutil"
|
||||
"sigs.k8s.io/yaml"
|
||||
@@ -53,74 +51,6 @@ func (p *NamespaceTransformerPlugin) Transform(m resmap.ResMap) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Special casing metadata.namespace since
|
||||
// all objects have it, even "ClusterKind" objects
|
||||
// that don't exist in a namespace (the Namespace
|
||||
// object itself doesn't live in a namespace).
|
||||
func (p *NamespaceTransformerPlugin) applicableFieldSpecs(id resid.ResId) []types.FieldSpec {
|
||||
var res []types.FieldSpec
|
||||
for _, fs := range p.FieldSpecs {
|
||||
if id.IsSelected(&fs.Gvk) &&
|
||||
(fs.Path != types.MetadataNamespacePath ||
|
||||
(fs.Path == types.MetadataNamespacePath && id.IsNamespaceableKind())) {
|
||||
res = append(res, fs)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (p *NamespaceTransformerPlugin) changeNamespace(
|
||||
_ *resource.Resource) func(in interface{}) (interface{}, error) {
|
||||
return func(in interface{}) (interface{}, error) {
|
||||
switch in.(type) {
|
||||
case string:
|
||||
// will happen when the metadata/namespace
|
||||
// value is replaced
|
||||
return p.Namespace, nil
|
||||
case []interface{}:
|
||||
l, _ := in.([]interface{})
|
||||
for idx, item := range l {
|
||||
switch item.(type) {
|
||||
case map[string]interface{}:
|
||||
// Will happen when mutating the subjects
|
||||
// field of ClusterRoleBinding and RoleBinding
|
||||
inMap, _ := item.(map[string]interface{})
|
||||
if _, ok := inMap["name"]; !ok {
|
||||
continue
|
||||
}
|
||||
name, ok := inMap["name"].(string)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
// The only case we need to force the namespace
|
||||
// if for the "service account". "default" is
|
||||
// kind of hardcoded here for right now.
|
||||
if name != "default" {
|
||||
continue
|
||||
}
|
||||
inMap["namespace"] = p.Namespace
|
||||
l[idx] = inMap
|
||||
default:
|
||||
// nothing to do for right now
|
||||
}
|
||||
}
|
||||
return in, nil
|
||||
case map[string]interface{}:
|
||||
// Will happen if the createField=true
|
||||
// when the namespace is added to the
|
||||
// object
|
||||
inMap := in.(map[string]interface{})
|
||||
if len(inMap) == 0 {
|
||||
return p.Namespace, nil
|
||||
} else {
|
||||
return in, nil
|
||||
}
|
||||
default:
|
||||
return in, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func NewNamespaceTransformerPlugin() resmap.TransformerPlugin {
|
||||
return &NamespaceTransformerPlugin{}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package nameref
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"sigs.k8s.io/kustomize/api/filters/fieldspec"
|
||||
"sigs.k8s.io/kustomize/api/filters/filtersutil"
|
||||
@@ -9,6 +11,7 @@ import (
|
||||
"sigs.k8s.io/kustomize/api/resmap"
|
||||
"sigs.k8s.io/kustomize/api/resource"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
kyaml_filtersutil "sigs.k8s.io/kustomize/kyaml/filtersutil"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
@@ -19,6 +22,7 @@ type Filter struct {
|
||||
Referrer *resource.Resource
|
||||
Target resid.Gvk
|
||||
ReferralCandidates resmap.ResMap
|
||||
isRoleRef bool
|
||||
}
|
||||
|
||||
func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
|
||||
@@ -37,6 +41,9 @@ func (f Filter) set(node *yaml.RNode) error {
|
||||
if yaml.IsMissingOrNull(node) {
|
||||
return nil
|
||||
}
|
||||
if strings.HasSuffix(f.FieldSpec.Path, "roleRef/name") {
|
||||
f.isRoleRef = true
|
||||
}
|
||||
switch node.YNode().Kind {
|
||||
case yaml.ScalarNode:
|
||||
return f.setScalar(node)
|
||||
@@ -65,6 +72,7 @@ func (f Filter) setMapping(node *yaml.RNode) error {
|
||||
f.Referrer,
|
||||
f.Target,
|
||||
f.ReferralCandidates,
|
||||
f.isRoleRef,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -75,6 +83,7 @@ func (f Filter) setScalar(node *yaml.RNode) error {
|
||||
f.Target,
|
||||
f.ReferralCandidates,
|
||||
f.ReferralCandidates.Resources(),
|
||||
f.isRoleRef,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -86,6 +95,40 @@ func (f Filter) setScalar(node *yaml.RNode) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// getRoleRefGvk returns a Gvk in the roleRef field. Return error
|
||||
// if the roleRef, roleRef/apiGroup or roleRef/kind is missing.
|
||||
func getRoleRefGvk(res json.Marshaler) (*resid.Gvk, error) {
|
||||
n, err := kyaml_filtersutil.GetRNode(res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
roleRef, err := n.Pipe(yaml.Lookup("roleRef"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if roleRef.IsNil() {
|
||||
return nil, fmt.Errorf("roleRef cannot be found in %s", n.MustString())
|
||||
}
|
||||
apiGroup, err := roleRef.Pipe(yaml.Lookup("apiGroup"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if apiGroup.IsNil() {
|
||||
return nil, fmt.Errorf("apiGroup cannot be found in roleRef %s", roleRef.MustString())
|
||||
}
|
||||
kind, err := roleRef.Pipe(yaml.Lookup("kind"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if kind.IsNil() {
|
||||
return nil, fmt.Errorf("kind cannot be found in roleRef %s", roleRef.MustString())
|
||||
}
|
||||
return &resid.Gvk{
|
||||
Group: apiGroup.YNode().Value,
|
||||
Kind: kind.YNode().Value,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func filterReferralCandidates(
|
||||
referrer *resource.Resource,
|
||||
matches []*resource.Resource,
|
||||
@@ -117,11 +160,22 @@ func selectReferral(
|
||||
referrer *resource.Resource,
|
||||
target resid.Gvk,
|
||||
referralCandidates resmap.ResMap,
|
||||
referralCandidateSubset []*resource.Resource) (string, string, error) {
|
||||
|
||||
referralCandidateSubset []*resource.Resource,
|
||||
isRoleRef bool) (string, string, error) {
|
||||
var roleRefGvk *resid.Gvk
|
||||
if isRoleRef {
|
||||
var err error
|
||||
roleRefGvk, err = getRoleRefGvk(referrer)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
}
|
||||
for _, res := range referralCandidateSubset {
|
||||
id := res.OrgId()
|
||||
if id.IsSelected(&target) && res.GetOriginalName() == oldName {
|
||||
// If the we are processing a roleRef, the apiGroup and Kind in the
|
||||
// roleRef are needed to be considered.
|
||||
if (!isRoleRef || id.IsSelected(roleRefGvk)) &&
|
||||
id.IsSelected(&target) && res.GetOriginalName() == oldName {
|
||||
matches := referralCandidates.GetMatchingResourcesByOriginalId(id.Equals)
|
||||
// If there's more than one match,
|
||||
// filter the matches by prefix and suffix
|
||||
@@ -155,10 +209,11 @@ func getSimpleNameField(
|
||||
referrer *resource.Resource,
|
||||
target resid.Gvk,
|
||||
referralCandidates resmap.ResMap,
|
||||
referralCandidateSubset []*resource.Resource) (string, error) {
|
||||
referralCandidateSubset []*resource.Resource,
|
||||
isRoleRef bool) (string, error) {
|
||||
|
||||
newName, _, err := selectReferral(oldName, referrer, target,
|
||||
referralCandidates, referralCandidateSubset)
|
||||
referralCandidates, referralCandidateSubset, isRoleRef)
|
||||
|
||||
return newName, err
|
||||
}
|
||||
@@ -177,7 +232,8 @@ func setNameAndNs(
|
||||
in *yaml.RNode,
|
||||
referrer *resource.Resource,
|
||||
target resid.Gvk,
|
||||
referralCandidates resmap.ResMap) error {
|
||||
referralCandidates resmap.ResMap,
|
||||
isRoleRef bool) error {
|
||||
|
||||
if in.YNode().Kind != yaml.MappingNode {
|
||||
return fmt.Errorf("expect a mapping node")
|
||||
@@ -213,7 +269,7 @@ func setNameAndNs(
|
||||
|
||||
oldName := nameNode.YNode().Value
|
||||
newname, newnamespace, err := selectReferral(oldName, referrer, target,
|
||||
referralCandidates, subset)
|
||||
referralCandidates, subset, isRoleRef)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -194,47 +194,47 @@ metadata:
|
||||
{
|
||||
name: "update-clusterrolebinding",
|
||||
input: `
|
||||
apiVersion: example.com/v1
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
subjects:
|
||||
- name: default
|
||||
---
|
||||
apiVersion: example.com/v1
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
subjects:
|
||||
- name: default
|
||||
namespace: foo
|
||||
---
|
||||
apiVersion: example.com/v1
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
subjects:
|
||||
- name: something
|
||||
---
|
||||
apiVersion: example.com/v1
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
subjects:
|
||||
- name: something
|
||||
namespace: foo
|
||||
`,
|
||||
expected: `
|
||||
apiVersion: example.com/v1
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
subjects:
|
||||
- name: default
|
||||
namespace: bar
|
||||
---
|
||||
apiVersion: example.com/v1
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
subjects:
|
||||
- name: default
|
||||
namespace: bar
|
||||
---
|
||||
apiVersion: example.com/v1
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
subjects:
|
||||
- name: something
|
||||
---
|
||||
apiVersion: example.com/v1
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
subjects:
|
||||
- name: something
|
||||
|
||||
@@ -17,8 +17,6 @@ require (
|
||||
k8s.io/apimachinery v0.17.0
|
||||
k8s.io/client-go v0.17.0
|
||||
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a
|
||||
sigs.k8s.io/kustomize/kyaml v0.9.1
|
||||
sigs.k8s.io/kustomize/kyaml v0.9.3
|
||||
sigs.k8s.io/yaml v1.2.0
|
||||
)
|
||||
|
||||
replace sigs.k8s.io/kustomize/kyaml v0.9.1 => ../kyaml
|
||||
|
||||
@@ -588,6 +588,8 @@ mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphD
|
||||
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
|
||||
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f h1:Cq7MalBHYACRd6EesksG1Q8EoIAKOsiZviGKbOLIej4=
|
||||
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw=
|
||||
sigs.k8s.io/kustomize/kyaml v0.9.3 h1:kZ5HnNmmnbndSXFivrAVM6u3Ik1dwu4kbpaV8KNwy8I=
|
||||
sigs.k8s.io/kustomize/kyaml v0.9.3/go.mod h1:UTm64bSWVdBUA8EQoYCxVOaBQxUdIOr5LKWxA4GNbkw=
|
||||
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||
|
||||
@@ -789,9 +789,9 @@ func TestNameReferenceClusterWide(t *testing.T) {
|
||||
"name": modifiedname,
|
||||
},
|
||||
"roleRef": map[string]interface{}{
|
||||
"apiVersion": "rbac.authorization.k8s.io/v1",
|
||||
"kind": "ClusterRole",
|
||||
"name": orgname,
|
||||
"apiGroup": "rbac.authorization.k8s.io",
|
||||
"kind": "ClusterRole",
|
||||
"name": orgname,
|
||||
},
|
||||
"subjects": []interface{}{
|
||||
map[string]interface{}{
|
||||
@@ -845,9 +845,9 @@ func TestNameReferenceClusterWide(t *testing.T) {
|
||||
"name": modifiedname,
|
||||
},
|
||||
"roleRef": map[string]interface{}{
|
||||
"apiVersion": "rbac.authorization.k8s.io/v1",
|
||||
"kind": "ClusterRole",
|
||||
"name": modifiedname,
|
||||
"apiGroup": "rbac.authorization.k8s.io",
|
||||
"kind": "ClusterRole",
|
||||
"name": modifiedname,
|
||||
},
|
||||
// The following tests required a change in
|
||||
// getNameFunc implementation in order to leverage
|
||||
@@ -937,9 +937,9 @@ func TestNameReferenceNamespaceTransformation(t *testing.T) {
|
||||
"name": modifiedname,
|
||||
},
|
||||
"roleRef": map[string]interface{}{
|
||||
"apiVersion": "rbac.authorization.k8s.io/v1",
|
||||
"kind": "ClusterRole",
|
||||
"name": orgname,
|
||||
"apiGroup": "rbac.authorization.k8s.io",
|
||||
"kind": "ClusterRole",
|
||||
"name": orgname,
|
||||
},
|
||||
"subjects": []interface{}{
|
||||
map[string]interface{}{
|
||||
@@ -973,9 +973,9 @@ func TestNameReferenceNamespaceTransformation(t *testing.T) {
|
||||
"name": modifiedname,
|
||||
},
|
||||
"roleRef": map[string]interface{}{
|
||||
"apiVersion": "rbac.authorization.k8s.io/v1",
|
||||
"kind": "ClusterRole",
|
||||
"name": modifiedname,
|
||||
"apiGroup": "rbac.authorization.k8s.io",
|
||||
"kind": "ClusterRole",
|
||||
"name": modifiedname,
|
||||
},
|
||||
// The following tests required a change in
|
||||
// getNameFunc implementation in order to leverage
|
||||
|
||||
@@ -527,8 +527,8 @@ k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl
|
||||
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc=
|
||||
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
|
||||
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw=
|
||||
sigs.k8s.io/kustomize/kyaml v0.9.1 h1:T7aNUraSioQp0NHJZtYjIhL/q8mqRzCiHcAKdvo09go=
|
||||
sigs.k8s.io/kustomize/kyaml v0.9.1/go.mod h1:UTm64bSWVdBUA8EQoYCxVOaBQxUdIOr5LKWxA4GNbkw=
|
||||
sigs.k8s.io/kustomize/kyaml v0.9.3 h1:kZ5HnNmmnbndSXFivrAVM6u3Ik1dwu4kbpaV8KNwy8I=
|
||||
sigs.k8s.io/kustomize/kyaml v0.9.3/go.mod h1:UTm64bSWVdBUA8EQoYCxVOaBQxUdIOr5LKWxA4GNbkw=
|
||||
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
|
||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
|
||||
@@ -26,13 +26,15 @@ func newMultiTransformer(t []resmap.Transformer) resmap.Transformer {
|
||||
return r
|
||||
}
|
||||
|
||||
// Transform prepends the name prefix.
|
||||
// Transform applies the member transformers in order to the resources,
|
||||
// optionally detecting and erroring on commutation conflict.
|
||||
func (o *multiTransformer) Transform(m resmap.ResMap) error {
|
||||
if o.checkConflictEnabled {
|
||||
return o.transformWithCheckConflict(m)
|
||||
}
|
||||
return o.transform(m)
|
||||
}
|
||||
|
||||
func (o *multiTransformer) transform(m resmap.ResMap) error {
|
||||
for _, t := range o.transformers {
|
||||
err := t.Transform(m)
|
||||
|
||||
@@ -238,6 +238,8 @@ nameReference:
|
||||
kind: Ingress
|
||||
- path: metadata/annotations/nginx.ingress.kubernetes.io\/auth-tls-secret
|
||||
kind: Ingress
|
||||
- path: spec/tls/secretName
|
||||
kind: Ingress
|
||||
- path: imagePullSecrets/name
|
||||
kind: ServiceAccount
|
||||
- path: parameters/secretName
|
||||
@@ -267,6 +269,10 @@ nameReference:
|
||||
kind: Ingress
|
||||
- path: spec/backend/serviceName
|
||||
kind: Ingress
|
||||
- path: spec/rules/http/paths/backend/service/name
|
||||
kind: Ingress
|
||||
- path: spec/defaultBackend/service/name
|
||||
kind: Ingress
|
||||
- path: spec/service/name
|
||||
kind: APIService
|
||||
group: apiregistration.k8s.io
|
||||
@@ -373,5 +379,12 @@ nameReference:
|
||||
kind: Job
|
||||
- path: spec/template/spec/priorityClassName
|
||||
kind: DaemonSet
|
||||
|
||||
- kind: IngressClass
|
||||
version: v1
|
||||
group: networking.k8s.io/v1
|
||||
fieldSpecs:
|
||||
- path: spec/ingressClassName
|
||||
kind: Ingress
|
||||
`
|
||||
)
|
||||
|
||||
@@ -159,7 +159,7 @@ subjects:
|
||||
name: default
|
||||
namespace: irrelevant
|
||||
---
|
||||
apiVersion: admissionregistration.k8s.io/v1beta1
|
||||
apiVersion: admissionregistration.k8s.io/v1
|
||||
kind: ValidatingWebhookConfiguration
|
||||
metadata:
|
||||
name: example
|
||||
@@ -180,15 +180,17 @@ webhooks:
|
||||
name: svc3
|
||||
namespace: random
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1beta1
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: crds.my.org
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: cr1
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: crb1
|
||||
@@ -197,6 +199,7 @@ subjects:
|
||||
name: default
|
||||
namespace: irrelevant
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: pv1
|
||||
@@ -257,7 +260,7 @@ subjects:
|
||||
name: default
|
||||
namespace: newnamespace
|
||||
---
|
||||
apiVersion: admissionregistration.k8s.io/v1beta1
|
||||
apiVersion: admissionregistration.k8s.io/v1
|
||||
kind: ValidatingWebhookConfiguration
|
||||
metadata:
|
||||
name: p1-example-s1
|
||||
@@ -278,15 +281,17 @@ webhooks:
|
||||
namespace: random
|
||||
name: example3
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1beta1
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: crds.my.org
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: p1-cr1-s1
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: p1-crb1-s1
|
||||
@@ -295,6 +300,7 @@ subjects:
|
||||
name: default
|
||||
namespace: newnamespace
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: p1-pv1-s1
|
||||
|
||||
287
api/krusty/nameupdateinroleref_test.go
Normal file
287
api/krusty/nameupdateinroleref_test.go
Normal file
@@ -0,0 +1,287 @@
|
||||
package krusty_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
|
||||
)
|
||||
|
||||
// https://github.com/kubernetes-sigs/kustomize/issues/2640
|
||||
func TestNameUpdateInRoleRef(t *testing.T) {
|
||||
th := kusttest_test.MakeHarness(t)
|
||||
th.WriteF("/app/rbac.yaml", `
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: my-role
|
||||
rules:
|
||||
- apiGroups:
|
||||
- '*'
|
||||
resources:
|
||||
- '*'
|
||||
verbs:
|
||||
- get
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: my-role
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: my-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: default
|
||||
namespace: foo
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: my-role
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- secrets
|
||||
verbs:
|
||||
- get
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: my-role
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
version: v1
|
||||
kind: Role
|
||||
name: my-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: default
|
||||
`)
|
||||
|
||||
th.WriteK("/app", `
|
||||
namespace: foo
|
||||
resources:
|
||||
- rbac.yaml
|
||||
|
||||
patches:
|
||||
- patch: |-
|
||||
- op: add
|
||||
path: /metadata/name
|
||||
value: prefix_my-role
|
||||
target:
|
||||
group: rbac.authorization.k8s.io
|
||||
version: v1
|
||||
kind: ClusterRole
|
||||
name: my-role
|
||||
`)
|
||||
|
||||
m := th.Run("/app", th.MakeDefaultOptions())
|
||||
th.AssertActualEqualsExpected(m, `
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: prefix_my-role
|
||||
rules:
|
||||
- apiGroups:
|
||||
- '*'
|
||||
resources:
|
||||
- '*'
|
||||
verbs:
|
||||
- get
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: my-role
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: prefix_my-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: default
|
||||
namespace: foo
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: my-role
|
||||
namespace: foo
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- secrets
|
||||
verbs:
|
||||
- get
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: my-role
|
||||
namespace: foo
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: my-role
|
||||
version: v1
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: default
|
||||
namespace: foo
|
||||
`)
|
||||
}
|
||||
|
||||
// https://github.com/kubernetes-sigs/kustomize/issues/3073
|
||||
func TestNameUpdateInRoleRef2(t *testing.T) {
|
||||
th := kusttest_test.MakeHarness(t)
|
||||
th.WriteF("/app/workloads.yaml", `
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: myapp
|
||||
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: myapp
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- nodes/metrics
|
||||
verbs:
|
||||
- get
|
||||
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: myapp
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: myapp
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: myapp
|
||||
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: myapp
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- services
|
||||
verbs:
|
||||
- get
|
||||
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: myapp
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: myapp
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: myapp
|
||||
`)
|
||||
|
||||
th.WriteF("/app/suffixTransformer.yaml", `
|
||||
apiVersion: builtin
|
||||
kind: PrefixSuffixTransformer
|
||||
metadata:
|
||||
name: notImportantHere
|
||||
suffix: -suffix
|
||||
fieldSpecs:
|
||||
- path: metadata/name
|
||||
kind: ClusterRole
|
||||
name: myapp
|
||||
- path: metadata/name
|
||||
kind: ClusterRoleBinding
|
||||
name: myapp
|
||||
`)
|
||||
|
||||
th.WriteK("/app", `
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- workloads.yaml
|
||||
transformers:
|
||||
- suffixTransformer.yaml
|
||||
namespace: test
|
||||
|
||||
`)
|
||||
|
||||
m := th.Run("/app", th.MakeDefaultOptions())
|
||||
th.AssertActualEqualsExpected(m, `
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: myapp
|
||||
namespace: test
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: myapp-suffix
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- nodes/metrics
|
||||
verbs:
|
||||
- get
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: myapp-suffix
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: myapp-suffix
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: myapp
|
||||
namespace: test
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: myapp
|
||||
namespace: test
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- services
|
||||
verbs:
|
||||
- get
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: myapp
|
||||
namespace: test
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: myapp
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: myapp
|
||||
namespace: test
|
||||
`)
|
||||
}
|
||||
@@ -6,6 +6,7 @@ package resid
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"sigs.k8s.io/kustomize/kyaml/openapi"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
|
||||
@@ -207,5 +208,6 @@ func (x Gvk) toKyamlTypeMeta() yaml.TypeMeta {
|
||||
// IsNamespaceableKind returns true if x is a namespaceable Gvk
|
||||
// Implements https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/#not-all-objects-are-in-a-namespace
|
||||
func (x Gvk) IsNamespaceableKind() bool {
|
||||
return x.toKyamlTypeMeta().IsNamespaceable()
|
||||
isNamespaceScoped, found := openapi.IsNamespaceScoped(x.toKyamlTypeMeta())
|
||||
return !found || isNamespaceScoped
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ package resid
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var equalsTests = []struct {
|
||||
@@ -255,3 +257,40 @@ func TestSelectByGVK(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsNamespaceableKind(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
gvk Gvk
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
"namespaceable resource",
|
||||
Gvk{Group: "apps", Version: "v1", Kind: "Deployment"},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"clusterscoped resource",
|
||||
Gvk{Group: "", Version: "v1", Kind: "Namespace"},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"unknown resource (should default to namespaceable)",
|
||||
Gvk{Group: "example1.com", Version: "v1", Kind: "Bar"},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"unknown resource (should default to namespaceable)",
|
||||
Gvk{Group: "apps", Version: "v1", Kind: "ClusterRoleBinding"},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for i := range testCases {
|
||||
test := testCases[i]
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
isNamespaceable := test.gvk.IsNamespaceableKind()
|
||||
assert.Equal(t, test.expected, isNamespaceable)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,7 +265,7 @@ func TestResIdEquals(t *testing.T) {
|
||||
Name: "nm",
|
||||
},
|
||||
gVknResult: false,
|
||||
nsEquals: false,
|
||||
nsEquals: true,
|
||||
equals: false,
|
||||
},
|
||||
{
|
||||
@@ -376,7 +376,7 @@ func TestEffectiveNamespace(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
id: ResId{
|
||||
Gvk: Gvk{Group: "g", Version: "v", Kind: "Node"},
|
||||
Gvk: Gvk{Group: "", Version: "v1", Kind: "Node"},
|
||||
Name: "nm",
|
||||
},
|
||||
expected: TotallyNotANamespace,
|
||||
@@ -384,7 +384,7 @@ func TestEffectiveNamespace(t *testing.T) {
|
||||
{
|
||||
id: ResId{
|
||||
Namespace: "foo",
|
||||
Gvk: Gvk{Group: "g", Version: "v", Kind: "Node"},
|
||||
Gvk: Gvk{Group: "", Version: "v1", Kind: "Node"},
|
||||
Name: "nm",
|
||||
},
|
||||
expected: TotallyNotANamespace,
|
||||
|
||||
@@ -355,7 +355,7 @@ func TestSubsetThatCouldBeReferencedByResource(t *testing.T) {
|
||||
})
|
||||
r4 := rf.FromMap(
|
||||
map[string]interface{}{
|
||||
"apiVersion": "v1",
|
||||
"apiVersion": "apps/v1",
|
||||
"kind": "Deployment",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": "charlie",
|
||||
@@ -374,7 +374,7 @@ func TestSubsetThatCouldBeReferencedByResource(t *testing.T) {
|
||||
r5.AddNamePrefix("little-")
|
||||
r6 := rf.FromMap(
|
||||
map[string]interface{}{
|
||||
"apiVersion": "v1",
|
||||
"apiVersion": "apps/v1",
|
||||
"kind": "Deployment",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": "domino",
|
||||
@@ -384,7 +384,7 @@ func TestSubsetThatCouldBeReferencedByResource(t *testing.T) {
|
||||
r6.AddNamePrefix("little-")
|
||||
r7 := rf.FromMap(
|
||||
map[string]interface{}{
|
||||
"apiVersion": "v1",
|
||||
"apiVersion": "rbac.authorization.k8s.io/v1",
|
||||
"kind": "ClusterRoleBinding",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": "meh",
|
||||
|
||||
@@ -17,3 +17,12 @@ type Patch struct {
|
||||
// Target points to the resources that the patch is applied to
|
||||
Target *Selector `json:"target,omitempty" yaml:"target,omitempty"`
|
||||
}
|
||||
|
||||
// Equals return true if p equals o.
|
||||
func (p *Patch) Equals(o Patch) bool {
|
||||
targetEqual := (p.Target == o.Target) ||
|
||||
(p.Target != nil && o.Target != nil && *p.Target == *o.Target)
|
||||
return p.Path == o.Path &&
|
||||
p.Patch == o.Patch &&
|
||||
targetEqual
|
||||
}
|
||||
|
||||
125
api/types/patch_test.go
Normal file
125
api/types/patch_test.go
Normal file
@@ -0,0 +1,125 @@
|
||||
package types_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"sigs.k8s.io/kustomize/api/resid"
|
||||
. "sigs.k8s.io/kustomize/api/types"
|
||||
)
|
||||
|
||||
func TestPatchEquals(t *testing.T) {
|
||||
selector := Selector{
|
||||
Gvk: resid.Gvk{
|
||||
Group: "group",
|
||||
Version: "version",
|
||||
Kind: "kind",
|
||||
},
|
||||
Name: "name",
|
||||
Namespace: "namespace",
|
||||
LabelSelector: "selector",
|
||||
AnnotationSelector: "selector",
|
||||
}
|
||||
type testcase struct {
|
||||
patch1 Patch
|
||||
patch2 Patch
|
||||
expect bool
|
||||
name string
|
||||
}
|
||||
testcases := []testcase{
|
||||
{
|
||||
name: "empty patches",
|
||||
patch1: Patch{},
|
||||
patch2: Patch{},
|
||||
expect: true,
|
||||
},
|
||||
{
|
||||
name: "full patches",
|
||||
patch1: Patch{
|
||||
Path: "foo",
|
||||
Patch: "bar",
|
||||
Target: &Selector{
|
||||
Gvk: resid.Gvk{
|
||||
Group: "group",
|
||||
Version: "version",
|
||||
Kind: "kind",
|
||||
},
|
||||
Name: "name",
|
||||
Namespace: "namespace",
|
||||
LabelSelector: "selector",
|
||||
AnnotationSelector: "selector",
|
||||
},
|
||||
},
|
||||
patch2: Patch{
|
||||
Path: "foo",
|
||||
Patch: "bar",
|
||||
Target: &Selector{
|
||||
Gvk: resid.Gvk{
|
||||
Group: "group",
|
||||
Version: "version",
|
||||
Kind: "kind",
|
||||
},
|
||||
Name: "name",
|
||||
Namespace: "namespace",
|
||||
LabelSelector: "selector",
|
||||
AnnotationSelector: "selector",
|
||||
},
|
||||
},
|
||||
expect: true,
|
||||
},
|
||||
{
|
||||
name: "same target",
|
||||
patch1: Patch{
|
||||
Path: "foo",
|
||||
Patch: "bar",
|
||||
Target: &selector,
|
||||
},
|
||||
patch2: Patch{
|
||||
Path: "foo",
|
||||
Patch: "bar",
|
||||
Target: &selector,
|
||||
},
|
||||
expect: true,
|
||||
},
|
||||
{
|
||||
name: "omit target",
|
||||
patch1: Patch{
|
||||
Path: "foo",
|
||||
Patch: "bar",
|
||||
},
|
||||
patch2: Patch{
|
||||
Path: "foo",
|
||||
Patch: "bar",
|
||||
},
|
||||
expect: true,
|
||||
},
|
||||
{
|
||||
name: "one nil target",
|
||||
patch1: Patch{
|
||||
Path: "foo",
|
||||
Patch: "bar",
|
||||
Target: &selector,
|
||||
},
|
||||
patch2: Patch{
|
||||
Path: "foo",
|
||||
Patch: "bar",
|
||||
},
|
||||
expect: false,
|
||||
},
|
||||
{
|
||||
name: "different path",
|
||||
patch1: Patch{
|
||||
Path: "foo",
|
||||
},
|
||||
patch2: Patch{
|
||||
Path: "bar",
|
||||
},
|
||||
expect: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
if tc.expect != tc.patch1.Equals(tc.patch2) {
|
||||
t.Fatalf("%s: unexpected result %v", tc.name, !tc.expect)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package complete
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/posener/complete/v2"
|
||||
"github.com/posener/complete/v2/predict"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
|
||||
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||
)
|
||||
|
||||
// NewCommand returns a new install-completion command
|
||||
func NewCommand() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "install-completion",
|
||||
Short: commands.CompletionShort,
|
||||
Long: commands.CompletionLong,
|
||||
PreRunE: preRunE,
|
||||
Run: run,
|
||||
}
|
||||
}
|
||||
|
||||
func preRunE(cmd *cobra.Command, args []string) error {
|
||||
// install by default
|
||||
if os.Getenv("COMP_INSTALL") == "" {
|
||||
if err := errors.Wrap(os.Setenv("COMP_INSTALL", "1")); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func run(cmd *cobra.Command, args []string) {
|
||||
// find the root command
|
||||
for cmd.Parent() != nil {
|
||||
cmd = cmd.Parent()
|
||||
}
|
||||
|
||||
// do completion
|
||||
Complete(cmd).Complete("kustomize")
|
||||
}
|
||||
|
||||
// Complete returns a completion command for a cobra command
|
||||
func Complete(cmd *cobra.Command) *complete.Command {
|
||||
cc := &complete.Command{
|
||||
Flags: map[string]complete.Predictor{},
|
||||
Sub: map[string]*complete.Command{},
|
||||
}
|
||||
if strings.Contains(cmd.Use, "DIR") {
|
||||
// if usage contains directory, then use a file predictor
|
||||
cc.Args = predict.Dirs("*")
|
||||
}
|
||||
|
||||
// add completion for each subcommand
|
||||
for i := range cmd.Commands() {
|
||||
c := cmd.Commands()[i]
|
||||
name := strings.Split(c.Use, " ")[0]
|
||||
cc.Sub[name] = Complete(c)
|
||||
}
|
||||
|
||||
// add completion for each flag
|
||||
cmd.Flags().VisitAll(func(flag *pflag.Flag) {
|
||||
cc.Flags[flag.Name] = predict.Nothing
|
||||
})
|
||||
return cc
|
||||
}
|
||||
33
cmd/config/completion/completion.go
Normal file
33
cmd/config/completion/completion.go
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright 2020 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package completion
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func NewCommand() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "completion [bash|zsh|fish|powershell]",
|
||||
Short: "Generate shell completion script",
|
||||
Long: "Generate shell completion.",
|
||||
DisableFlagsInUseLine: true,
|
||||
ValidArgs: []string{"bash", "zsh", "fish", "powershell"},
|
||||
Args: cobra.ExactValidArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
switch args[0] {
|
||||
case "bash":
|
||||
cmd.Root().GenBashCompletion(os.Stdout)
|
||||
case "zsh":
|
||||
cmd.Root().GenZshCompletion(os.Stdout)
|
||||
case "fish":
|
||||
cmd.Root().GenFishCompletion(os.Stdout, true)
|
||||
case "powershell":
|
||||
cmd.Root().GenPowerShellCompletion(os.Stdout)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"sigs.k8s.io/kustomize/cmd/config/internal/commands"
|
||||
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/api"
|
||||
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/tutorials"
|
||||
"sigs.k8s.io/kustomize/cmd/config/runner"
|
||||
)
|
||||
|
||||
// Export commands publicly for composition
|
||||
@@ -35,13 +36,13 @@ var (
|
||||
Wrap = commands.WrapCommand
|
||||
XArgs = commands.XArgsCommand
|
||||
|
||||
StackOnError = &commands.StackOnError
|
||||
ExitOnError = &commands.ExitOnError
|
||||
StackOnError = &runner.StackOnError
|
||||
ExitOnError = &runner.ExitOnError
|
||||
)
|
||||
|
||||
// AddCommands adds the cfg and fn commands to kustomize.
|
||||
func AddCommands(root *cobra.Command, name string) *cobra.Command {
|
||||
commands.ExitOnError = true
|
||||
runner.ExitOnError = true
|
||||
|
||||
root.PersistentFlags().BoolVar(StackOnError, "stack-trace", false,
|
||||
"print a stack-trace on error")
|
||||
|
||||
@@ -1,20 +1,25 @@
|
||||
## install-completion
|
||||
## completion
|
||||
|
||||
Install shell completion.
|
||||
Generate shell completion.
|
||||
|
||||
### Synopsis
|
||||
|
||||
Install shell completion for kustomize commands and flags -- supports bash, fish and zsh.
|
||||
Generate shell completion for `kustomize` -- supports bash, zsh, fish and powershell.
|
||||
|
||||
kustomize install-completion
|
||||
### Examples
|
||||
|
||||
Registers the completion command with known shells (e.g. .bashrc, .bash_profile, etc):
|
||||
# load completion for Bash
|
||||
source <(kustomize completion bash)
|
||||
|
||||
complete -C /Users/USER/go/bin/kustomize kustomize
|
||||
# install for Bash in Linux
|
||||
kustomize completion bash > /etc/bash_completion.d/kustomize
|
||||
|
||||
Because the completion command is embedded in kustomize directly, there is no need to update
|
||||
it separately from the kustomize binary.
|
||||
# install for Bash in MacOS
|
||||
kustomize completion bash > /usr/local/etc/bash_completion.d/kustomize
|
||||
|
||||
To uninstall shell completion run:
|
||||
# package for Bash
|
||||
kustomize completion bash > /usr/share/bash-completion/completions/kustomize
|
||||
|
||||
# package for zsh
|
||||
kustomize completion zsh > /usr/share/zsh/site-functions/_kustomize
|
||||
|
||||
COMP_UNINSTALL=1 kustomize install-completion
|
||||
|
||||
@@ -9,15 +9,11 @@ require (
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.4
|
||||
github.com/posener/complete/v2 v2.0.1-alpha.12
|
||||
github.com/spf13/cobra v1.0.0
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/stretchr/testify v1.6.1
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
||||
k8s.io/apimachinery v0.17.3
|
||||
sigs.k8s.io/kustomize/kyaml v0.9.1
|
||||
sigs.k8s.io/kustomize/kyaml v0.9.3
|
||||
)
|
||||
|
||||
replace sigs.k8s.io/kustomize/kyaml v0.9.1 => ../../kyaml
|
||||
|
||||
@@ -152,10 +152,6 @@ github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoA
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
@@ -226,14 +222,9 @@ github.com/paulmach/orb v0.1.3/go.mod h1:VFlX/8C+IQ1p6FTRRKzKoOPJnvEtA5G0Veuqwbu
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete/v2 v2.0.1-alpha.12 h1:0wvkuDfHb5vSZlNBYgpEH4XQHpF46MjLPHav8XC77Nc=
|
||||
github.com/posener/complete/v2 v2.0.1-alpha.12/go.mod h1://JlL91cS2JV7rOl6LVHrRqBXoBUecJu3ILQPgbJiMQ=
|
||||
github.com/posener/script v1.0.4 h1:nSuXW5ZdmFnQIueLB2s0qvs4oNsUloM1Zydzh75v42w=
|
||||
github.com/posener/script v1.0.4/go.mod h1:Rg3ijooqulo05aGLyGsHoLmIOUzHUVK19WVgrYBPU/E=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
@@ -400,6 +391,8 @@ k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
|
||||
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
|
||||
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a h1:UcxjrRMyNx/i/y8G7kPvLyy7rfbeuf1PYyBf973pgyU=
|
||||
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
|
||||
sigs.k8s.io/kustomize/kyaml v0.9.3 h1:kZ5HnNmmnbndSXFivrAVM6u3Ik1dwu4kbpaV8KNwy8I=
|
||||
sigs.k8s.io/kustomize/kyaml v0.9.3/go.mod h1:UTm64bSWVdBUA8EQoYCxVOaBQxUdIOr5LKWxA4GNbkw=
|
||||
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
|
||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/cmd/config/ext"
|
||||
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
|
||||
"sigs.k8s.io/kustomize/cmd/config/runner"
|
||||
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
@@ -27,7 +28,7 @@ func NewAnnotateRunner(parent string) *AnnotateRunner {
|
||||
Example: commands.AnnotateExamples,
|
||||
RunE: r.runE,
|
||||
}
|
||||
fixDocs(parent, c)
|
||||
runner.FixDocs(parent, c)
|
||||
r.Command = c
|
||||
c.Flags().StringVar(&r.Kind, "kind", "", "Resource kind to annotate")
|
||||
c.Flags().StringVar(&r.ApiVersion, "apiVersion", "", "Resource apiVersion to annotate")
|
||||
@@ -62,29 +63,29 @@ func (r *AnnotateRunner) runE(c *cobra.Command, args []string) error {
|
||||
input = []kio.Reader{rw}
|
||||
output = []kio.Writer{rw}
|
||||
|
||||
return handleError(c, kio.Pipeline{
|
||||
return runner.HandleError(c, kio.Pipeline{
|
||||
Inputs: input,
|
||||
Filters: []kio.Filter{r},
|
||||
Outputs: output,
|
||||
}.Execute())
|
||||
}
|
||||
|
||||
e := executeCmdOnPkgs{
|
||||
writer: c.OutOrStdout(),
|
||||
needOpenAPI: false,
|
||||
recurseSubPackages: r.RecurseSubPackages,
|
||||
cmdRunner: r,
|
||||
rootPkgPath: args[0],
|
||||
e := runner.ExecuteCmdOnPkgs{
|
||||
Writer: c.OutOrStdout(),
|
||||
NeedOpenAPI: false,
|
||||
RecurseSubPackages: r.RecurseSubPackages,
|
||||
CmdRunner: r,
|
||||
RootPkgPath: args[0],
|
||||
}
|
||||
|
||||
err := e.execute()
|
||||
err := e.Execute()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *AnnotateRunner) executeCmd(w io.Writer, pkgPath string) error {
|
||||
func (r *AnnotateRunner) ExecuteCmd(w io.Writer, pkgPath string) error {
|
||||
rw := &kio.LocalPackageReadWriter{
|
||||
PackagePath: pkgPath,
|
||||
NoDeleteFiles: true,
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/cmd/config/ext"
|
||||
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
|
||||
"sigs.k8s.io/kustomize/cmd/config/runner"
|
||||
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio/filters"
|
||||
@@ -30,7 +31,7 @@ func GetCatRunner(name string) *CatRunner {
|
||||
RunE: r.runE,
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
}
|
||||
fixDocs(name, c)
|
||||
runner.FixDocs(name, c)
|
||||
c.Flags().BoolVar(&r.Format, "format", true,
|
||||
"format resource config yaml before printing.")
|
||||
c.Flags().BoolVar(&r.KeepAnnotations, "annotate", false,
|
||||
@@ -95,21 +96,21 @@ func (r *CatRunner) runE(c *cobra.Command, args []string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return handleError(c, kio.Pipeline{Inputs: []kio.Reader{input}, Filters: r.catFilters(), Outputs: outputs}.Execute())
|
||||
return runner.HandleError(c, kio.Pipeline{Inputs: []kio.Reader{input}, Filters: r.catFilters(), Outputs: outputs}.Execute())
|
||||
}
|
||||
|
||||
out := &bytes.Buffer{}
|
||||
|
||||
e := executeCmdOnPkgs{
|
||||
writer: out,
|
||||
needOpenAPI: false,
|
||||
recurseSubPackages: r.RecurseSubPackages,
|
||||
cmdRunner: r,
|
||||
rootPkgPath: args[0],
|
||||
skipPkgPathPrint: true,
|
||||
e := runner.ExecuteCmdOnPkgs{
|
||||
Writer: out,
|
||||
NeedOpenAPI: false,
|
||||
RecurseSubPackages: r.RecurseSubPackages,
|
||||
CmdRunner: r,
|
||||
RootPkgPath: args[0],
|
||||
SkipPkgPathPrint: true,
|
||||
}
|
||||
|
||||
err := e.execute()
|
||||
err := e.Execute()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -120,7 +121,7 @@ func (r *CatRunner) runE(c *cobra.Command, args []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *CatRunner) executeCmd(w io.Writer, pkgPath string) error {
|
||||
func (r *CatRunner) ExecuteCmd(w io.Writer, pkgPath string) error {
|
||||
input := kio.LocalPackageReader{PackagePath: pkgPath, PackageFileName: ext.KRMFileName()}
|
||||
out := &bytes.Buffer{}
|
||||
outputs, err := r.out(out)
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/cmd/config/ext"
|
||||
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
|
||||
"sigs.k8s.io/kustomize/cmd/config/runner"
|
||||
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
"sigs.k8s.io/kustomize/kyaml/setters"
|
||||
@@ -63,7 +64,7 @@ func NewCreateSetterRunner(parent string) *CreateSetterRunner {
|
||||
set.Flags().BoolVarP(&r.CreateSetter.RecurseSubPackages, "recurse-subpackages", "R", false,
|
||||
"creates setter recursively in all the nested subpackages")
|
||||
set.Flags().MarkHidden("version")
|
||||
fixDocs(parent, set)
|
||||
runner.FixDocs(parent, set)
|
||||
r.Command = set
|
||||
return r
|
||||
}
|
||||
@@ -81,7 +82,7 @@ type CreateSetterRunner struct {
|
||||
}
|
||||
|
||||
func (r *CreateSetterRunner) runE(c *cobra.Command, args []string) error {
|
||||
return handleError(c, r.createSetter(c, args))
|
||||
return runner.HandleError(c, r.createSetter(c, args))
|
||||
}
|
||||
|
||||
func (r *CreateSetterRunner) preRunE(c *cobra.Command, args []string) error {
|
||||
@@ -179,16 +180,16 @@ func (r *CreateSetterRunner) processSchema() error {
|
||||
|
||||
func (r *CreateSetterRunner) createSetter(c *cobra.Command, args []string) error {
|
||||
if setterVersion == "v2" {
|
||||
e := executeCmdOnPkgs{
|
||||
needOpenAPI: true,
|
||||
writer: c.OutOrStdout(),
|
||||
rootPkgPath: args[0],
|
||||
recurseSubPackages: r.CreateSetter.RecurseSubPackages,
|
||||
cmdRunner: r,
|
||||
e := runner.ExecuteCmdOnPkgs{
|
||||
NeedOpenAPI: true,
|
||||
Writer: c.OutOrStdout(),
|
||||
RootPkgPath: args[0],
|
||||
RecurseSubPackages: r.CreateSetter.RecurseSubPackages,
|
||||
CmdRunner: r,
|
||||
}
|
||||
err := e.execute()
|
||||
err := e.Execute()
|
||||
if err != nil {
|
||||
return handleError(c, err)
|
||||
return runner.HandleError(c, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -204,7 +205,7 @@ func (r *CreateSetterRunner) createSetter(c *cobra.Command, args []string) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *CreateSetterRunner) executeCmd(w io.Writer, pkgPath string) error {
|
||||
func (r *CreateSetterRunner) ExecuteCmd(w io.Writer, pkgPath string) error {
|
||||
r.CreateSetter = settersutil.SetterCreator{
|
||||
Name: r.CreateSetter.Name,
|
||||
SetBy: r.CreateSetter.SetBy,
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/cmd/config/ext"
|
||||
"sigs.k8s.io/kustomize/cmd/config/runner"
|
||||
"sigs.k8s.io/kustomize/kyaml/setters2/settersutil"
|
||||
)
|
||||
|
||||
@@ -32,7 +33,7 @@ func NewCreateSubstitutionRunner(parent string) *CreateSubstitutionRunner {
|
||||
"creates substitution recursively in all the nested subpackages")
|
||||
_ = cs.MarkFlagRequired("pattern")
|
||||
_ = cs.MarkFlagRequired("field-value")
|
||||
fixDocs(parent, cs)
|
||||
runner.FixDocs(parent, cs)
|
||||
r.Command = cs
|
||||
return r
|
||||
}
|
||||
@@ -49,22 +50,22 @@ type CreateSubstitutionRunner struct {
|
||||
}
|
||||
|
||||
func (r *CreateSubstitutionRunner) runE(c *cobra.Command, args []string) error {
|
||||
e := executeCmdOnPkgs{
|
||||
needOpenAPI: true,
|
||||
writer: c.OutOrStdout(),
|
||||
rootPkgPath: args[0],
|
||||
recurseSubPackages: r.CreateSubstitution.RecurseSubPackages,
|
||||
cmdRunner: r,
|
||||
e := runner.ExecuteCmdOnPkgs{
|
||||
NeedOpenAPI: true,
|
||||
Writer: c.OutOrStdout(),
|
||||
RootPkgPath: args[0],
|
||||
RecurseSubPackages: r.CreateSubstitution.RecurseSubPackages,
|
||||
CmdRunner: r,
|
||||
}
|
||||
err := e.execute()
|
||||
err := e.Execute()
|
||||
if err != nil {
|
||||
return handleError(c, err)
|
||||
return runner.HandleError(c, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *CreateSubstitutionRunner) executeCmd(w io.Writer, pkgPath string) error {
|
||||
func (r *CreateSubstitutionRunner) ExecuteCmd(w io.Writer, pkgPath string) error {
|
||||
r.CreateSubstitution = settersutil.SubstitutionCreator{
|
||||
Name: r.CreateSubstitution.Name,
|
||||
FieldName: r.CreateSubstitution.FieldName,
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/cmd/config/ext"
|
||||
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
|
||||
"sigs.k8s.io/kustomize/cmd/config/runner"
|
||||
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
|
||||
"sigs.k8s.io/kustomize/kyaml/setters2/settersutil"
|
||||
)
|
||||
@@ -29,7 +30,7 @@ func NewDeleteSetterRunner(parent string) *DeleteSetterRunner {
|
||||
}
|
||||
c.Flags().BoolVarP(&r.RecurseSubPackages, "recurse-subpackages", "R", false,
|
||||
"deletes setter recursively in all the nested subpackages")
|
||||
fixDocs(parent, c)
|
||||
runner.FixDocs(parent, c)
|
||||
r.Command = c
|
||||
|
||||
return r
|
||||
@@ -56,22 +57,21 @@ func (r *DeleteSetterRunner) preRunE(c *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
func (r *DeleteSetterRunner) runE(c *cobra.Command, args []string) error {
|
||||
e := executeCmdOnPkgs{
|
||||
needOpenAPI: true,
|
||||
writer: c.OutOrStdout(),
|
||||
rootPkgPath: args[0],
|
||||
recurseSubPackages: r.RecurseSubPackages,
|
||||
cmdRunner: r,
|
||||
e := runner.ExecuteCmdOnPkgs{
|
||||
NeedOpenAPI: true,
|
||||
Writer: c.OutOrStdout(),
|
||||
RootPkgPath: args[0],
|
||||
RecurseSubPackages: r.RecurseSubPackages,
|
||||
CmdRunner: r,
|
||||
}
|
||||
err := e.execute()
|
||||
err := e.Execute()
|
||||
if err != nil {
|
||||
return handleError(c, err)
|
||||
return runner.HandleError(c, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *DeleteSetterRunner) executeCmd(w io.Writer, pkgPath string) error {
|
||||
|
||||
func (r *DeleteSetterRunner) ExecuteCmd(w io.Writer, pkgPath string) error {
|
||||
r.DeleteSetter = settersutil.DeleterCreator{
|
||||
Name: r.DeleteSetter.Name,
|
||||
DefinitionPrefix: fieldmeta.SetterDefinitionPrefix,
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/cmd/config/ext"
|
||||
"sigs.k8s.io/kustomize/cmd/config/runner"
|
||||
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
|
||||
"sigs.k8s.io/kustomize/kyaml/setters2/settersutil"
|
||||
)
|
||||
@@ -25,7 +26,7 @@ func NewDeleteSubstitutionRunner(parent string) *DeleteSubstitutionRunner {
|
||||
}
|
||||
c.Flags().BoolVarP(&r.RecurseSubPackages, "recurse-subpackages", "R", false,
|
||||
"deletes substitution recursively in all the nested subpackages")
|
||||
fixDocs(parent, c)
|
||||
runner.FixDocs(parent, c)
|
||||
r.Command = c
|
||||
|
||||
return r
|
||||
@@ -52,21 +53,21 @@ func (r *DeleteSubstitutionRunner) preRunE(c *cobra.Command, args []string) erro
|
||||
}
|
||||
|
||||
func (r *DeleteSubstitutionRunner) runE(c *cobra.Command, args []string) error {
|
||||
e := executeCmdOnPkgs{
|
||||
needOpenAPI: true,
|
||||
writer: c.OutOrStdout(),
|
||||
rootPkgPath: args[0],
|
||||
recurseSubPackages: r.RecurseSubPackages,
|
||||
cmdRunner: r,
|
||||
e := runner.ExecuteCmdOnPkgs{
|
||||
NeedOpenAPI: true,
|
||||
Writer: c.OutOrStdout(),
|
||||
RootPkgPath: args[0],
|
||||
RecurseSubPackages: r.RecurseSubPackages,
|
||||
CmdRunner: r,
|
||||
}
|
||||
err := e.execute()
|
||||
err := e.Execute()
|
||||
if err != nil {
|
||||
return handleError(c, err)
|
||||
return runner.HandleError(c, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *DeleteSubstitutionRunner) executeCmd(w io.Writer, pkgPath string) error {
|
||||
func (r *DeleteSubstitutionRunner) ExecuteCmd(w io.Writer, pkgPath string) error {
|
||||
r.DeleteSubstitution = settersutil.DeleterCreator{
|
||||
Name: r.DeleteSubstitution.Name,
|
||||
DefinitionPrefix: fieldmeta.SubstitutionDefinitionPrefix,
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
|
||||
"sigs.k8s.io/kustomize/cmd/config/runner"
|
||||
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||
"sigs.k8s.io/kustomize/kyaml/krmfile"
|
||||
)
|
||||
@@ -26,7 +27,7 @@ func GetInitRunner(name string) *InitRunner {
|
||||
Example: commands.InitExamples,
|
||||
RunE: r.runE,
|
||||
}
|
||||
fixDocs(name, c)
|
||||
runner.FixDocs(name, c)
|
||||
r.Command = c
|
||||
return r
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/cmd/config/ext"
|
||||
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
|
||||
"sigs.k8s.io/kustomize/cmd/config/runner"
|
||||
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
|
||||
"sigs.k8s.io/kustomize/kyaml/setters"
|
||||
"sigs.k8s.io/kustomize/kyaml/setters2"
|
||||
@@ -37,7 +38,7 @@ func NewListSettersRunner(parent string) *ListSettersRunner {
|
||||
"include substitutions in the output")
|
||||
c.Flags().BoolVarP(&r.RecurseSubPackages, "recurse-subpackages", "R", true,
|
||||
"list setters recursively in all the nested subpackages")
|
||||
fixDocs(parent, c)
|
||||
runner.FixDocs(parent, c)
|
||||
r.Command = c
|
||||
return r
|
||||
}
|
||||
@@ -67,24 +68,24 @@ func (r *ListSettersRunner) preRunE(c *cobra.Command, args []string) error {
|
||||
|
||||
func (r *ListSettersRunner) runE(c *cobra.Command, args []string) error {
|
||||
if setterVersion == "v2" {
|
||||
e := executeCmdOnPkgs{
|
||||
needOpenAPI: true,
|
||||
writer: c.OutOrStdout(),
|
||||
rootPkgPath: args[0],
|
||||
recurseSubPackages: r.RecurseSubPackages,
|
||||
cmdRunner: r,
|
||||
e := runner.ExecuteCmdOnPkgs{
|
||||
NeedOpenAPI: true,
|
||||
Writer: c.OutOrStdout(),
|
||||
RootPkgPath: args[0],
|
||||
RecurseSubPackages: r.RecurseSubPackages,
|
||||
CmdRunner: r,
|
||||
}
|
||||
|
||||
err := e.execute()
|
||||
err := e.Execute()
|
||||
if err != nil {
|
||||
return handleError(c, err)
|
||||
return runner.HandleError(c, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return handleError(c, lookup(r.Lookup, c, args))
|
||||
return runner.HandleError(c, lookup(r.Lookup, c, args))
|
||||
}
|
||||
|
||||
func (r *ListSettersRunner) executeCmd(w io.Writer, pkgPath string) error {
|
||||
func (r *ListSettersRunner) ExecuteCmd(w io.Writer, pkgPath string) error {
|
||||
r.List = setters2.List{
|
||||
Name: r.List.Name,
|
||||
OpenAPIFileName: ext.KRMFileName(),
|
||||
@@ -107,7 +108,7 @@ func (r *ListSettersRunner) ListSetters(w io.Writer, openAPIPath, resourcePath s
|
||||
return err
|
||||
}
|
||||
table := newTable(w, r.Markdown)
|
||||
table.SetHeader([]string{"NAME", "VALUE", "SET BY", "DESCRIPTION", "COUNT", "REQUIRED"})
|
||||
table.SetHeader([]string{"NAME", "VALUE", "SET BY", "DESCRIPTION", "COUNT", "REQUIRED", "IS SET"})
|
||||
for i := range r.List.Setters {
|
||||
s := r.List.Setters[i]
|
||||
v := s.Value
|
||||
@@ -117,20 +118,23 @@ func (r *ListSettersRunner) ListSetters(w io.Writer, openAPIPath, resourcePath s
|
||||
v = strings.Join(s.ListValues, ",")
|
||||
v = fmt.Sprintf("[%s]", v)
|
||||
}
|
||||
var required string
|
||||
required := "No"
|
||||
if s.Required {
|
||||
required = "Yes"
|
||||
} else {
|
||||
required = "No"
|
||||
}
|
||||
isSet := "No"
|
||||
if s.IsSet {
|
||||
isSet = "Yes"
|
||||
}
|
||||
|
||||
table.Append([]string{
|
||||
s.Name, v, s.SetBy, s.Description, fmt.Sprintf("%d", s.Count), required})
|
||||
s.Name, v, s.SetBy, s.Description, fmt.Sprintf("%d", s.Count), required, isSet})
|
||||
}
|
||||
table.Render()
|
||||
|
||||
if len(r.List.Setters) == 0 {
|
||||
// exit non-0 if no matching setters are found
|
||||
if ExitOnError {
|
||||
if runner.ExitOnError {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,8 +46,8 @@ metadata:
|
||||
spec:
|
||||
replicas: 3 # {"$ref": "#/definitions/io.k8s.cli.setters.replicas"}
|
||||
`,
|
||||
expected: ` NAME VALUE SET BY DESCRIPTION COUNT REQUIRED
|
||||
replicas 3 me hello world 1 Yes
|
||||
expected: ` NAME VALUE SET BY DESCRIPTION COUNT REQUIRED IS SET
|
||||
replicas 3 me hello world 1 Yes No
|
||||
`,
|
||||
},
|
||||
|
||||
@@ -72,8 +72,8 @@ metadata:
|
||||
spec:
|
||||
replicas: 3 # {"$ref": "#/definitions/io.k8s.cli.setters.replicas"}
|
||||
`,
|
||||
expected: ` NAME VALUE SET BY DESCRIPTION COUNT REQUIRED
|
||||
replicas 4 me hello world 1 No
|
||||
expected: ` NAME VALUE SET BY DESCRIPTION COUNT REQUIRED IS SET
|
||||
replicas 4 me hello world 1 No No
|
||||
`,
|
||||
},
|
||||
{
|
||||
@@ -131,10 +131,10 @@ spec:
|
||||
- name: nginx2
|
||||
image: nginx # {"$ref": "#/definitions/io.k8s.cli.setters.image"}
|
||||
`,
|
||||
expected: ` NAME VALUE SET BY DESCRIPTION COUNT REQUIRED
|
||||
image nginx me2 hello world 2 2 No
|
||||
replicas 3 me1 hello world 1 1 No
|
||||
tag 1.7.9 me3 hello world 3 1 Yes
|
||||
expected: ` NAME VALUE SET BY DESCRIPTION COUNT REQUIRED IS SET
|
||||
image nginx me2 hello world 2 2 No No
|
||||
replicas 3 me1 hello world 1 1 No No
|
||||
tag 1.7.9 me3 hello world 3 1 Yes No
|
||||
--------------- ----------- --------------
|
||||
SUBSTITUTION PATTERN REFERENCES
|
||||
image IMAGE:TAG [image,tag]
|
||||
@@ -207,10 +207,10 @@ spec:
|
||||
- name: nginx2
|
||||
image: nginx
|
||||
`,
|
||||
expected: ` NAME VALUE SET BY DESCRIPTION COUNT REQUIRED
|
||||
image nginx me2 hello world 2 3 No
|
||||
replicas 3 me1 hello world 1 2 No
|
||||
tag 1.7.9 me3 hello world 3 2 No
|
||||
expected: ` NAME VALUE SET BY DESCRIPTION COUNT REQUIRED IS SET
|
||||
image nginx me2 hello world 2 3 No No
|
||||
replicas 3 me1 hello world 1 2 No No
|
||||
tag 1.7.9 me3 hello world 3 2 No No
|
||||
--------------- ----------- --------------
|
||||
SUBSTITUTION PATTERN REFERENCES
|
||||
image IMAGE:TAG [image,tag]
|
||||
@@ -284,8 +284,8 @@ spec:
|
||||
- name: nginx2
|
||||
image: nginx
|
||||
`,
|
||||
expected: ` NAME VALUE SET BY DESCRIPTION COUNT REQUIRED
|
||||
image nginx me2 hello world 2 3 Yes
|
||||
expected: ` NAME VALUE SET BY DESCRIPTION COUNT REQUIRED IS SET
|
||||
image nginx me2 hello world 2 3 Yes No
|
||||
`,
|
||||
},
|
||||
|
||||
@@ -324,8 +324,8 @@ spec:
|
||||
- "b"
|
||||
- "c"
|
||||
`,
|
||||
expected: ` NAME VALUE SET BY DESCRIPTION COUNT REQUIRED
|
||||
list [a,b,c] me hello world 1 Yes
|
||||
expected: ` NAME VALUE SET BY DESCRIPTION COUNT REQUIRED IS SET
|
||||
list [a,b,c] me hello world 1 Yes No
|
||||
`,
|
||||
},
|
||||
|
||||
@@ -390,10 +390,10 @@ openAPI:
|
||||
name: my-other-setter
|
||||
value: nginxotherthing
|
||||
`,
|
||||
expected: ` NAME VALUE SET BY DESCRIPTION COUNT REQUIRED
|
||||
my-image-setter nginx 2 No
|
||||
my-other-setter nginxotherthing 1 No
|
||||
my-tag-setter 1.7.9 2 Yes
|
||||
expected: ` NAME VALUE SET BY DESCRIPTION COUNT REQUIRED IS SET
|
||||
my-image-setter nginx 2 No No
|
||||
my-other-setter nginxotherthing 1 No No
|
||||
my-tag-setter 1.7.9 2 Yes Yes
|
||||
------------------ ------------------------------------------------ -----------------------------------
|
||||
SUBSTITUTION PATTERN REFERENCES
|
||||
my-image-subst ${my-image-setter}::${my-tag-setter} [my-image-setter,my-tag-setter]
|
||||
@@ -476,20 +476,20 @@ func TestListSettersSubPackages(t *testing.T) {
|
||||
expected: `
|
||||
|
||||
test/testdata/dataset-with-setters/mysql/
|
||||
NAME VALUE SET BY DESCRIPTION COUNT REQUIRED
|
||||
image mysql 1 No
|
||||
namespace myspace 1 No
|
||||
tag 1.7.9 1 No
|
||||
NAME VALUE SET BY DESCRIPTION COUNT REQUIRED IS SET
|
||||
image mysql 1 No No
|
||||
namespace myspace 1 No No
|
||||
tag 1.7.9 1 No No
|
||||
--------------- ----------------- --------------
|
||||
SUBSTITUTION PATTERN REFERENCES
|
||||
image-tag ${image}:${tag} [image,tag]
|
||||
|
||||
test/testdata/dataset-with-setters/mysql/nosetters/
|
||||
NAME VALUE SET BY DESCRIPTION COUNT REQUIRED
|
||||
NAME VALUE SET BY DESCRIPTION COUNT REQUIRED IS SET
|
||||
|
||||
test/testdata/dataset-with-setters/mysql/storage/
|
||||
NAME VALUE SET BY DESCRIPTION COUNT REQUIRED
|
||||
namespace myspace 1 No
|
||||
NAME VALUE SET BY DESCRIPTION COUNT REQUIRED IS SET
|
||||
namespace myspace 1 No No
|
||||
`,
|
||||
},
|
||||
{
|
||||
@@ -499,10 +499,10 @@ test/testdata/dataset-with-setters/mysql/storage/
|
||||
expected: `
|
||||
|
||||
test/testdata/dataset-with-setters/mysql/
|
||||
NAME VALUE SET BY DESCRIPTION COUNT REQUIRED
|
||||
image mysql 1 No
|
||||
namespace myspace 1 No
|
||||
tag 1.7.9 1 No
|
||||
NAME VALUE SET BY DESCRIPTION COUNT REQUIRED IS SET
|
||||
image mysql 1 No No
|
||||
namespace myspace 1 No No
|
||||
tag 1.7.9 1 No No
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/cmd/config/ext"
|
||||
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
|
||||
"sigs.k8s.io/kustomize/cmd/config/runner"
|
||||
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
"sigs.k8s.io/kustomize/kyaml/setters"
|
||||
@@ -31,7 +32,7 @@ func NewSetRunner(parent string) *SetRunner {
|
||||
PreRunE: r.preRunE,
|
||||
RunE: r.runE,
|
||||
}
|
||||
fixDocs(parent, c)
|
||||
runner.FixDocs(parent, c)
|
||||
r.Command = c
|
||||
c.Flags().StringArrayVar(&r.Values, "values", []string{},
|
||||
"optional flag, the values of the setter to be set to")
|
||||
@@ -131,26 +132,26 @@ func (r *SetRunner) preRunE(c *cobra.Command, args []string) error {
|
||||
|
||||
func (r *SetRunner) runE(c *cobra.Command, args []string) error {
|
||||
if setterVersion == "v2" {
|
||||
e := executeCmdOnPkgs{
|
||||
needOpenAPI: true,
|
||||
writer: c.OutOrStdout(),
|
||||
rootPkgPath: args[0],
|
||||
recurseSubPackages: r.Set.RecurseSubPackages,
|
||||
cmdRunner: r,
|
||||
e := runner.ExecuteCmdOnPkgs{
|
||||
NeedOpenAPI: true,
|
||||
Writer: c.OutOrStdout(),
|
||||
RootPkgPath: args[0],
|
||||
RecurseSubPackages: r.Set.RecurseSubPackages,
|
||||
CmdRunner: r,
|
||||
}
|
||||
err := e.execute()
|
||||
err := e.Execute()
|
||||
if err != nil {
|
||||
return handleError(c, err)
|
||||
return runner.HandleError(c, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if len(args) > 2 || c.Flag("values").Changed {
|
||||
return handleError(c, r.perform(c, args))
|
||||
return runner.HandleError(c, r.perform(c, args))
|
||||
}
|
||||
return handleError(c, lookup(r.Lookup, c, args))
|
||||
return runner.HandleError(c, lookup(r.Lookup, c, args))
|
||||
}
|
||||
|
||||
func (r *SetRunner) executeCmd(w io.Writer, pkgPath string) error {
|
||||
func (r *SetRunner) ExecuteCmd(w io.Writer, pkgPath string) error {
|
||||
r.Set = settersutil.FieldSetter{
|
||||
Name: r.Set.Name,
|
||||
Value: r.Set.Value,
|
||||
@@ -162,6 +163,7 @@ func (r *SetRunner) executeCmd(w io.Writer, pkgPath string) error {
|
||||
OpenAPIFileName: ext.KRMFileName(),
|
||||
ResourcesPath: pkgPath,
|
||||
RecurseSubPackages: r.Set.RecurseSubPackages,
|
||||
IsSet: true,
|
||||
}
|
||||
count, err := r.Set.Set()
|
||||
if err != nil {
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/cmd/config/runner"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio/filters"
|
||||
)
|
||||
@@ -135,5 +136,5 @@ func (r *WrapRunner) runE(c *cobra.Command, args []string) error {
|
||||
Writer: c.OutOrStdout(),
|
||||
WrappingKind: kio.ResourceListKind,
|
||||
WrappingAPIVersion: kio.ResourceListAPIVersion}}}.Execute()
|
||||
return handleError(c, err)
|
||||
return runner.HandleError(c, err)
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"unicode"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/cmd/config/runner"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
@@ -211,7 +212,7 @@ func (r *XArgsRunner) runE(c *cobra.Command, _ []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return handleError(c, run.Run())
|
||||
return runner.HandleError(c, run.Run())
|
||||
}
|
||||
|
||||
func parseYNode(node *yaml.Node) string {
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/cmd/config/ext"
|
||||
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
|
||||
"sigs.k8s.io/kustomize/cmd/config/runner"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
"sigs.k8s.io/kustomize/kyaml/sets"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
@@ -26,7 +27,7 @@ func GetCountRunner(name string) *CountRunner {
|
||||
Example: commands.CountExamples,
|
||||
RunE: r.runE,
|
||||
}
|
||||
fixDocs(name, c)
|
||||
runner.FixDocs(name, c)
|
||||
c.Flags().BoolVar(&r.Kind, "kind", true,
|
||||
"count resources by kind.")
|
||||
c.Flags().BoolVarP(&r.RecurseSubPackages, "recurse-subpackages", "R", true,
|
||||
@@ -51,24 +52,24 @@ func (r *CountRunner) runE(c *cobra.Command, args []string) error {
|
||||
if len(args) == 0 {
|
||||
input := &kio.ByteReader{Reader: c.InOrStdin()}
|
||||
|
||||
return handleError(c, kio.Pipeline{
|
||||
return runner.HandleError(c, kio.Pipeline{
|
||||
Inputs: []kio.Reader{input},
|
||||
Outputs: r.out(c.OutOrStdout()),
|
||||
}.Execute())
|
||||
}
|
||||
|
||||
e := executeCmdOnPkgs{
|
||||
writer: c.OutOrStdout(),
|
||||
needOpenAPI: false,
|
||||
recurseSubPackages: r.RecurseSubPackages,
|
||||
cmdRunner: r,
|
||||
rootPkgPath: args[0],
|
||||
e := runner.ExecuteCmdOnPkgs{
|
||||
Writer: c.OutOrStdout(),
|
||||
NeedOpenAPI: false,
|
||||
RecurseSubPackages: r.RecurseSubPackages,
|
||||
CmdRunner: r,
|
||||
RootPkgPath: args[0],
|
||||
}
|
||||
|
||||
return e.execute()
|
||||
return e.Execute()
|
||||
}
|
||||
|
||||
func (r *CountRunner) executeCmd(w io.Writer, pkgPath string) error {
|
||||
func (r *CountRunner) ExecuteCmd(w io.Writer, pkgPath string) error {
|
||||
input := kio.LocalPackageReader{PackagePath: pkgPath, PackageFileName: ext.KRMFileName()}
|
||||
|
||||
err := kio.Pipeline{
|
||||
|
||||
@@ -35,8 +35,8 @@ openAPI:
|
||||
},
|
||||
expectedStdOut: `
|
||||
./
|
||||
NAME VALUE SET BY DESCRIPTION COUNT REQUIRED
|
||||
replicas 3 1 No
|
||||
NAME VALUE SET BY DESCRIPTION COUNT REQUIRED IS SET
|
||||
replicas 3 1 No No
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/cmd/config/ext"
|
||||
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
|
||||
"sigs.k8s.io/kustomize/cmd/config/runner"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio/filters"
|
||||
)
|
||||
@@ -25,7 +26,7 @@ func GetFmtRunner(name string) *FmtRunner {
|
||||
RunE: r.runE,
|
||||
PreRunE: r.preRunE,
|
||||
}
|
||||
fixDocs(name, c)
|
||||
runner.FixDocs(name, c)
|
||||
c.Flags().StringVar(&r.FilenamePattern, "pattern", filters.DefaultFilenamePattern,
|
||||
`pattern to use for generating filenames for resources -- may contain the following
|
||||
formatting substitution verbs {'%n': 'metadata.name', '%s': 'metadata.namespace', '%k': 'kind'}`)
|
||||
@@ -74,20 +75,20 @@ func (r *FmtRunner) runE(c *cobra.Command, args []string) error {
|
||||
Writer: c.OutOrStdout(),
|
||||
KeepReaderAnnotations: r.KeepAnnotations,
|
||||
}
|
||||
return handleError(c, kio.Pipeline{
|
||||
return runner.HandleError(c, kio.Pipeline{
|
||||
Inputs: []kio.Reader{rw}, Filters: r.fmtFilters(), Outputs: []kio.Writer{rw}}.Execute())
|
||||
}
|
||||
|
||||
for _, rootPkgPath := range args {
|
||||
e := executeCmdOnPkgs{
|
||||
writer: c.OutOrStdout(),
|
||||
needOpenAPI: false,
|
||||
recurseSubPackages: r.RecurseSubPackages,
|
||||
cmdRunner: r,
|
||||
rootPkgPath: rootPkgPath,
|
||||
e := runner.ExecuteCmdOnPkgs{
|
||||
Writer: c.OutOrStdout(),
|
||||
NeedOpenAPI: false,
|
||||
RecurseSubPackages: r.RecurseSubPackages,
|
||||
CmdRunner: r,
|
||||
RootPkgPath: rootPkgPath,
|
||||
}
|
||||
|
||||
err := e.execute()
|
||||
err := e.Execute()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -95,7 +96,7 @@ func (r *FmtRunner) runE(c *cobra.Command, args []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *FmtRunner) executeCmd(w io.Writer, pkgPath string) error {
|
||||
func (r *FmtRunner) ExecuteCmd(w io.Writer, pkgPath string) error {
|
||||
rw := &kio.LocalPackageReadWriter{
|
||||
NoDeleteFiles: true,
|
||||
PackagePath: pkgPath,
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
"sigs.k8s.io/kustomize/cmd/config/ext"
|
||||
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
|
||||
"sigs.k8s.io/kustomize/cmd/config/runner"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio/filters"
|
||||
)
|
||||
@@ -29,7 +30,7 @@ func GetGrepRunner(name string) *GrepRunner {
|
||||
RunE: r.runE,
|
||||
Args: cobra.MaximumNArgs(2),
|
||||
}
|
||||
fixDocs(name, c)
|
||||
runner.FixDocs(name, c)
|
||||
c.Flags().BoolVar(&r.KeepAnnotations, "annotate", true,
|
||||
"annotate resources with their file origins.")
|
||||
c.Flags().BoolVarP(&r.InvertMatch, "invert-match", "", false,
|
||||
@@ -66,7 +67,7 @@ func (r *GrepRunner) preRunE(c *cobra.Command, args []string) error {
|
||||
|
||||
return qa.Cmp(qb), err
|
||||
}
|
||||
parts, err := parseFieldPath(args[0])
|
||||
parts, err := runner.ParseFieldPath(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -105,7 +106,7 @@ func (r *GrepRunner) preRunE(c *cobra.Command, args []string) error {
|
||||
func (r *GrepRunner) runE(c *cobra.Command, args []string) error {
|
||||
if len(args) == 1 {
|
||||
input := &kio.ByteReader{Reader: c.InOrStdin()}
|
||||
return handleError(c, kio.Pipeline{
|
||||
return runner.HandleError(c, kio.Pipeline{
|
||||
Inputs: []kio.Reader{input},
|
||||
Filters: []kio.Filter{r.GrepFilter},
|
||||
Outputs: []kio.Writer{kio.ByteWriter{
|
||||
@@ -117,16 +118,16 @@ func (r *GrepRunner) runE(c *cobra.Command, args []string) error {
|
||||
|
||||
out := bytes.Buffer{}
|
||||
|
||||
e := executeCmdOnPkgs{
|
||||
writer: &out,
|
||||
needOpenAPI: false,
|
||||
recurseSubPackages: r.RecurseSubPackages,
|
||||
cmdRunner: r,
|
||||
rootPkgPath: args[1],
|
||||
skipPkgPathPrint: true,
|
||||
e := runner.ExecuteCmdOnPkgs{
|
||||
Writer: &out,
|
||||
NeedOpenAPI: false,
|
||||
RecurseSubPackages: r.RecurseSubPackages,
|
||||
CmdRunner: r,
|
||||
RootPkgPath: args[1],
|
||||
SkipPkgPathPrint: true,
|
||||
}
|
||||
|
||||
err := e.execute()
|
||||
err := e.Execute()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -138,7 +139,7 @@ func (r *GrepRunner) runE(c *cobra.Command, args []string) error {
|
||||
|
||||
}
|
||||
|
||||
func (r *GrepRunner) executeCmd(w io.Writer, pkgPath string) error {
|
||||
func (r *GrepRunner) ExecuteCmd(w io.Writer, pkgPath string) error {
|
||||
input := kio.LocalPackageReader{PackagePath: pkgPath, PackageFileName: ext.KRMFileName()}
|
||||
out := &bytes.Buffer{}
|
||||
err := kio.Pipeline{
|
||||
|
||||
@@ -6,6 +6,7 @@ package commands
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
|
||||
"sigs.k8s.io/kustomize/cmd/config/runner"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio/filters"
|
||||
)
|
||||
@@ -19,7 +20,7 @@ func GetMergeRunner(name string) *MergeRunner {
|
||||
Example: commands.MergeExamples,
|
||||
RunE: r.runE,
|
||||
}
|
||||
fixDocs(name, c)
|
||||
runner.FixDocs(name, c)
|
||||
r.Command = c
|
||||
r.Command.Flags().BoolVar(&r.InvertOrder, "invert-order", false,
|
||||
"if true, merge Resources in the reverse order")
|
||||
@@ -64,5 +65,5 @@ func (r *MergeRunner) runE(c *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
filters := []kio.Filter{filters.MergeFilter{}, filters.FormatFilter{}}
|
||||
return handleError(c, kio.Pipeline{Inputs: inputs, Filters: filters, Outputs: outputs}.Execute())
|
||||
return runner.HandleError(c, kio.Pipeline{Inputs: inputs, Filters: filters, Outputs: outputs}.Execute())
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ package commands
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
|
||||
"sigs.k8s.io/kustomize/cmd/config/runner"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio/filters"
|
||||
)
|
||||
|
||||
@@ -18,7 +19,7 @@ func GetMerge3Runner(name string) *Merge3Runner {
|
||||
Example: commands.Merge3Examples,
|
||||
RunE: r.runE,
|
||||
}
|
||||
fixDocs(name, c)
|
||||
runner.FixDocs(name, c)
|
||||
c.Flags().StringVar(&r.ancestor, "ancestor", "",
|
||||
"Path to original package")
|
||||
c.Flags().StringVar(&r.fromDir, "from", "",
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/cmd/config/runner"
|
||||
|
||||
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||
"sigs.k8s.io/kustomize/kyaml/fn/runtime/runtimeutil"
|
||||
@@ -29,7 +30,7 @@ func GetRunFnRunner(name string) *RunFnRunner {
|
||||
RunE: r.runE,
|
||||
PreRunE: r.preRunE,
|
||||
}
|
||||
fixDocs(name, c)
|
||||
runner.FixDocs(name, c)
|
||||
c.Flags().BoolVar(&r.IncludeSubpackages, "include-subpackages", true,
|
||||
"also print resources from subpackages.")
|
||||
r.Command = c
|
||||
@@ -103,7 +104,7 @@ type RunFnRunner struct {
|
||||
}
|
||||
|
||||
func (r *RunFnRunner) runE(c *cobra.Command, args []string) error {
|
||||
return handleError(c, r.RunFns.Execute())
|
||||
return runner.HandleError(c, r.RunFns.Execute())
|
||||
}
|
||||
|
||||
// getContainerFunctions parses the commandline flags and arguments into explicit
|
||||
|
||||
@@ -6,6 +6,7 @@ package commands
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
|
||||
"sigs.k8s.io/kustomize/cmd/config/runner"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio/kioutil"
|
||||
)
|
||||
@@ -21,7 +22,7 @@ func GetSinkRunner(name string) *SinkRunner {
|
||||
RunE: r.runE,
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
}
|
||||
fixDocs(name, c)
|
||||
runner.FixDocs(name, c)
|
||||
r.Command = c
|
||||
return r
|
||||
}
|
||||
@@ -49,5 +50,5 @@ func (r *SinkRunner) runE(c *cobra.Command, args []string) error {
|
||||
err := kio.Pipeline{
|
||||
Inputs: []kio.Reader{&kio.ByteReader{Reader: c.InOrStdin()}},
|
||||
Outputs: outputs}.Execute()
|
||||
return handleError(c, err)
|
||||
return runner.HandleError(c, err)
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
|
||||
"sigs.k8s.io/kustomize/cmd/config/runner"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
@@ -22,7 +23,7 @@ func GetSourceRunner(name string) *SourceRunner {
|
||||
Example: commands.SourceExamples,
|
||||
RunE: r.runE,
|
||||
}
|
||||
fixDocs(name, c)
|
||||
runner.FixDocs(name, c)
|
||||
c.Flags().StringVar(&r.WrapKind, "wrap-kind", kio.ResourceListKind,
|
||||
"output using this format.")
|
||||
c.Flags().StringVar(&r.WrapApiVersion, "wrap-version", kio.ResourceListAPIVersion,
|
||||
@@ -78,5 +79,5 @@ func (r *SourceRunner) runE(c *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
err := kio.Pipeline{Inputs: inputs, Outputs: outputs}.Execute()
|
||||
return handleError(c, err)
|
||||
return runner.HandleError(c, err)
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
"sigs.k8s.io/kustomize/cmd/config/ext"
|
||||
"sigs.k8s.io/kustomize/cmd/config/internal/generateddocs/commands"
|
||||
"sigs.k8s.io/kustomize/cmd/config/runner"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio/filters"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
@@ -26,7 +27,7 @@ func GetTreeRunner(name string) *TreeRunner {
|
||||
RunE: r.runE,
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
}
|
||||
fixDocs(name, c)
|
||||
runner.FixDocs(name, c)
|
||||
|
||||
// TODO(pwittrock): Figure out if these are the right things to expose, and consider making it
|
||||
// a list of options instead of individual flags
|
||||
@@ -91,7 +92,7 @@ func (r *TreeRunner) runE(c *cobra.Command, args []string) error {
|
||||
|
||||
var fields []kio.TreeWriterField
|
||||
for _, field := range r.fields {
|
||||
path, err := parseFieldPath(field)
|
||||
path, err := runner.ParseFieldPath(field)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -155,7 +156,7 @@ func (r *TreeRunner) runE(c *cobra.Command, args []string) error {
|
||||
ExcludeNonLocalConfig: r.excludeNonLocal,
|
||||
}}
|
||||
|
||||
return handleError(c, kio.Pipeline{
|
||||
return runner.HandleError(c, kio.Pipeline{
|
||||
Inputs: []kio.Reader{input},
|
||||
Filters: fltrs,
|
||||
Outputs: []kio.Writer{kio.TreeWriter{
|
||||
|
||||
@@ -35,22 +35,26 @@ var CatExamples = `
|
||||
# unwrap Resource config from a directory in an ResourceList
|
||||
... | kustomize cfg cat`
|
||||
|
||||
var CompletionShort = `Install shell completion.`
|
||||
var CompletionShort = `Generate shell completion.`
|
||||
var CompletionLong = `
|
||||
Install shell completion for kustomize commands and flags -- supports bash, fish and zsh.
|
||||
Generate shell completion for ` + "`" + `kustomize` + "`" + ` -- supports bash, zsh, fish and powershell.
|
||||
`
|
||||
var CompletionExamples = `
|
||||
# load completion for Bash
|
||||
source <(kustomize completion bash)
|
||||
|
||||
kustomize install-completion
|
||||
# install for Bash in Linux
|
||||
kustomize completion bash > /etc/bash_completion.d/kustomize
|
||||
|
||||
Registers the completion command with known shells (e.g. .bashrc, .bash_profile, etc):
|
||||
# install for Bash in MacOS
|
||||
kustomize completion bash > /usr/local/etc/bash_completion.d/kustomize
|
||||
|
||||
complete -C /Users/USER/go/bin/kustomize kustomize
|
||||
# package for Bash
|
||||
kustomize completion bash > /usr/share/bash-completion/completions/kustomize
|
||||
|
||||
Because the completion command is embedded in kustomize directly, there is no need to update
|
||||
it separately from the kustomize binary.
|
||||
|
||||
To uninstall shell completion run:
|
||||
|
||||
COMP_UNINSTALL=1 kustomize install-completion`
|
||||
# package for zsh
|
||||
kustomize completion zsh > /usr/share/zsh/site-functions/_kustomize
|
||||
`
|
||||
|
||||
var CountShort = `[Alpha] Count Resources Config from a local directory.`
|
||||
var CountLong = `
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
package commands
|
||||
package runner
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -17,72 +17,72 @@ import (
|
||||
"sigs.k8s.io/kustomize/kyaml/pathutil"
|
||||
)
|
||||
|
||||
// cmdRunner interface holds executeCmd definition which executes respective command's
|
||||
// CmdRunner interface holds ExecuteCmd definition which executes respective command's
|
||||
// implementation on single package
|
||||
type cmdRunner interface {
|
||||
executeCmd(w io.Writer, pkgPath string) error
|
||||
type CmdRunner interface {
|
||||
ExecuteCmd(w io.Writer, pkgPath string) error
|
||||
}
|
||||
|
||||
// executeCmdOnPkgs struct holds the parameters necessary to
|
||||
// ExecuteCmdOnPkgs struct holds the parameters necessary to
|
||||
// execute the filter command on packages in rootPkgPath
|
||||
type executeCmdOnPkgs struct {
|
||||
rootPkgPath string
|
||||
recurseSubPackages bool
|
||||
needOpenAPI bool
|
||||
cmdRunner cmdRunner
|
||||
writer io.Writer
|
||||
skipPkgPathPrint bool
|
||||
type ExecuteCmdOnPkgs struct {
|
||||
RootPkgPath string
|
||||
RecurseSubPackages bool
|
||||
NeedOpenAPI bool
|
||||
CmdRunner CmdRunner
|
||||
Writer io.Writer
|
||||
SkipPkgPathPrint bool
|
||||
}
|
||||
|
||||
// executeCmdOnPkgs takes the function definition for a command to be executed on single package, applies that definition
|
||||
// ExecuteCmdOnPkgs takes the function definition for a command to be executed on single package, applies that definition
|
||||
// recursively on all the subpackages present in rootPkgPath if recurseSubPackages is true, else applies the command on rootPkgPath only
|
||||
func (e executeCmdOnPkgs) execute() error {
|
||||
pkgsPaths, err := pathutil.DirsWithFile(e.rootPkgPath, ext.KRMFileName(), e.recurseSubPackages)
|
||||
func (e ExecuteCmdOnPkgs) Execute() error {
|
||||
pkgsPaths, err := pathutil.DirsWithFile(e.RootPkgPath, ext.KRMFileName(), e.RecurseSubPackages)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(pkgsPaths) == 0 {
|
||||
// at this point, there are no openAPI files in the rootPkgPath
|
||||
if e.needOpenAPI {
|
||||
if e.NeedOpenAPI {
|
||||
// few executions need openAPI file to be present(ex: setters commands), if true throw an error
|
||||
return errors.Errorf("unable to find %q in package %q", ext.KRMFileName(), e.rootPkgPath)
|
||||
return errors.Errorf("unable to find %q in package %q", ext.KRMFileName(), e.RootPkgPath)
|
||||
}
|
||||
|
||||
// add root path for commands which doesn't need openAPI(ex: annotate, fmt)
|
||||
pkgsPaths = []string{e.rootPkgPath}
|
||||
pkgsPaths = []string{e.RootPkgPath}
|
||||
}
|
||||
|
||||
// for commands which doesn't need openAPI file, make sure that the root package is
|
||||
// included all the times
|
||||
if !e.needOpenAPI && !containsString(pkgsPaths, e.rootPkgPath) {
|
||||
pkgsPaths = append([]string{e.rootPkgPath}, pkgsPaths...)
|
||||
if !e.NeedOpenAPI && !containsString(pkgsPaths, e.RootPkgPath) {
|
||||
pkgsPaths = append([]string{e.RootPkgPath}, pkgsPaths...)
|
||||
}
|
||||
|
||||
for i := range pkgsPaths {
|
||||
pkgPath := pkgsPaths[i]
|
||||
// Add schema present in openAPI file for current package
|
||||
if e.needOpenAPI {
|
||||
if e.NeedOpenAPI {
|
||||
if err := openapi.AddSchemaFromFile(filepath.Join(pkgPath, ext.KRMFileName())); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if !e.skipPkgPathPrint {
|
||||
fmt.Fprintf(e.writer, "%s/\n", pkgPath)
|
||||
if !e.SkipPkgPathPrint {
|
||||
fmt.Fprintf(e.Writer, "%s/\n", pkgPath)
|
||||
}
|
||||
|
||||
err := e.cmdRunner.executeCmd(e.writer, pkgPath)
|
||||
err := e.CmdRunner.ExecuteCmd(e.Writer, pkgPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if i != len(pkgsPaths)-1 {
|
||||
fmt.Fprint(e.writer, "\n")
|
||||
fmt.Fprint(e.Writer, "\n")
|
||||
}
|
||||
|
||||
// Delete schema present in openAPI file for current package
|
||||
if e.needOpenAPI {
|
||||
if e.NeedOpenAPI {
|
||||
if err := openapi.DeleteSchemaInFile(filepath.Join(pkgPath, ext.KRMFileName())); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -91,8 +91,8 @@ func (e executeCmdOnPkgs) execute() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseFieldPath parse a flag value into a field path
|
||||
func parseFieldPath(path string) ([]string, error) {
|
||||
// ParseFieldPath parse a flag value into a field path
|
||||
func ParseFieldPath(path string) ([]string, error) {
|
||||
// fixup '\.' so we don't split on it
|
||||
match := strings.ReplaceAll(path, "\\.", "$$$$")
|
||||
parts := strings.Split(match, ".")
|
||||
@@ -118,7 +118,7 @@ func parseFieldPath(path string) ([]string, error) {
|
||||
return newParts, nil
|
||||
}
|
||||
|
||||
func handleError(c *cobra.Command, err error) error {
|
||||
func HandleError(c *cobra.Command, err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -145,7 +145,7 @@ var StackOnError bool
|
||||
const cmdName = "kustomize config"
|
||||
|
||||
// FixDocs replaces instances of old with new in the docs for c
|
||||
func fixDocs(new string, c *cobra.Command) {
|
||||
func FixDocs(new string, c *cobra.Command) {
|
||||
c.Use = strings.ReplaceAll(c.Use, cmdName, new)
|
||||
c.Short = strings.ReplaceAll(c.Short, cmdName, new)
|
||||
c.Long = strings.ReplaceAll(c.Long, cmdName, new)
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package commands
|
||||
package runner
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -76,14 +76,14 @@ ${baseDir}/subpkg2/subpkg3/
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
actual := &bytes.Buffer{}
|
||||
r := &TestRunner{}
|
||||
e := executeCmdOnPkgs{
|
||||
needOpenAPI: test.needOpenAPI,
|
||||
writer: actual,
|
||||
rootPkgPath: filepath.Join(dir, test.pkgPath),
|
||||
recurseSubPackages: test.recurse,
|
||||
cmdRunner: r,
|
||||
e := ExecuteCmdOnPkgs{
|
||||
NeedOpenAPI: test.needOpenAPI,
|
||||
Writer: actual,
|
||||
RootPkgPath: filepath.Join(dir, test.pkgPath),
|
||||
RecurseSubPackages: test.recurse,
|
||||
CmdRunner: r,
|
||||
}
|
||||
err := e.execute()
|
||||
err := e.Execute()
|
||||
if test.errMsg == "" {
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
@@ -170,7 +170,7 @@ func createTestDirStructure(dir string) error {
|
||||
|
||||
type TestRunner struct{}
|
||||
|
||||
func (r *TestRunner) executeCmd(w io.Writer, pkgPath string) error {
|
||||
func (r *TestRunner) ExecuteCmd(w io.Writer, pkgPath string) error {
|
||||
children, err := ioutil.ReadDir(pkgPath)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -482,8 +482,8 @@ k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl
|
||||
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc=
|
||||
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
|
||||
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw=
|
||||
sigs.k8s.io/kustomize/kyaml v0.9.1 h1:T7aNUraSioQp0NHJZtYjIhL/q8mqRzCiHcAKdvo09go=
|
||||
sigs.k8s.io/kustomize/kyaml v0.9.1/go.mod h1:UTm64bSWVdBUA8EQoYCxVOaBQxUdIOr5LKWxA4GNbkw=
|
||||
sigs.k8s.io/kustomize/kyaml v0.9.3 h1:kZ5HnNmmnbndSXFivrAVM6u3Ik1dwu4kbpaV8KNwy8I=
|
||||
sigs.k8s.io/kustomize/kyaml v0.9.3/go.mod h1:UTm64bSWVdBUA8EQoYCxVOaBQxUdIOr5LKWxA4GNbkw=
|
||||
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
|
||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
|
||||
8
cmd/prchecker/go.mod
Normal file
8
cmd/prchecker/go.mod
Normal file
@@ -0,0 +1,8 @@
|
||||
module sigs.k8s.io/kustomize/cmd/prchecker
|
||||
|
||||
go 1.15
|
||||
|
||||
require (
|
||||
github.com/google/go-github v17.0.0+incompatible
|
||||
github.com/google/go-querystring v1.0.0 // indirect
|
||||
)
|
||||
4
cmd/prchecker/go.sum
Normal file
4
cmd/prchecker/go.sum
Normal file
@@ -0,0 +1,4 @@
|
||||
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
|
||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
@@ -1,12 +1,16 @@
|
||||
// multi-module-span script:
|
||||
// A script which can detect when a pull request would make changes which
|
||||
// span a series of restricted directories (ex: multiple go modules or projects)
|
||||
// prchecker examines pull requests
|
||||
//
|
||||
// When a pull request includes files which span two modules the script will
|
||||
// exit with a non-zero exit code.
|
||||
// - When a PR includes files from multiple modules that we'd rather not
|
||||
// modify at the same time (in an effort to have more self-contained
|
||||
// release notes), the script will exit with a non-zero exit code.
|
||||
//
|
||||
// Running:
|
||||
// go run multi-module-span.go -owner=kubernetes-sigs -repo=kustomize -pr=2997 cmd/config api/ kustomize/ kyaml/
|
||||
// Usage:
|
||||
//
|
||||
// go run . \
|
||||
// -owner=kubernetes-sigs \
|
||||
// -repo=kustomize \
|
||||
// -pr=2997 \
|
||||
// cmd/config api kustomize kyaml
|
||||
|
||||
package main
|
||||
|
||||
@@ -251,8 +251,15 @@ specification of the cluster's desired state to
|
||||
point deployments to _new_ configMaps with _new_ names.
|
||||
`kustomize` makes this easy with its
|
||||
`configMapGenerator` directive and associated naming
|
||||
controls. A GC process in the k8s master eventually
|
||||
deletes unused configMaps.
|
||||
controls.
|
||||
|
||||
To remove outdated configMaps add a label
|
||||
to your resource, for example, kustomize-cleanup="true",
|
||||
and then you can use `kustomize` to prune old resources^
|
||||
|
||||
> ```
|
||||
> kustomize build | kubectl apply --prune -f- -l kustomize-cleanup="true"
|
||||
> ```
|
||||
|
||||
|
||||
### Create and use the overlay for _production_
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
|
||||
## ConfigMap generation and rolling updates
|
||||
|
||||
Kustomize provides two ways of adding ConfigMap in one `kustomization`, either by declaring ConfigMap as a [resource] or declaring ConfigMap from a ConfigMapGenerator. The formats inside `kustomization.yaml` are
|
||||
Kustomize provides two ways of adding ConfigMap in one `kustomization`, either by declaring ConfigMap as a [resource] or declaring ConfigMap from a ConfigMapGenerator. The formats inside `kustomization.yaml` are
|
||||
|
||||
> ```
|
||||
> # declare ConfigMap as a resource
|
||||
> resources:
|
||||
> - configmap.yaml
|
||||
>
|
||||
>
|
||||
> # declare ConfigMap from a ConfigMapGenerator
|
||||
> configMapGenerator:
|
||||
> - name: a-configmap
|
||||
@@ -28,7 +28,9 @@ In this demo, the same [hello_world](helloWorld/README.md) is used while the Con
|
||||
### Establish base and staging
|
||||
|
||||
Establish the base with a configMapGenerator
|
||||
|
||||
<!-- @establishBase @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
|
||||
@@ -46,16 +48,18 @@ commonLabels:
|
||||
resources:
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
configMapGenerator:
|
||||
- name: the-map
|
||||
literals:
|
||||
- altGreeting=Good Morning!
|
||||
configMapGenerator:
|
||||
- name: the-map
|
||||
literals:
|
||||
- altGreeting=Good Morning!
|
||||
- enableRisky="false"
|
||||
EOF
|
||||
```
|
||||
|
||||
Establish the staging with a patch applied to the ConfigMap
|
||||
|
||||
<!-- @establishStaging @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
OVERLAYS=$DEMO_HOME/overlays
|
||||
mkdir -p $OVERLAYS/staging
|
||||
@@ -92,8 +96,8 @@ configured with data from a configMap.
|
||||
|
||||
The deployment refers to this map by name:
|
||||
|
||||
|
||||
<!-- @showDeployment @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
grep -C 2 configMapKeyRef $BASE/deployment.yaml
|
||||
```
|
||||
@@ -106,12 +110,12 @@ changed, so such updates have no effect.
|
||||
The recommended way to change a deployment's
|
||||
configuration is to
|
||||
|
||||
1. create a new configMap with a new name,
|
||||
1. patch the _deployment_, modifying the name value of
|
||||
1. create a new configMap with a new name,
|
||||
1. patch the _deployment_, modifying the name value of
|
||||
the appropriate `configMapKeyRef` field.
|
||||
|
||||
This latter change initiates rolling update to the pods
|
||||
in the deployment. The older configMap, when no longer
|
||||
in the deployment. The older configMap, when no longer
|
||||
referenced by any other resource, is eventually [garbage
|
||||
collected](/../../issues/242).
|
||||
|
||||
@@ -120,6 +124,7 @@ collected](/../../issues/242).
|
||||
The _staging_ [variant] here has a configMap [patch]:
|
||||
|
||||
<!-- @showMapPatch @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
cat $OVERLAYS/staging/map.yaml
|
||||
```
|
||||
@@ -131,6 +136,7 @@ resource spec.
|
||||
The ConfigMap it modifies is declared from a configMapGenerator.
|
||||
|
||||
<!-- @showMapBase @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
grep -C 4 configMapGenerator $BASE/kustomization.yaml
|
||||
```
|
||||
@@ -139,11 +145,12 @@ For a patch to work, the names in the `metadata/name`
|
||||
fields must match.
|
||||
|
||||
However, the name values specified in the file are
|
||||
_not_ what gets used in the cluster. By design,
|
||||
kustomize modifies names of ConfigMaps declared from ConfigMapGenerator. To see the names
|
||||
_not_ what gets used in the cluster. By design,
|
||||
kustomize modifies names of ConfigMaps declared from ConfigMapGenerator. To see the names
|
||||
ultimately used in the cluster, just run kustomize:
|
||||
|
||||
<!-- @grepStagingName @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
kustomize build $OVERLAYS/staging |\
|
||||
grep -B 8 -A 1 staging-the-map
|
||||
@@ -161,7 +168,8 @@ The suffix to the configMap name is generated from a
|
||||
hash of the maps content - in this case the name suffix
|
||||
is _5276h4th55_:
|
||||
|
||||
<!-- @grepStagingHash -->
|
||||
<!-- @grepStagingHash @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
kustomize build $OVERLAYS/staging | grep 5276h4th55
|
||||
```
|
||||
@@ -170,6 +178,7 @@ Now modify the map patch, to change the greeting
|
||||
the server will use:
|
||||
|
||||
<!-- @changeMap @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
sed -i.bak 's/pineapple/kiwi/' $OVERLAYS/staging/map.yaml
|
||||
```
|
||||
@@ -184,6 +193,7 @@ kustomize build $OVERLAYS/staging |\
|
||||
Run kustomize again to see the new configMap names:
|
||||
|
||||
<!-- @grepStagingName @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
kustomize build $OVERLAYS/staging |\
|
||||
grep -B 8 -A 1 staging-the-map
|
||||
@@ -194,7 +204,8 @@ in three new names ending in _c2g8fcbf88_ - one in the
|
||||
configMap name itself, and two in the deployment that
|
||||
uses the map:
|
||||
|
||||
<!-- @countHashes -->
|
||||
<!-- @countHashes @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
test 3 == \
|
||||
$(kustomize build $OVERLAYS/staging | grep c2g8fcbf88 | wc -l); \
|
||||
@@ -204,7 +215,7 @@ test 3 == \
|
||||
Applying these resources to the cluster will result in
|
||||
a rolling update of the deployments pods, retargetting
|
||||
them from the _5276h4th55_ maps to the _c2g8fcbf88_
|
||||
maps. The system will later garbage collect the
|
||||
maps. The system will later garbage collect the
|
||||
unused maps.
|
||||
|
||||
## Rollback
|
||||
|
||||
@@ -102,7 +102,7 @@ For Spring Boot application, we can set an active profile through the environmen
|
||||
the application will pick up an extra `application-<profile>.properties` file. With this, we can customize the configMap in two
|
||||
steps. Add an environment variable through the patch and add a file to the configMap.
|
||||
|
||||
<!-- @customizeConfigMap @testAgainstLatestRelease -->
|
||||
<!-- @customizeConfigMap -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/patch.yaml
|
||||
apiVersion: apps/v1
|
||||
@@ -119,7 +119,7 @@ spec:
|
||||
value: prod
|
||||
EOF
|
||||
|
||||
kustomize edit add patch patch.yaml
|
||||
kustomize edit add patch --path patch.yaml --name sbdemo --kind Deployment --group apps --version v1
|
||||
|
||||
cat <<EOF >$DEMO_HOME/application-prod.properties
|
||||
spring.jpa.hibernate.ddl-auto=update
|
||||
@@ -281,20 +281,35 @@ The output contains
|
||||
|
||||
Add these patches to the kustomization:
|
||||
|
||||
<!-- @addPatch @testAgainstLatestRelease -->
|
||||
<!-- @addPatch -->
|
||||
```
|
||||
cd $DEMO_HOME
|
||||
kustomize edit add patch memorylimit_patch.yaml
|
||||
kustomize edit add patch healthcheck_patch.yaml
|
||||
kustomize edit add patch --path memorylimit_patch.yaml --name sbdemo --kind Deployment --group apps --version v1
|
||||
kustomize edit add patch --path healthcheck_patch.yaml --name sbdemo --kind Deployment --group apps --version v1
|
||||
```
|
||||
|
||||
`kustomization.yaml` should have patches field:
|
||||
|
||||
> ```
|
||||
> patchesStrategicMerge:
|
||||
> - patch.yaml
|
||||
> - memorylimit_patch.yaml
|
||||
> - healthcheck_patch.yaml
|
||||
> patches:
|
||||
> - path: patch.yaml
|
||||
> target:
|
||||
> group: apps
|
||||
> version: v1
|
||||
> kind: Deployment
|
||||
> name: sbdemo
|
||||
> - path: memorylimit_patch.yaml
|
||||
> target:
|
||||
> group: apps
|
||||
> version: v1
|
||||
> kind: Deployment
|
||||
> name: sbdemo
|
||||
> - path: healthcheck_patch.yaml
|
||||
> target:
|
||||
> group: apps
|
||||
> version: v1
|
||||
> kind: Deployment
|
||||
> name: sbdemo
|
||||
> ```
|
||||
|
||||
The output of the following command can now be applied
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
## ConfigMap 的生成和滚动更新
|
||||
|
||||
kustomize 提供了两种添加 ConfigMap 的方法:
|
||||
|
||||
- 将 ConfigMap 声明为 [resource]
|
||||
- 通过 ConfigMapGenerator 声明 ConfigMap
|
||||
|
||||
@@ -14,7 +15,7 @@ kustomize 提供了两种添加 ConfigMap 的方法:
|
||||
> # 将 ConfigMap 声明为 resource
|
||||
> resources:
|
||||
> - configmap.yaml
|
||||
>
|
||||
>
|
||||
> # 在 ConfigMapGenerator 中声明 ConfigMap
|
||||
> configMapGenerator:
|
||||
> - name: a-configmap
|
||||
@@ -30,7 +31,9 @@ kustomize 提供了两种添加 ConfigMap 的方法:
|
||||
### 建立 base 和 staging
|
||||
|
||||
使用 configMapGenerator 建立 base
|
||||
|
||||
<!-- @establishBase @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
|
||||
@@ -48,16 +51,18 @@ commonLabels:
|
||||
resources:
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
configMapGenerator:
|
||||
- name: the-map
|
||||
literals:
|
||||
- altGreeting=Good Morning!
|
||||
configMapGenerator:
|
||||
- name: the-map
|
||||
literals:
|
||||
- altGreeting=Good Morning!
|
||||
- enableRisky="false"
|
||||
EOF
|
||||
```
|
||||
|
||||
通过应用 ConfigMap patch 的方式建立 staging
|
||||
|
||||
<!-- @establishStaging @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
OVERLAYS=$DEMO_HOME/overlays
|
||||
mkdir -p $OVERLAYS/staging
|
||||
@@ -94,6 +99,7 @@ EOF
|
||||
deployment 按照名称引用此 ConfigMap :
|
||||
|
||||
<!-- @showDeployment @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
grep -C 2 configMapKeyRef $BASE/deployment.yaml
|
||||
```
|
||||
@@ -102,16 +108,17 @@ grep -C 2 configMapKeyRef $BASE/deployment.yaml
|
||||
|
||||
更改 Deployment 配置的推荐方法是:
|
||||
|
||||
1. 使用新名称创建一个新的 configMap
|
||||
2. 为_deployment_ 添加 patch,修改相应 `configMapKeyRef` 字段的名称值。
|
||||
1. 使用新名称创建一个新的 configMap
|
||||
2. 为*deployment* 添加 patch,修改相应 `configMapKeyRef` 字段的名称值。
|
||||
|
||||
后一种更改会启动对 deployment 中的 pod 的滚动更新。旧的 configMap 在不再被任何其他资源引用时最终会被[垃圾回收](/../../issues/242)。
|
||||
|
||||
### 如何使用 kustomize
|
||||
### 如何使用 kustomize
|
||||
|
||||
_staging_ 的 [variant] 包含一个 configMap 的 [patch]:
|
||||
|
||||
<!-- @showMapPatch @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
cat $OVERLAYS/staging/map.yaml
|
||||
```
|
||||
@@ -121,6 +128,7 @@ cat $OVERLAYS/staging/map.yaml
|
||||
在 ConfigMapGenerator 中声明 ConfigMap 的修改。
|
||||
|
||||
<!-- @showMapBase @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
grep -C 4 configMapGenerator $BASE/kustomization.yaml
|
||||
```
|
||||
@@ -130,6 +138,7 @@ grep -C 4 configMapGenerator $BASE/kustomization.yaml
|
||||
但是,文件中指定的名称值不是群集中使用的名称值。根据设计,kustomize 修改从 ConfigMapGenerator 声明的 ConfigMaps 的名称。要查看最终在群集中使用的名称,只需运行 kustomize:
|
||||
|
||||
<!-- @grepStagingName @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
kustomize build $OVERLAYS/staging |\
|
||||
grep -B 8 -A 1 staging-the-map
|
||||
@@ -141,7 +150,8 @@ kustomize build $OVERLAYS/staging |\
|
||||
|
||||
configMap 名称的后缀是由 map 内容的哈希生成的 - 在这种情况下,名称后缀是 _5276h4th55_ :
|
||||
|
||||
<!-- @grepStagingHash -->
|
||||
<!-- @grepStagingHash @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
kustomize build $OVERLAYS/staging | grep 5276h4th55
|
||||
```
|
||||
@@ -149,6 +159,7 @@ kustomize build $OVERLAYS/staging | grep 5276h4th55
|
||||
现在修改 map patch ,更改该服务将使用的问候消息:
|
||||
|
||||
<!-- @changeMap @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
sed -i.bak 's/pineapple/kiwi/' $OVERLAYS/staging/map.yaml
|
||||
```
|
||||
@@ -163,6 +174,7 @@ kustomize build $OVERLAYS/staging |\
|
||||
再次运行 kustomize 查看新的 configMap 名称:
|
||||
|
||||
<!-- @grepStagingName @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
kustomize build $OVERLAYS/staging |\
|
||||
grep -B 8 -A 1 staging-the-map
|
||||
@@ -170,7 +182,8 @@ kustomize build $OVERLAYS/staging |\
|
||||
|
||||
确认 configMap 内容的更改将会生成以 _c2g8fcbf88_ 结尾的三个新名称 - 一个在 configMap 的名称中,另两个在使用 ConfigMap 的 deployment 中:
|
||||
|
||||
<!-- @countHashes -->
|
||||
<!-- @countHashes @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
test 3 == \
|
||||
$(kustomize build $OVERLAYS/staging | grep c2g8fcbf88 | wc -l); \
|
||||
|
||||
@@ -89,7 +89,7 @@ cat kustomization.yaml
|
||||
1. 通过 patch 添加一个环境变量
|
||||
2. 将文件添加到 ConfigMap 中
|
||||
|
||||
<!-- @customizeConfigMap @testAgainstLatestRelease -->
|
||||
<!-- @customizeConfigMap -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/patch.yaml
|
||||
apiVersion: apps/v1
|
||||
@@ -106,7 +106,7 @@ spec:
|
||||
value: prod
|
||||
EOF
|
||||
|
||||
kustomize edit add patch patch.yaml
|
||||
kustomize edit add patch --path patch.yaml --name sbdemo --kind Deployment --group apps --version v1
|
||||
|
||||
cat <<EOF >$DEMO_HOME/application-prod.properties
|
||||
spring.jpa.hibernate.ddl-auto=update
|
||||
@@ -257,23 +257,38 @@ cat $DEMO_HOME/healthcheck_patch.yaml
|
||||
|
||||
将这些 patch 添加到 `kustomization.yaml` 中:
|
||||
|
||||
<!-- @addPatch @testAgainstLatestRelease -->
|
||||
<!-- @addPatch -->
|
||||
```
|
||||
cd $DEMO_HOME
|
||||
kustomize edit add patch memorylimit_patch.yaml
|
||||
kustomize edit add patch healthcheck_patch.yaml
|
||||
kustomize edit add patch --path memorylimit_patch.yaml --name sbdemo --kind Deployment --group apps --version v1
|
||||
kustomize edit add patch --path healthcheck_patch.yaml --name sbdemo --kind Deployment --group apps --version v1
|
||||
```
|
||||
|
||||
执行上面的命令后,`kustomization.yaml` 的 patchesStrategicMerge 字段如下:
|
||||
执行上面的命令后,`kustomization.yaml` 的 patches 字段如下:
|
||||
|
||||
> ```
|
||||
> patchesStrategicMerge:
|
||||
> - patch.yaml
|
||||
> - memorylimit_patch.yaml
|
||||
> - healthcheck_patch.yaml
|
||||
> patches:
|
||||
> - path: patch.yaml
|
||||
> target:
|
||||
> group: apps
|
||||
> version: v1
|
||||
> kind: Deployment
|
||||
> name: sbdemo
|
||||
> - path: memorylimit_patch.yaml
|
||||
> target:
|
||||
> group: apps
|
||||
> version: v1
|
||||
> kind: Deployment
|
||||
> name: sbdemo
|
||||
> - path: healthcheck_patch.yaml
|
||||
> target:
|
||||
> group: apps
|
||||
> version: v1
|
||||
> kind: Deployment
|
||||
> name: sbdemo
|
||||
> ```
|
||||
|
||||
现在就可以将完整的配置输出并在集群中部署(将结果通过管道输出给 `kubectl apply`),在生产环境创建Spring Boot 应用。
|
||||
现在就可以将完整的配置输出并在集群中部署(将结果通过管道输出给 `kubectl apply`),在生产环境创建 Spring Boot 应用。
|
||||
|
||||
<!-- @finalBuild @testAgainstLatestRelease -->
|
||||
```
|
||||
|
||||
@@ -9,7 +9,8 @@ require (
|
||||
github.com/spf13/pflag v1.0.5
|
||||
k8s.io/client-go v0.17.3
|
||||
sigs.k8s.io/kustomize/api v0.6.3
|
||||
sigs.k8s.io/kustomize/cmd/config v0.8.2
|
||||
sigs.k8s.io/kustomize/cmd/config v0.8.4
|
||||
sigs.k8s.io/kustomize/kyaml v0.9.3
|
||||
sigs.k8s.io/yaml v1.2.0
|
||||
)
|
||||
|
||||
@@ -20,5 +21,3 @@ exclude (
|
||||
)
|
||||
|
||||
replace sigs.k8s.io/kustomize/api v0.6.3 => ../api
|
||||
|
||||
replace sigs.k8s.io/kustomize/cmd/config v0.8.2 => ../cmd/config
|
||||
|
||||
@@ -229,12 +229,8 @@ github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:Fecb
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.0 h1:wvCrVc9TjDls6+YGAF2hAifE1E5U1+b4tH6KdvN3Gig=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo=
|
||||
github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I=
|
||||
github.com/hashicorp/go-version v1.1.0 h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PFRGzg0=
|
||||
@@ -339,10 +335,6 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
||||
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete/v2 v2.0.1-alpha.12 h1:0wvkuDfHb5vSZlNBYgpEH4XQHpF46MjLPHav8XC77Nc=
|
||||
github.com/posener/complete/v2 v2.0.1-alpha.12/go.mod h1://JlL91cS2JV7rOl6LVHrRqBXoBUecJu3ILQPgbJiMQ=
|
||||
github.com/posener/script v1.0.4 h1:nSuXW5ZdmFnQIueLB2s0qvs4oNsUloM1Zydzh75v42w=
|
||||
github.com/posener/script v1.0.4/go.mod h1:Rg3ijooqulo05aGLyGsHoLmIOUzHUVK19WVgrYBPU/E=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
@@ -606,8 +598,10 @@ k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl
|
||||
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc=
|
||||
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
|
||||
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw=
|
||||
sigs.k8s.io/kustomize/kyaml v0.9.1 h1:T7aNUraSioQp0NHJZtYjIhL/q8mqRzCiHcAKdvo09go=
|
||||
sigs.k8s.io/kustomize/kyaml v0.9.1/go.mod h1:UTm64bSWVdBUA8EQoYCxVOaBQxUdIOr5LKWxA4GNbkw=
|
||||
sigs.k8s.io/kustomize/cmd/config v0.8.4 h1:Lo26VjENBVfAOJu0v6w6C1cv5Zp9K8XRs39/0cb87+k=
|
||||
sigs.k8s.io/kustomize/cmd/config v0.8.4/go.mod h1:1+URiyIJrjdxCdCNDuh2SLyf+I36txRgubFI3PIg2Gc=
|
||||
sigs.k8s.io/kustomize/kyaml v0.9.3 h1:kZ5HnNmmnbndSXFivrAVM6u3Ik1dwu4kbpaV8KNwy8I=
|
||||
sigs.k8s.io/kustomize/kyaml v0.9.3/go.mod h1:UTm64bSWVdBUA8EQoYCxVOaBQxUdIOr5LKWxA4GNbkw=
|
||||
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||
|
||||
@@ -15,10 +15,11 @@ import (
|
||||
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
|
||||
"sigs.k8s.io/kustomize/api/k8sdeps/validator"
|
||||
"sigs.k8s.io/kustomize/api/konfig"
|
||||
shell_complete "sigs.k8s.io/kustomize/cmd/config/complete"
|
||||
"sigs.k8s.io/kustomize/cmd/config/completion"
|
||||
"sigs.k8s.io/kustomize/kustomize/v3/internal/commands/build"
|
||||
"sigs.k8s.io/kustomize/kustomize/v3/internal/commands/create"
|
||||
"sigs.k8s.io/kustomize/kustomize/v3/internal/commands/edit"
|
||||
"sigs.k8s.io/kustomize/kustomize/v3/internal/commands/openapi"
|
||||
"sigs.k8s.io/kustomize/kustomize/v3/internal/commands/version"
|
||||
)
|
||||
|
||||
@@ -38,11 +39,12 @@ See https://sigs.k8s.io/kustomize
|
||||
uf := kunstruct.NewKunstructuredFactoryImpl()
|
||||
v := validator.NewKustValidator()
|
||||
c.AddCommand(
|
||||
shell_complete.NewCommand(),
|
||||
completion.NewCommand(),
|
||||
build.NewCmdBuild(stdOut),
|
||||
edit.NewCmdEdit(fSys, v, uf),
|
||||
create.NewCmdCreate(fSys, uf),
|
||||
version.NewCmdVersion(stdOut),
|
||||
openapi.NewCmdOpenAPI(stdOut),
|
||||
)
|
||||
configcobra.AddCommands(c, "kustomize")
|
||||
|
||||
|
||||
@@ -9,54 +9,67 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/api/filesys"
|
||||
"sigs.k8s.io/kustomize/kustomize/v3/internal/commands/edit/patch"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
"sigs.k8s.io/kustomize/kustomize/v3/internal/commands/kustfile"
|
||||
"sigs.k8s.io/kustomize/kustomize/v3/internal/commands/util"
|
||||
)
|
||||
|
||||
type addPatchOptions struct {
|
||||
patchFilePaths []string
|
||||
Patch types.Patch
|
||||
}
|
||||
|
||||
// newCmdAddPatch adds the name of a file containing a patch to the kustomization file.
|
||||
func newCmdAddPatch(fSys filesys.FileSystem) *cobra.Command {
|
||||
var o addPatchOptions
|
||||
o.Patch.Target = &types.Selector{}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "patch",
|
||||
Short: "Add the name of a file containing a patch to the kustomization file.",
|
||||
Short: "Add an item to patches field.",
|
||||
Long: `This command will add an item to patches field in the kustomization file.
|
||||
Each item may:
|
||||
|
||||
- be either a strategic merge patch, or a JSON patch
|
||||
- be either a file, or an inline string
|
||||
- target a single resource or multiple resources
|
||||
|
||||
For more information please see https://kubernetes-sigs.github.io/kustomize/api-reference/kustomization/patches/
|
||||
`,
|
||||
Example: `
|
||||
add patch {filepath}`,
|
||||
add patch --path {filepath} --group {target group name} --version {target version}`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
err := o.Validate(args)
|
||||
err := o.Validate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return o.RunAddPatch(fSys)
|
||||
},
|
||||
}
|
||||
cmd.Flags().StringVar(&o.Patch.Path, "path", "", "Path to the patch file. Cannot be used with --patch at the same time.")
|
||||
cmd.Flags().StringVar(&o.Patch.Patch, "patch", "", "Literal string of patch content. Cannot be used with --path at the same time.")
|
||||
cmd.Flags().StringVar(&o.Patch.Target.Group, "group", "", "API group in patch target")
|
||||
cmd.Flags().StringVar(&o.Patch.Target.Version, "version", "", "API version in patch target")
|
||||
cmd.Flags().StringVar(&o.Patch.Target.Kind, "kind", "", "Resource kind in patch target")
|
||||
cmd.Flags().StringVar(&o.Patch.Target.Name, "name", "", "Resource name in patch target")
|
||||
cmd.Flags().StringVar(&o.Patch.Target.Namespace, "namespace", "", "Resource namespace in patch target")
|
||||
cmd.Flags().StringVar(&o.Patch.Target.AnnotationSelector, "annotation-selector", "", "annotationSelector in patch target")
|
||||
cmd.Flags().StringVar(&o.Patch.Target.LabelSelector, "label-selector", "", "labelSelector in patch target")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Validate validates addPatch command.
|
||||
func (o *addPatchOptions) Validate(args []string) error {
|
||||
if len(args) == 0 {
|
||||
return errors.New("must specify a patch file")
|
||||
func (o *addPatchOptions) Validate() error {
|
||||
if o.Patch.Patch != "" && o.Patch.Path != "" {
|
||||
return errors.New("patch and path can't be set at the same time")
|
||||
}
|
||||
if o.Patch.Patch == "" && o.Patch.Path == "" {
|
||||
return errors.New("must provide either patch or path")
|
||||
}
|
||||
o.patchFilePaths = args
|
||||
return nil
|
||||
}
|
||||
|
||||
// RunAddPatch runs addPatch command (do real work).
|
||||
func (o *addPatchOptions) RunAddPatch(fSys filesys.FileSystem) error {
|
||||
patches, err := util.GlobPatterns(fSys, o.patchFilePaths)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(patches) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
mf, err := kustfile.NewKustomizationFile(fSys)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -67,13 +80,18 @@ func (o *addPatchOptions) RunAddPatch(fSys filesys.FileSystem) error {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, p := range patches {
|
||||
if patch.Exist(m.PatchesStrategicMerge, p) {
|
||||
log.Printf("patch %s already in kustomization file", p)
|
||||
continue
|
||||
}
|
||||
m.PatchesStrategicMerge = patch.Append(m.PatchesStrategicMerge, p)
|
||||
// Omit target if it's empty
|
||||
emptyTarget := types.Selector{}
|
||||
if o.Patch.Target != nil && *o.Patch.Target == emptyTarget {
|
||||
o.Patch.Target = nil
|
||||
}
|
||||
for _, p := range m.Patches {
|
||||
if p.Equals(o.Patch) {
|
||||
log.Printf("patch %#v already in kustomization file", p)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
m.Patches = append(m.Patches, o.Patch)
|
||||
|
||||
return mf.Write(m)
|
||||
}
|
||||
|
||||
@@ -15,19 +15,34 @@ const (
|
||||
patchFileName = "myWonderfulPatch.yaml"
|
||||
patchFileContent = `
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit,
|
||||
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
`
|
||||
kind = "myKind"
|
||||
group = "myGroup"
|
||||
version = "myVersion"
|
||||
name = "myName"
|
||||
namespace = "myNamespace"
|
||||
annotationSelector = "myAnnotationSelector"
|
||||
labelSelector = "myLabelSelector"
|
||||
)
|
||||
|
||||
func TestAddPatchHappyPath(t *testing.T) {
|
||||
func TestAddPatchWithFilePath(t *testing.T) {
|
||||
fSys := filesys.MakeEmptyDirInMemory()
|
||||
fSys.WriteFile(patchFileName, []byte(patchFileContent))
|
||||
fSys.WriteFile(patchFileName+"another", []byte(patchFileContent))
|
||||
testutils_test.WriteTestKustomization(fSys)
|
||||
|
||||
cmd := newCmdAddPatch(fSys)
|
||||
args := []string{patchFileName + "*"}
|
||||
err := cmd.RunE(cmd, args)
|
||||
args := []string{
|
||||
"--path", patchFileName,
|
||||
"--kind", kind,
|
||||
"--group", group,
|
||||
"--version", version,
|
||||
"--name", name,
|
||||
"--namespace", namespace,
|
||||
"--annotation-selector", annotationSelector,
|
||||
"--label-selector", labelSelector,
|
||||
}
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
if err != nil {
|
||||
t.Errorf("unexpected cmd error: %v", err)
|
||||
}
|
||||
@@ -35,11 +50,42 @@ func TestAddPatchHappyPath(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Errorf("unexpected read error: %v", err)
|
||||
}
|
||||
if !strings.Contains(string(content), patchFileName) {
|
||||
t.Errorf("expected patch name in kustomization")
|
||||
for i := 1; i < len(args); i += 2 {
|
||||
if !strings.Contains(string(content), args[i]) {
|
||||
t.Errorf("expected flag value of %s in kustomization but got\n%s", args[i-1], content)
|
||||
}
|
||||
}
|
||||
if !strings.Contains(string(content), patchFileName+"another") {
|
||||
t.Errorf("expected patch name in kustomization")
|
||||
}
|
||||
|
||||
func TestAddPatchWithPatchContent(t *testing.T) {
|
||||
fSys := filesys.MakeEmptyDirInMemory()
|
||||
fSys.WriteFile(patchFileName, []byte(patchFileContent))
|
||||
testutils_test.WriteTestKustomization(fSys)
|
||||
|
||||
cmd := newCmdAddPatch(fSys)
|
||||
args := []string{
|
||||
"--patch", patchFileContent,
|
||||
"--kind", kind,
|
||||
"--group", group,
|
||||
"--version", version,
|
||||
"--name", name,
|
||||
"--namespace", namespace,
|
||||
"--annotation-selector", annotationSelector,
|
||||
"--label-selector", labelSelector,
|
||||
}
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
if err != nil {
|
||||
t.Errorf("unexpected cmd error: %v", err)
|
||||
}
|
||||
content, err := testutils_test.ReadTestKustomization(fSys)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected read error: %v", err)
|
||||
}
|
||||
for i := 1; i < len(args); i += 2 {
|
||||
if !strings.Contains(string(content), strings.Trim(args[i], " \n")) {
|
||||
t.Errorf("expected flag value of %s in kustomization but got\n%s", args[i-1], content)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,14 +95,24 @@ func TestAddPatchAlreadyThere(t *testing.T) {
|
||||
testutils_test.WriteTestKustomization(fSys)
|
||||
|
||||
cmd := newCmdAddPatch(fSys)
|
||||
args := []string{patchFileName}
|
||||
err := cmd.RunE(cmd, args)
|
||||
args := []string{
|
||||
"--path", patchFileName,
|
||||
"--kind", kind,
|
||||
"--group", group,
|
||||
"--version", version,
|
||||
"--name", name,
|
||||
"--namespace", namespace,
|
||||
"--annotation-selector", annotationSelector,
|
||||
"--label-selector", labelSelector,
|
||||
}
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected cmd error: %v", err)
|
||||
}
|
||||
|
||||
// adding an existing patch shouldn't return an error
|
||||
err = cmd.RunE(cmd, args)
|
||||
err = cmd.Execute()
|
||||
if err != nil {
|
||||
t.Errorf("unexpected cmd error: %v", err)
|
||||
}
|
||||
@@ -70,7 +126,7 @@ func TestAddPatchNoArgs(t *testing.T) {
|
||||
if err == nil {
|
||||
t.Errorf("expected error: %v", err)
|
||||
}
|
||||
if err.Error() != "must specify a patch file" {
|
||||
if err.Error() != "must provide either patch or path" {
|
||||
t.Errorf("incorrect error: %v", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
79
kustomize/internal/commands/edit/add/addtransformer.go
Normal file
79
kustomize/internal/commands/edit/add/addtransformer.go
Normal file
@@ -0,0 +1,79 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package add
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/api/filesys"
|
||||
"sigs.k8s.io/kustomize/kustomize/v3/internal/commands/kustfile"
|
||||
"sigs.k8s.io/kustomize/kustomize/v3/internal/commands/util"
|
||||
)
|
||||
|
||||
type addTransformerOptions struct {
|
||||
transformerFilePaths []string
|
||||
}
|
||||
|
||||
// newCmdAddTransformer adds the name of a file containing a transformer
|
||||
// configuration to the kustomization file.
|
||||
func newCmdAddTransformer(fSys filesys.FileSystem) *cobra.Command {
|
||||
var o addTransformerOptions
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "transformer",
|
||||
Short: "Add the name of a file containing a transformer configuration to the kustomization file.",
|
||||
Example: `
|
||||
add transformer {filepath}`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
err := o.Validate(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return o.RunAddTransformer(fSys)
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Validate validates add transformer command.
|
||||
func (o *addTransformerOptions) Validate(args []string) error {
|
||||
if len(args) == 0 {
|
||||
return errors.New("must specify a transformer file")
|
||||
}
|
||||
o.transformerFilePaths = args
|
||||
return nil
|
||||
}
|
||||
|
||||
// RunAddTransformer runs add transformer command (do real work).
|
||||
func (o *addTransformerOptions) RunAddTransformer(fSys filesys.FileSystem) error {
|
||||
transformers, err := util.GlobPatterns(fSys, o.transformerFilePaths)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(transformers) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
mf, err := kustfile.NewKustomizationFile(fSys)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m, err := mf.Read()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, t := range transformers {
|
||||
if kustfile.StringInSlice(t, m.Transformers) {
|
||||
log.Printf("transformer %s already in kustomization file", t)
|
||||
continue
|
||||
}
|
||||
m.Transformers = append(m.Transformers, t)
|
||||
}
|
||||
|
||||
return mf.Write(m)
|
||||
}
|
||||
109
kustomize/internal/commands/edit/add/addtransformer_test.go
Normal file
109
kustomize/internal/commands/edit/add/addtransformer_test.go
Normal file
@@ -0,0 +1,109 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package add
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"sigs.k8s.io/kustomize/api/filesys"
|
||||
"sigs.k8s.io/kustomize/kustomize/v3/internal/commands/kustfile"
|
||||
testutils_test "sigs.k8s.io/kustomize/kustomize/v3/internal/commands/testutils"
|
||||
)
|
||||
|
||||
const (
|
||||
transformerFileName = "myWonderfulTransformer.yaml"
|
||||
transformerFileContent = `
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit,
|
||||
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
`
|
||||
)
|
||||
|
||||
func TestAddTransformerHappyPath(t *testing.T) {
|
||||
fSys := filesys.MakeEmptyDirInMemory()
|
||||
fSys.WriteFile(transformerFileName, []byte(transformerFileContent))
|
||||
fSys.WriteFile(transformerFileName+"another", []byte(transformerFileContent))
|
||||
testutils_test.WriteTestKustomization(fSys)
|
||||
|
||||
cmd := newCmdAddTransformer(fSys)
|
||||
args := []string{transformerFileName + "*"}
|
||||
err := cmd.RunE(cmd, args)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected cmd error: %v", err)
|
||||
}
|
||||
content, err := testutils_test.ReadTestKustomization(fSys)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected read error: %v", err)
|
||||
}
|
||||
if !strings.Contains(string(content), transformerFileName) {
|
||||
t.Errorf("expected transformer name in kustomization")
|
||||
}
|
||||
if !strings.Contains(string(content), transformerFileName+"another") {
|
||||
t.Errorf("expected transformer name in kustomization")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddTransformerAlreadyThere(t *testing.T) {
|
||||
fSys := filesys.MakeEmptyDirInMemory()
|
||||
fSys.WriteFile(transformerFileName, []byte(transformerFileName))
|
||||
testutils_test.WriteTestKustomization(fSys)
|
||||
|
||||
cmd := newCmdAddTransformer(fSys)
|
||||
args := []string{transformerFileName}
|
||||
err := cmd.RunE(cmd, args)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected cmd error: %v", err)
|
||||
}
|
||||
|
||||
// adding an existing transformer shouldn't return an error
|
||||
err = cmd.RunE(cmd, args)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected cmd error: %v", err)
|
||||
}
|
||||
|
||||
// There can be only one. May it be the...
|
||||
mf, err := kustfile.NewKustomizationFile(fSys)
|
||||
if err != nil {
|
||||
t.Fatalf("error retrieving kustomization file: %v", err)
|
||||
}
|
||||
m, err := mf.Read()
|
||||
if err != nil {
|
||||
t.Fatalf("error reading kustomization file: %v", err)
|
||||
}
|
||||
|
||||
if len(m.Transformers) != 1 || m.Transformers[0] != transformerFileName {
|
||||
t.Errorf("expected transformers [%s]; got transformers [%s]", transformerFileName, strings.Join(m.Transformers, ","))
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddTransformerNoArgs(t *testing.T) {
|
||||
fSys := filesys.MakeFsInMemory()
|
||||
|
||||
cmd := newCmdAddTransformer(fSys)
|
||||
err := cmd.Execute()
|
||||
if err == nil {
|
||||
t.Errorf("expected error: %v", err)
|
||||
}
|
||||
if err.Error() != "must specify a transformer file" {
|
||||
t.Errorf("incorrect error: %v", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddTransformerMissingKustomizationYAML(t *testing.T) {
|
||||
fSys := filesys.MakeEmptyDirInMemory()
|
||||
fSys.WriteFile(transformerFileName, []byte(transformerFileContent))
|
||||
fSys.WriteFile(transformerFileName+"another", []byte(transformerFileContent))
|
||||
|
||||
cmd := newCmdAddTransformer(fSys)
|
||||
args := []string{transformerFileName + "*"}
|
||||
err := cmd.RunE(cmd, args)
|
||||
if err == nil {
|
||||
t.Errorf("expected error: %v", err)
|
||||
}
|
||||
fmt.Println(err.Error())
|
||||
if err.Error() != "Missing kustomization file 'kustomization.yaml'.\n" {
|
||||
t.Errorf("incorrect error: %v", err.Error())
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,7 @@ func NewCmdAdd(
|
||||
kustomize edit add resource <filepath>
|
||||
|
||||
# Adds a patch to the kustomization
|
||||
kustomize edit add patch <filepath>
|
||||
kustomize edit add patch --path {filepath} --group {target group name} --version {target version}
|
||||
|
||||
# Adds a component to the kustomization
|
||||
kustomize edit add component <filepath>
|
||||
@@ -43,6 +43,9 @@ func NewCmdAdd(
|
||||
|
||||
# Adds one or more commonAnnotations to the kustomization
|
||||
kustomize edit add annotation {annotationKey1:annotationValue1},{annotationKey2:annotationValue2}
|
||||
|
||||
# Adds a transformer configuration to the kustomization
|
||||
kustomize edit add transformer <filepath>
|
||||
`,
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
}
|
||||
@@ -55,6 +58,7 @@ func NewCmdAdd(
|
||||
newCmdAddBase(fSys),
|
||||
newCmdAddLabel(fSys, ldr.Validator().MakeLabelValidator()),
|
||||
newCmdAddAnnotation(fSys, ldr.Validator().MakeAnnotationValidator()),
|
||||
newCmdAddTransformer(fSys),
|
||||
)
|
||||
return c
|
||||
}
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package patch
|
||||
|
||||
import "sigs.k8s.io/kustomize/api/types"
|
||||
|
||||
// Append appends a slice of patch paths to a PatchStrategicMerge slice
|
||||
func Append(patches []types.PatchStrategicMerge, paths ...string) []types.PatchStrategicMerge {
|
||||
for _, p := range paths {
|
||||
patches = append(patches, types.PatchStrategicMerge(p))
|
||||
}
|
||||
return patches
|
||||
}
|
||||
|
||||
// Exist determines if a patch path exists in a slice of PatchStrategicMerge
|
||||
func Exist(patches []types.PatchStrategicMerge, path string) bool {
|
||||
for _, p := range patches {
|
||||
if p == types.PatchStrategicMerge(path) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Delete deletes patches from a PatchStrategicMerge slice
|
||||
func Delete(patches []types.PatchStrategicMerge, paths ...string) []types.PatchStrategicMerge {
|
||||
// Convert paths into PatchStrategicMerge slice
|
||||
convertedPath := make([]types.PatchStrategicMerge, len(paths))
|
||||
for i, p := range paths {
|
||||
convertedPath[i] = types.PatchStrategicMerge(p)
|
||||
}
|
||||
|
||||
filteredPatches := make([]types.PatchStrategicMerge, 0, len(patches))
|
||||
for _, containedPatch := range patches {
|
||||
if !Exist(convertedPath, string(containedPatch)) {
|
||||
filteredPatches = append(filteredPatches, containedPatch)
|
||||
}
|
||||
}
|
||||
return filteredPatches
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.
|
||||
|
||||
package patch
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
)
|
||||
|
||||
func buildPatchStrategicMergeSlice(patchStrings []string) []types.PatchStrategicMerge {
|
||||
var patches []types.PatchStrategicMerge
|
||||
for _, patchString := range patchStrings {
|
||||
patches = append(patches, types.PatchStrategicMerge(patchString))
|
||||
}
|
||||
return patches
|
||||
}
|
||||
|
||||
func TestAppend(t *testing.T) {
|
||||
patchStrings := []string{"patch1.yaml", "patch2.yaml"}
|
||||
patches := buildPatchStrategicMergeSlice(patchStrings)
|
||||
|
||||
patches = Append(patches, "patch3.yaml")
|
||||
|
||||
for i, k := range []string{"patch1.yaml", "patch2.yaml", "patch3.yaml"} {
|
||||
if patches[i] != types.PatchStrategicMerge(k) {
|
||||
t.Fatalf("patches[%d] must be %s, got %s", i, k, patches[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestExistTrue(t *testing.T) {
|
||||
patchStrings := []string{"patch1.yaml", "patch2.yaml"}
|
||||
patches := buildPatchStrategicMergeSlice(patchStrings)
|
||||
|
||||
for _, patchString := range patchStrings {
|
||||
if !Exist(patches, patchString) {
|
||||
t.Fatalf("%s must exist", patchString)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestExistFalse(t *testing.T) {
|
||||
patchStrings := []string{"patch1.yaml", "patch2.yaml"}
|
||||
patches := buildPatchStrategicMergeSlice(patchStrings)
|
||||
|
||||
for _, patchString := range []string{"invalid1.yaml", "invalid2.yaml"} {
|
||||
if Exist(patches, patchString) {
|
||||
t.Fatalf("%s must not exist", patchString)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDelete(t *testing.T) {
|
||||
patchStrings := []string{"patch1.yaml", "patch2.yaml"}
|
||||
patches := buildPatchStrategicMergeSlice(patchStrings)
|
||||
|
||||
patches = Delete(patches, "patch1.yaml")
|
||||
|
||||
if Exist(patches, "patch1.yaml") {
|
||||
t.Fatalf("patch1.yaml should be deleted")
|
||||
}
|
||||
if !Exist(patches, "patch2.yaml") {
|
||||
t.Fatalf("patch2.yaml should exist")
|
||||
}
|
||||
if len(patches) != 1 {
|
||||
t.Fatalf("Length of slice must be 1: actual %d", len(patches))
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteMultiple(t *testing.T) {
|
||||
patchStrings := []string{"patch1.yaml", "patch2.yaml"}
|
||||
patches := buildPatchStrategicMergeSlice(patchStrings)
|
||||
|
||||
patches = Delete(patches, "patch2.yaml", "patch4.yaml", "patch1.yaml", "patch3.yaml")
|
||||
|
||||
for _, k := range patchStrings {
|
||||
if Exist(patches, k) {
|
||||
t.Fatalf("%s should be deleted", k)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,13 +23,16 @@ func NewCmdRemove(
|
||||
kustomize edit remove resource {pattern}
|
||||
|
||||
# Removes one or more patches from the kustomization file
|
||||
kustomize edit remove patch <filepath>
|
||||
kustomize edit remove patch --path {filepath} --group {target group name} --version {target version}
|
||||
|
||||
# Removes one or more commonLabels from the kustomization file
|
||||
kustomize edit remove label {labelKey1},{labelKey2}
|
||||
|
||||
# Removes one or more commonAnnotations from the kustomization file
|
||||
kustomize edit remove annotation {annotationKey1},{annotationKey2}
|
||||
|
||||
# Removes one or more transformers from the kustomization file
|
||||
kustomize edit remove transformer <filepath>
|
||||
`,
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
}
|
||||
@@ -38,6 +41,7 @@ func NewCmdRemove(
|
||||
newCmdRemoveLabel(fSys, v.MakeLabelNameValidator()),
|
||||
newCmdRemoveAnnotation(fSys, v.MakeAnnotationNameValidator()),
|
||||
newCmdRemovePatch(fSys),
|
||||
newCmdRemoveTransformer(fSys),
|
||||
)
|
||||
return c
|
||||
}
|
||||
|
||||
@@ -10,55 +10,58 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/api/filesys"
|
||||
"sigs.k8s.io/kustomize/api/konfig"
|
||||
"sigs.k8s.io/kustomize/kustomize/v3/internal/commands/edit/patch"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
"sigs.k8s.io/kustomize/kustomize/v3/internal/commands/kustfile"
|
||||
"sigs.k8s.io/kustomize/kustomize/v3/internal/commands/util"
|
||||
)
|
||||
|
||||
type removePatchOptions struct {
|
||||
patchFilePaths []string
|
||||
Patch types.Patch
|
||||
}
|
||||
|
||||
// newCmdRemovePatch removes the name of a file containing a patch from the kustomization file.
|
||||
func newCmdRemovePatch(fSys filesys.FileSystem) *cobra.Command {
|
||||
var o removePatchOptions
|
||||
o.Patch.Target = &types.Selector{}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "patch",
|
||||
Short: "Removes one or more patches from " +
|
||||
Short: "Removes a patch from " +
|
||||
konfig.DefaultKustomizationFileName(),
|
||||
Long: `Removes a patch from patches field. The fields specified by flags must
|
||||
exactly match the patch item to successfully remote the item.`,
|
||||
Example: `
|
||||
remove patch {filepath}`,
|
||||
remove patch --path {filepath} --group {target group name} --version {target version}`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
err := o.Validate(args)
|
||||
err := o.Validate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return o.RunRemovePatch(fSys)
|
||||
},
|
||||
}
|
||||
cmd.Flags().StringVar(&o.Patch.Path, "path", "", "Path to the patch file. Cannot be used with --patch at the same time.")
|
||||
cmd.Flags().StringVar(&o.Patch.Patch, "patch", "", "Literal string of patch content. Cannot be used with --path at the same time.")
|
||||
cmd.Flags().StringVar(&o.Patch.Target.Group, "group", "", "API group in patch target")
|
||||
cmd.Flags().StringVar(&o.Patch.Target.Version, "version", "", "API version in patch target")
|
||||
cmd.Flags().StringVar(&o.Patch.Target.Kind, "kind", "", "Resource kind in patch target")
|
||||
cmd.Flags().StringVar(&o.Patch.Target.Name, "name", "", "Resource name in patch target")
|
||||
cmd.Flags().StringVar(&o.Patch.Target.Namespace, "namespace", "", "Resource namespace in patch target")
|
||||
cmd.Flags().StringVar(&o.Patch.Target.AnnotationSelector, "annotation-selector", "", "annotationSelector in patch target")
|
||||
cmd.Flags().StringVar(&o.Patch.Target.LabelSelector, "label-selector", "", "labelSelector in patch target")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Validate validates removePatch command.
|
||||
func (o *removePatchOptions) Validate(args []string) error {
|
||||
if len(args) == 0 {
|
||||
return errors.New("must specify a patch file")
|
||||
func (o *removePatchOptions) Validate() error {
|
||||
if o.Patch.Patch != "" && o.Patch.Path != "" {
|
||||
return errors.New("patch and path can't be set at the same time")
|
||||
}
|
||||
o.patchFilePaths = args
|
||||
return nil
|
||||
}
|
||||
|
||||
// RunRemovePatch runs removePatch command (do real work).
|
||||
func (o *removePatchOptions) RunRemovePatch(fSys filesys.FileSystem) error {
|
||||
patches, err := util.GlobPatterns(fSys, o.patchFilePaths)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(patches) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
mf, err := kustfile.NewKustomizationFile(fSys)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -69,15 +72,23 @@ func (o *removePatchOptions) RunRemovePatch(fSys filesys.FileSystem) error {
|
||||
return err
|
||||
}
|
||||
|
||||
var removePatches []string
|
||||
for _, p := range patches {
|
||||
if !patch.Exist(m.PatchesStrategicMerge, p) {
|
||||
log.Printf("patch %s doesn't exist in kustomization file", p)
|
||||
continue
|
||||
}
|
||||
removePatches = append(removePatches, p)
|
||||
// Omit target if it's empty
|
||||
emptyTarget := types.Selector{}
|
||||
if o.Patch.Target != nil && *o.Patch.Target == emptyTarget {
|
||||
o.Patch.Target = nil
|
||||
}
|
||||
m.PatchesStrategicMerge = patch.Delete(m.PatchesStrategicMerge, removePatches...)
|
||||
|
||||
var patches []types.Patch
|
||||
for _, p := range m.Patches {
|
||||
if !p.Equals(o.Patch) {
|
||||
patches = append(patches, p)
|
||||
}
|
||||
}
|
||||
if len(patches) == len(m.Patches) {
|
||||
log.Printf("patch %s doesn't exist in kustomization file", o.Patch)
|
||||
return nil
|
||||
}
|
||||
m.Patches = patches
|
||||
|
||||
return mf.Write(m)
|
||||
}
|
||||
|
||||
@@ -4,29 +4,53 @@
|
||||
package remove
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"sigs.k8s.io/kustomize/api/filesys"
|
||||
"sigs.k8s.io/kustomize/kustomize/v3/internal/commands/edit/patch"
|
||||
testutils_test "sigs.k8s.io/kustomize/kustomize/v3/internal/commands/testutils"
|
||||
)
|
||||
|
||||
const (
|
||||
patchFileContent = `
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit,
|
||||
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
`
|
||||
patchFileContent = `- op: replace
|
||||
path: /some/existing/path
|
||||
value: new value`
|
||||
kind = "myKind"
|
||||
group = "myGroup"
|
||||
version = "myVersion"
|
||||
name = "myName"
|
||||
namespace = "myNamespace"
|
||||
annotationSelector = "myAnnotationSelector"
|
||||
labelSelector = "myLabelSelector"
|
||||
)
|
||||
|
||||
func makeKustomizationPatchFS() filesys.FileSystem {
|
||||
fSys := filesys.MakeEmptyDirInMemory()
|
||||
patches := []string{"patch1.yaml", "patch2.yaml"}
|
||||
|
||||
testutils_test.WriteTestKustomizationWith(fSys, []byte(
|
||||
fmt.Sprintf("patchesStrategicMerge:\n - %s",
|
||||
strings.Join(patches, "\n - "))))
|
||||
testutils_test.WriteTestKustomizationWith(fSys, []byte(`
|
||||
patches:
|
||||
- path: patch1.yaml
|
||||
target:
|
||||
group: myGroup
|
||||
version: myVersion
|
||||
kind: myKind
|
||||
name: myName
|
||||
namespace: myNamespace
|
||||
labelSelector: myLabelSelector
|
||||
annotationSelector: myAnnotationSelector
|
||||
- path: patch2.yaml
|
||||
target:
|
||||
group: myGroup
|
||||
version: myVersion
|
||||
kind: myKind
|
||||
- patch: |-
|
||||
- op: replace
|
||||
path: /some/existing/path
|
||||
value: new value
|
||||
target:
|
||||
kind: myKind
|
||||
labelSelector: myLabelSelector
|
||||
`))
|
||||
|
||||
for _, p := range patches {
|
||||
fSys.WriteFile(p, []byte(patchFileContent))
|
||||
@@ -38,69 +62,86 @@ func makeKustomizationPatchFS() filesys.FileSystem {
|
||||
func TestRemovePatch(t *testing.T) {
|
||||
fSys := makeKustomizationPatchFS()
|
||||
cmd := newCmdRemovePatch(fSys)
|
||||
args := []string{"patch1.yaml"}
|
||||
err := cmd.RunE(cmd, args)
|
||||
patchPath := "patch1.yaml"
|
||||
args := []string{
|
||||
"--path", patchPath,
|
||||
"--kind", kind,
|
||||
"--group", group,
|
||||
"--version", version,
|
||||
"--name", name,
|
||||
"--namespace", namespace,
|
||||
"--annotation-selector", annotationSelector,
|
||||
"--label-selector", labelSelector,
|
||||
}
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error %v", err)
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
|
||||
m := readKustomizationFS(t, fSys)
|
||||
for _, k := range args {
|
||||
if patch.Exist(m.PatchesStrategicMerge, k) {
|
||||
t.Errorf("%s must be deleted", k)
|
||||
for _, p := range m.Patches {
|
||||
if p.Path == patchPath {
|
||||
t.Fatalf("%s must be deleted", patchPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemovePatchMultipleArgs(t *testing.T) {
|
||||
func TestRemovePatch2(t *testing.T) {
|
||||
fSys := makeKustomizationPatchFS()
|
||||
cmd := newCmdRemovePatch(fSys)
|
||||
args := []string{"patch1.yaml", "patch2.yaml"}
|
||||
err := cmd.RunE(cmd, args)
|
||||
args := []string{
|
||||
"--patch", patchFileContent,
|
||||
"--kind", kind,
|
||||
"--label-selector", labelSelector,
|
||||
}
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error %v", err)
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
|
||||
m := readKustomizationFS(t, fSys)
|
||||
for _, k := range args {
|
||||
if patch.Exist(m.PatchesStrategicMerge, k) {
|
||||
t.Errorf("%s must be deleted", k)
|
||||
for _, p := range m.Patches {
|
||||
if p.Patch == patchFileContent {
|
||||
t.Fatalf("%s must be deleted", patchFileContent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemovePatchGlob(t *testing.T) {
|
||||
fSys := makeKustomizationPatchFS()
|
||||
cmd := newCmdRemovePatch(fSys)
|
||||
args := []string{"patch*.yaml"}
|
||||
err := cmd.RunE(cmd, args)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error %v", err)
|
||||
}
|
||||
|
||||
m := readKustomizationFS(t, fSys)
|
||||
if len(m.PatchesStrategicMerge) != 0 {
|
||||
t.Errorf("all patch must be deleted")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemovePatchNotDefinedInKustomization(t *testing.T) {
|
||||
fSys := makeKustomizationPatchFS()
|
||||
cmd := newCmdRemovePatch(fSys)
|
||||
args := []string{"patch3.yaml"}
|
||||
err := cmd.RunE(cmd, args)
|
||||
args := []string{
|
||||
"--path", "patch3.yaml",
|
||||
"--kind", kind,
|
||||
"--group", group,
|
||||
"--version", version,
|
||||
"--name", name,
|
||||
"--namespace", namespace,
|
||||
"--annotation-selector", annotationSelector,
|
||||
"--label-selector", labelSelector,
|
||||
}
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error %v", err)
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
|
||||
m := readKustomizationFS(t, fSys)
|
||||
for _, k := range []string{"patch1.yaml", "patch2.yaml"} {
|
||||
if !patch.Exist(m.PatchesStrategicMerge, k) {
|
||||
t.Errorf("%s must exist", k)
|
||||
found := false
|
||||
for _, p := range m.Patches {
|
||||
if p.Path == k {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatalf("%s must exist", k)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -108,30 +149,45 @@ func TestRemovePatchNotDefinedInKustomization(t *testing.T) {
|
||||
func TestRemovePatchNotExist(t *testing.T) {
|
||||
fSys := makeKustomizationPatchFS()
|
||||
cmd := newCmdRemovePatch(fSys)
|
||||
args := []string{"patch4.yaml"}
|
||||
err := cmd.RunE(cmd, args)
|
||||
args := []string{
|
||||
"--path", "patch4.yaml",
|
||||
"--kind", kind,
|
||||
"--group", group,
|
||||
"--version", version,
|
||||
"--name", name,
|
||||
"--namespace", namespace,
|
||||
"--annotation-selector", annotationSelector,
|
||||
"--label-selector", labelSelector,
|
||||
}
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error %v", err)
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
|
||||
m := readKustomizationFS(t, fSys)
|
||||
for _, k := range []string{"patch1.yaml", "patch2.yaml"} {
|
||||
if !patch.Exist(m.PatchesStrategicMerge, k) {
|
||||
t.Errorf("%s must exist", k)
|
||||
found := false
|
||||
for _, p := range m.Patches {
|
||||
if p.Path == k {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatalf("%s must exist", k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemovePatchNoArgs(t *testing.T) {
|
||||
// if no flags specified, we should do nothing
|
||||
fSys := makeKustomizationPatchFS()
|
||||
cmd := newCmdRemovePatch(fSys)
|
||||
err := cmd.RunE(cmd, nil)
|
||||
err := cmd.Execute()
|
||||
|
||||
if err == nil {
|
||||
t.Errorf("expected an error")
|
||||
}
|
||||
if err.Error() != "must specify a patch file" {
|
||||
t.Errorf("incorrect error: %v", err.Error())
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,65 +5,49 @@ package remove
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"sigs.k8s.io/kustomize/api/filesys"
|
||||
testutils_test "sigs.k8s.io/kustomize/kustomize/v3/internal/commands/testutils"
|
||||
"sigs.k8s.io/kustomize/kustomize/v3/internal/commands/edit/remove_test"
|
||||
)
|
||||
|
||||
func TestRemoveResources(t *testing.T) {
|
||||
type given struct {
|
||||
resources []string
|
||||
removeArgs []string
|
||||
}
|
||||
type expected struct {
|
||||
resources []string
|
||||
deleted []string
|
||||
err error
|
||||
}
|
||||
testCases := []struct {
|
||||
description string
|
||||
given given
|
||||
expected expected
|
||||
}{
|
||||
testCases := []remove_test.Case{
|
||||
{
|
||||
description: "remove resource",
|
||||
given: given{
|
||||
resources: []string{
|
||||
Description: "remove resources",
|
||||
Given: remove_test.Given{
|
||||
Items: []string{
|
||||
"resource1.yaml",
|
||||
"resource2.yaml",
|
||||
"resource3.yaml",
|
||||
},
|
||||
removeArgs: []string{"resource1.yaml"},
|
||||
RemoveArgs: []string{"resource1.yaml"},
|
||||
},
|
||||
expected: expected{
|
||||
resources: []string{
|
||||
Expected: remove_test.Expected{
|
||||
Items: []string{
|
||||
"resource2.yaml",
|
||||
"resource3.yaml",
|
||||
},
|
||||
deleted: []string{
|
||||
Deleted: []string{
|
||||
"resource1.yaml",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "remove resources with pattern",
|
||||
given: given{
|
||||
resources: []string{
|
||||
Description: "remove resource with pattern",
|
||||
Given: remove_test.Given{
|
||||
Items: []string{
|
||||
"foo/resource1.yaml",
|
||||
"foo/resource2.yaml",
|
||||
"foo/resource3.yaml",
|
||||
"do/not/deleteme/please.yaml",
|
||||
},
|
||||
removeArgs: []string{"foo/resource*.yaml"},
|
||||
RemoveArgs: []string{"foo/resource*.yaml"},
|
||||
},
|
||||
expected: expected{
|
||||
resources: []string{
|
||||
Expected: remove_test.Expected{
|
||||
Items: []string{
|
||||
"do/not/deleteme/please.yaml",
|
||||
},
|
||||
deleted: []string{
|
||||
Deleted: []string{
|
||||
"foo/resource1.yaml",
|
||||
"foo/resource2.yaml",
|
||||
"foo/resource3.yaml",
|
||||
@@ -71,17 +55,17 @@ func TestRemoveResources(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "nothing found to remove",
|
||||
given: given{
|
||||
resources: []string{
|
||||
Description: "nothing found to remove",
|
||||
Given: remove_test.Given{
|
||||
Items: []string{
|
||||
"resource1.yaml",
|
||||
"resource2.yaml",
|
||||
"resource3.yaml",
|
||||
},
|
||||
removeArgs: []string{"foo"},
|
||||
RemoveArgs: []string{"foo"},
|
||||
},
|
||||
expected: expected{
|
||||
resources: []string{
|
||||
Expected: remove_test.Expected{
|
||||
Items: []string{
|
||||
"resource2.yaml",
|
||||
"resource3.yaml",
|
||||
"resource1.yaml",
|
||||
@@ -89,32 +73,32 @@ func TestRemoveResources(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "no arguments",
|
||||
given: given{},
|
||||
expected: expected{
|
||||
err: errors.New("must specify a resource file"),
|
||||
Description: "no arguments",
|
||||
Given: remove_test.Given{},
|
||||
Expected: remove_test.Expected{
|
||||
Err: errors.New("must specify a resource file"),
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "remove with multiple pattern arguments",
|
||||
given: given{
|
||||
resources: []string{
|
||||
Description: "remove with multiple pattern arguments",
|
||||
Given: remove_test.Given{
|
||||
Items: []string{
|
||||
"foo/foo.yaml",
|
||||
"bar/bar.yaml",
|
||||
"resource3.yaml",
|
||||
"do/not/deleteme/please.yaml",
|
||||
},
|
||||
removeArgs: []string{
|
||||
RemoveArgs: []string{
|
||||
"foo/*.*",
|
||||
"bar/*.*",
|
||||
"res*.yaml",
|
||||
},
|
||||
},
|
||||
expected: expected{
|
||||
resources: []string{
|
||||
Expected: remove_test.Expected{
|
||||
Items: []string{
|
||||
"do/not/deleteme/please.yaml",
|
||||
},
|
||||
deleted: []string{
|
||||
Deleted: []string{
|
||||
"foo/foo.yaml",
|
||||
"bar/bar.yaml",
|
||||
"resource3.yaml",
|
||||
@@ -123,40 +107,5 @@ func TestRemoveResources(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
fSys := filesys.MakeFsInMemory()
|
||||
testutils_test.WriteTestKustomizationWith(
|
||||
fSys,
|
||||
[]byte(fmt.Sprintf(
|
||||
"resources:\n - %s", strings.Join(tc.given.resources, "\n - "))))
|
||||
cmd := newCmdRemoveResource(fSys)
|
||||
err := cmd.RunE(cmd, tc.given.removeArgs)
|
||||
if err != nil && tc.expected.err == nil {
|
||||
|
||||
t.Errorf("unexpected cmd error: %v", err)
|
||||
} else if tc.expected.err != nil {
|
||||
if err.Error() != tc.expected.err.Error() {
|
||||
t.Errorf("expected error did not occurred. Expected: %v. Actual: %v", tc.expected.err, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
content, err := testutils_test.ReadTestKustomization(fSys)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected read error: %v", err)
|
||||
}
|
||||
|
||||
for _, resourceFileName := range tc.expected.resources {
|
||||
if !strings.Contains(string(content), resourceFileName) {
|
||||
t.Errorf("expected resource not found in kustomization file.\nResource: %s\nKustomization file:\n%s", resourceFileName, content)
|
||||
}
|
||||
}
|
||||
for _, resourceFileName := range tc.expected.deleted {
|
||||
if strings.Contains(string(content), resourceFileName) {
|
||||
t.Errorf("expected deleted resource found in kustomization file. Resource: %s\nKustomization file:\n%s", resourceFileName, content)
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
remove_test.ExecuteTestCases(t, testCases, "resources", newCmdRemoveResource)
|
||||
}
|
||||
|
||||
83
kustomize/internal/commands/edit/remove/removetransformer.go
Normal file
83
kustomize/internal/commands/edit/remove/removetransformer.go
Normal file
@@ -0,0 +1,83 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package remove
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/api/filesys"
|
||||
"sigs.k8s.io/kustomize/api/konfig"
|
||||
"sigs.k8s.io/kustomize/kustomize/v3/internal/commands/kustfile"
|
||||
)
|
||||
|
||||
type removeTransformerOptions struct {
|
||||
transformerFilePaths []string
|
||||
}
|
||||
|
||||
// newCmdRemoveTransformer remove the name of a file containing a transformer to the kustomization file.
|
||||
func newCmdRemoveTransformer(fSys filesys.FileSystem) *cobra.Command {
|
||||
var o removeTransformerOptions
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "transformer",
|
||||
Short: "Removes one or more transformers from " +
|
||||
konfig.DefaultKustomizationFileName(),
|
||||
Example: `
|
||||
remove transformer my-transformer.yml
|
||||
remove transformer transformer1.yml transformer2.yml transformer3.yml
|
||||
remove transformer transformers/*.yml
|
||||
`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
err := o.Validate(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return o.RunRemoveTransformer(fSys)
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Validate validates removeTransformer command.
|
||||
func (o *removeTransformerOptions) Validate(args []string) error {
|
||||
if len(args) == 0 {
|
||||
return errors.New("must specify a transformer file")
|
||||
}
|
||||
o.transformerFilePaths = args
|
||||
return nil
|
||||
}
|
||||
|
||||
// RunRemoveTransformer runs Transformer command (do real work).
|
||||
func (o *removeTransformerOptions) RunRemoveTransformer(fSys filesys.FileSystem) error {
|
||||
mf, err := kustfile.NewKustomizationFile(fSys)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m, err := mf.Read()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
transformers, err := globPatterns(m.Transformers, o.transformerFilePaths)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(transformers) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
newTransformers := make([]string, 0, len(m.Transformers))
|
||||
for _, transformer := range m.Transformers {
|
||||
if kustfile.StringInSlice(transformer, transformers) {
|
||||
continue
|
||||
}
|
||||
newTransformers = append(newTransformers, transformer)
|
||||
}
|
||||
|
||||
m.Transformers = newTransformers
|
||||
return mf.Write(m)
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package remove
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"sigs.k8s.io/kustomize/kustomize/v3/internal/commands/edit/remove_test"
|
||||
)
|
||||
|
||||
func TestRemoveTransformer(t *testing.T) {
|
||||
testCases := []remove_test.Case{
|
||||
{
|
||||
Description: "remove transformers",
|
||||
Given: remove_test.Given{
|
||||
Items: []string{
|
||||
"transformer1.yaml",
|
||||
"transformer2.yaml",
|
||||
"transformer3.yaml",
|
||||
},
|
||||
RemoveArgs: []string{"transformer1.yaml"},
|
||||
},
|
||||
Expected: remove_test.Expected{
|
||||
Items: []string{
|
||||
"transformer2.yaml",
|
||||
"transformer3.yaml",
|
||||
},
|
||||
Deleted: []string{
|
||||
"transformer1.yaml",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Description: "remove transformer with pattern",
|
||||
Given: remove_test.Given{
|
||||
Items: []string{
|
||||
"foo/transformer1.yaml",
|
||||
"foo/transformer2.yaml",
|
||||
"foo/transformer3.yaml",
|
||||
"do/not/deleteme/please.yaml",
|
||||
},
|
||||
RemoveArgs: []string{"foo/transformer*.yaml"},
|
||||
},
|
||||
Expected: remove_test.Expected{
|
||||
Items: []string{
|
||||
"do/not/deleteme/please.yaml",
|
||||
},
|
||||
Deleted: []string{
|
||||
"foo/transformer1.yaml",
|
||||
"foo/transformer2.yaml",
|
||||
"foo/transformer3.yaml",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Description: "nothing found to remove",
|
||||
Given: remove_test.Given{
|
||||
Items: []string{
|
||||
"transformer1.yaml",
|
||||
"transformer2.yaml",
|
||||
"transformer3.yaml",
|
||||
},
|
||||
RemoveArgs: []string{"foo"},
|
||||
},
|
||||
Expected: remove_test.Expected{
|
||||
Items: []string{
|
||||
"transformer2.yaml",
|
||||
"transformer3.yaml",
|
||||
"transformer1.yaml",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Description: "no arguments",
|
||||
Given: remove_test.Given{},
|
||||
Expected: remove_test.Expected{
|
||||
Err: errors.New("must specify a transformer file"),
|
||||
},
|
||||
},
|
||||
{
|
||||
Description: "remove with multiple pattern arguments",
|
||||
Given: remove_test.Given{
|
||||
Items: []string{
|
||||
"foo/foo.yaml",
|
||||
"bar/bar.yaml",
|
||||
"transformer3.yaml",
|
||||
"do/not/deleteme/please.yaml",
|
||||
},
|
||||
RemoveArgs: []string{
|
||||
"foo/*.*",
|
||||
"bar/*.*",
|
||||
"tra*.yaml",
|
||||
},
|
||||
},
|
||||
Expected: remove_test.Expected{
|
||||
Items: []string{
|
||||
"do/not/deleteme/please.yaml",
|
||||
},
|
||||
Deleted: []string{
|
||||
"foo/foo.yaml",
|
||||
"bar/bar.yaml",
|
||||
"transformer3.yaml",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
remove_test.ExecuteTestCases(t, testCases, "transformers", newCmdRemoveTransformer)
|
||||
}
|
||||
85
kustomize/internal/commands/edit/remove_test/removetest.go
Normal file
85
kustomize/internal/commands/edit/remove_test/removetest.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package remove_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/api/filesys"
|
||||
testutils_test "sigs.k8s.io/kustomize/kustomize/v3/internal/commands/testutils"
|
||||
)
|
||||
|
||||
// Given represents the provided inputs for the test case.
|
||||
type Given struct {
|
||||
// Items is the given input items.
|
||||
Items []string
|
||||
// RemoveArgs are the arguments to pass to the remove command.
|
||||
RemoveArgs []string
|
||||
}
|
||||
|
||||
// Expected represents the expected outputs of the test case.
|
||||
type Expected struct {
|
||||
// Expected is the collection of expected output items.
|
||||
Items []string
|
||||
// Deleted is the collection of expected Deleted items (if any).
|
||||
Deleted []string
|
||||
// Err represents the error that is expected in the output (if any).
|
||||
Err error
|
||||
}
|
||||
|
||||
// Case represents a test case to execute.
|
||||
type Case struct {
|
||||
// Description is the description of the test case.
|
||||
Description string
|
||||
// Given is the provided inputs for the test case.
|
||||
Given Given
|
||||
// Expected is the expected outputs for the test case.
|
||||
Expected Expected
|
||||
}
|
||||
|
||||
// ExecuteTestCases executes the provided test cases against the specified command
|
||||
// for a particular collection (e.g. ) tests a command defined by the provided
|
||||
// collection Name (e.g. transformers or resources) and newRemoveCmdToTest function.
|
||||
func ExecuteTestCases(t *testing.T, testCases []Case, collectionName string,
|
||||
newRemoveCmdToTest func(filesys.FileSystem) *cobra.Command) {
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.Description, func(t *testing.T) {
|
||||
fSys := filesys.MakeFsInMemory()
|
||||
testutils_test.WriteTestKustomizationWith(
|
||||
fSys,
|
||||
[]byte(fmt.Sprintf("%s:\n - %s",
|
||||
collectionName,
|
||||
strings.Join(tc.Given.Items, "\n - "))))
|
||||
cmd := newRemoveCmdToTest(fSys)
|
||||
err := cmd.RunE(cmd, tc.Given.RemoveArgs)
|
||||
if err != nil && tc.Expected.Err == nil {
|
||||
t.Errorf("unexpected cmd error: %v", err)
|
||||
} else if tc.Expected.Err != nil {
|
||||
if err.Error() != tc.Expected.Err.Error() {
|
||||
t.Errorf("expected error did not occurred. Expected: %v. Actual: %v",
|
||||
tc.Expected.Err,
|
||||
err)
|
||||
}
|
||||
return
|
||||
}
|
||||
content, err := testutils_test.ReadTestKustomization(fSys)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected read error: %v", err)
|
||||
}
|
||||
|
||||
for _, itemFileName := range tc.Expected.Items {
|
||||
if !strings.Contains(string(content), itemFileName) {
|
||||
t.Errorf("expected item not found in kustomization file.\nItem: %s\nKustomization file:\n%s",
|
||||
itemFileName, content)
|
||||
}
|
||||
}
|
||||
for _, itemFileName := range tc.Expected.Deleted {
|
||||
if strings.Contains(string(content), itemFileName) {
|
||||
t.Errorf("expected deleted item found in kustomization file. Item: %s\nKustomization file:\n%s",
|
||||
itemFileName, content)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
28
kustomize/internal/commands/openapi/info/info.go
Normal file
28
kustomize/internal/commands/openapi/info/info.go
Normal file
@@ -0,0 +1,28 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package info
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/kyaml/openapi/kubernetesapi"
|
||||
)
|
||||
|
||||
// NewCmdInfo makes a new info command.
|
||||
func NewCmdInfo(w io.Writer) *cobra.Command {
|
||||
|
||||
infoCmd := cobra.Command{
|
||||
Use: "info",
|
||||
Short: "Prints the `info` field from the kubernetes OpenAPI data",
|
||||
Example: `kustomize openapi info`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Fprintln(w, kubernetesapi.Info)
|
||||
},
|
||||
Hidden: true,
|
||||
}
|
||||
|
||||
return &infoCmd
|
||||
}
|
||||
28
kustomize/internal/commands/openapi/openapi.go
Normal file
28
kustomize/internal/commands/openapi/openapi.go
Normal file
@@ -0,0 +1,28 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package openapi
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/kustomize/cmd/config/configcobra"
|
||||
"sigs.k8s.io/kustomize/kustomize/v3/internal/commands/openapi/info"
|
||||
)
|
||||
|
||||
// NewCmdOpenAPI makes a new openapi command.
|
||||
func NewCmdOpenAPI(w io.Writer) *cobra.Command {
|
||||
|
||||
openApiCmd := &cobra.Command{
|
||||
Use: "openapi",
|
||||
Short: "Commands for interacting with the OpenAPI data",
|
||||
Example: `kustomize openapi info`,
|
||||
Hidden: true,
|
||||
}
|
||||
|
||||
openApiCmd.AddCommand(info.NewCmdInfo(w))
|
||||
configcobra.AddCommands(openApiCmd, "openapi")
|
||||
|
||||
return openApiCmd
|
||||
}
|
||||
@@ -7,7 +7,6 @@ package main
|
||||
import (
|
||||
"os"
|
||||
|
||||
"sigs.k8s.io/kustomize/cmd/config/complete"
|
||||
"sigs.k8s.io/kustomize/kustomize/v3/internal/commands"
|
||||
|
||||
// initialize auth
|
||||
@@ -17,10 +16,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
cmd := commands.NewDefaultCommand()
|
||||
complete.Complete(cmd).Complete("kustomize")
|
||||
|
||||
if err := cmd.Execute(); err != nil {
|
||||
if err := commands.NewDefaultCommand().Execute(); err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
os.Exit(0)
|
||||
|
||||
@@ -2,10 +2,9 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
MYGOBIN := $(shell go env GOPATH)/bin
|
||||
GOPATH := $(shell go env GOPATH)
|
||||
export PATH := $(MYGOBIN):$(PATH)
|
||||
|
||||
.PHONY: generate license fix vet fmt test lint tidy openapi schema
|
||||
.PHONY: generate license fix vet fmt test lint tidy
|
||||
all: generate license fix vet fmt test lint tidy
|
||||
|
||||
fix:
|
||||
@@ -15,51 +14,22 @@ fmt:
|
||||
go fmt ./...
|
||||
|
||||
generate:
|
||||
(which $(GOPATH)/bin/stringer || go get golang.org/x/tools/cmd/stringer)
|
||||
(which $(MYGOBIN)/stringer || go get golang.org/x/tools/cmd/stringer)
|
||||
go generate ./...
|
||||
|
||||
license:
|
||||
(which $(GOPATH)/bin/addlicense || go get github.com/google/addlicense)
|
||||
$(GOPATH)/bin/addlicense -y 2019 -c "The Kubernetes Authors." -f LICENSE_TEMPLATE .
|
||||
(which $(MYGOBIN)/addlicense || go get github.com/google/addlicense)
|
||||
$(MYGOBIN)/addlicense -y 2019 -c "The Kubernetes Authors." -f LICENSE_TEMPLATE .
|
||||
|
||||
tidy:
|
||||
go mod tidy
|
||||
|
||||
lint:
|
||||
(which $(GOPATH)/bin/golangci-lint || go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.19.1)
|
||||
$(GOPATH)/bin/golangci-lint run ./...
|
||||
(which $(MYGOBIN)/golangci-lint || go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.19.1)
|
||||
$(MYGOBIN)/golangci-lint run ./...
|
||||
|
||||
test:
|
||||
go test -cover ./...
|
||||
|
||||
vet:
|
||||
go vet ./...
|
||||
|
||||
openapi:
|
||||
(which $(GOPATH)/bin/go-bindata || go get -u github.com/go-bindata/go-bindata/...)
|
||||
$(GOPATH)/bin/go-bindata --pkg kubernetesapi -o openapi/kubernetesapi/swagger.go openapi/kubernetesapi/swagger.json
|
||||
$(GOPATH)/bin/go-bindata --pkg kustomizationapi -o openapi/kustomizationapi/swagger.go openapi/kustomizationapi/swagger.json
|
||||
|
||||
$(MYGOBIN)/kind:
|
||||
( \
|
||||
set -e; \
|
||||
d=$(shell mktemp -d); cd $$d; \
|
||||
wget -O ./kind https://github.com/kubernetes-sigs/kind/releases/download/v0.7.0/kind-$(shell uname)-amd64; \
|
||||
chmod +x ./kind; \
|
||||
mv ./kind $(MYGOBIN); \
|
||||
rm -rf $$d; \
|
||||
)
|
||||
|
||||
$(MYGOBIN)/kpt:
|
||||
../hack/install_kpt.sh 0.34.0 $(MYGOBIN)
|
||||
|
||||
API_VERSION="v1.19.1"
|
||||
schema: $(MYGOBIN)/kind $(MYGOBIN)/kpt
|
||||
cp $(HOME)/.kube/config /tmp/kubeconfig.txt | true
|
||||
$(MYGOBIN)/kind create cluster --image kindest/node:$(API_VERSION) --name=getopenapidata
|
||||
$(MYGOBIN)/kpt live fetch-k8s-schema --pretty-print > /tmp/new_swagger.json
|
||||
$(MYGOBIN)/kind delete cluster --name=getopenapidata
|
||||
cp /tmp/kubeconfig.txt $(HOME)/.kube/config | true
|
||||
cp /tmp/new_swagger.json openapi/kubernetesapi/swagger.json
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
)
|
||||
|
||||
// EnabkeAlphaCommmandsEnvName is the environment variable used to enable Alpha kustomize commands.
|
||||
//If set to "true" alpha commands will be enabled.
|
||||
// If set to "true" alpha commands will be enabled.
|
||||
const EnableAlphaCommmandsEnvName = "KUSTOMIZE_ENABLE_ALPHA_COMMANDS"
|
||||
|
||||
// GetAlphaEnabled returns true if alpha commands should be enabled.
|
||||
|
||||
@@ -64,7 +64,7 @@ run(ctx.resource_list["items"])
|
||||
Filters: []kio.Filter{fltr},
|
||||
Outputs: []kio.Writer{&kio.ByteWriter{Writer: output}}}.Execute()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
fmt.Println(output.String())
|
||||
@@ -131,7 +131,7 @@ spec:
|
||||
value: "hello world"
|
||||
`)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
// fltr transforms the input using a starlark program
|
||||
@@ -156,7 +156,7 @@ run(ctx.resource_list["items"], ctx.resource_list["functionConfig"]["spec"]["val
|
||||
Filters: []kio.Filter{fltr},
|
||||
Outputs: []kio.Writer{&kio.ByteWriter{Writer: output}}}.Execute()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
fmt.Println(output.String())
|
||||
@@ -197,7 +197,7 @@ func ExampleFilter_Filter_file() {
|
||||
// setup the configuration
|
||||
d, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
log.Println(err)
|
||||
}
|
||||
defer os.RemoveAll(d)
|
||||
|
||||
@@ -214,7 +214,7 @@ spec:
|
||||
image: nginx:1.8.1 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image-1"}
|
||||
`), 0600)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(filepath.Join(d, "deploy2.yaml"), []byte(`
|
||||
@@ -230,7 +230,7 @@ spec:
|
||||
image: nginx:1.7.9 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image-2"}
|
||||
`), 0600)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(filepath.Join(d, "annotate.star"), []byte(`
|
||||
@@ -241,7 +241,7 @@ def run(items):
|
||||
run(ctx.resource_list["items"])
|
||||
`), 0600)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
fltr := &starlark.Filter{
|
||||
@@ -261,7 +261,7 @@ run(ctx.resource_list["items"])
|
||||
ClearAnnotations: []string{"config.kubernetes.io/path"},
|
||||
}}}.Execute()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
fmt.Println(output.String())
|
||||
|
||||
@@ -117,7 +117,7 @@ func (r *ByteReader) Read() ([]*yaml.RNode, error) {
|
||||
}
|
||||
|
||||
// replace the ending \r\n (line ending used in windows) with \n and then separate by \n---\n
|
||||
values := strings.Split(strings.Replace(input.String(), "\r\n", "\n", -1), "\n---\n")
|
||||
values := strings.Split(strings.ReplaceAll(input.String(), "\r\n", "\n"), "\n---\n")
|
||||
|
||||
index := 0
|
||||
for i := range values {
|
||||
|
||||
@@ -170,9 +170,9 @@ func (f *FileSetter) Filter(input []*yaml.RNode) ([]*yaml.RNode, error) {
|
||||
return nil, err
|
||||
}
|
||||
file := f.FilenamePattern
|
||||
file = strings.Replace(file, string(KindFmt), strings.ToLower(m.Kind), -1)
|
||||
file = strings.Replace(file, string(NameFmt), strings.ToLower(m.Name), -1)
|
||||
file = strings.Replace(file, string(NamespaceFmt), strings.ToLower(m.Namespace), -1)
|
||||
file = strings.ReplaceAll(file, string(KindFmt), strings.ToLower(m.Kind))
|
||||
file = strings.ReplaceAll(file, string(NameFmt), strings.ToLower(m.Name))
|
||||
file = strings.ReplaceAll(file, string(NamespaceFmt), strings.ToLower(m.Namespace))
|
||||
|
||||
if _, found := m.Annotations[kioutil.PathAnnotation]; !found || f.Override {
|
||||
if _, err := input[i].Pipe(yaml.SetAnnotation(kioutil.PathAnnotation, file)); err != nil {
|
||||
|
||||
@@ -68,7 +68,7 @@ func (f GrepFilter) Filter(input []*yaml.RNode) ([]*yaml.RNode, error) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
str = strings.TrimSpace(strings.Replace(str, `"`, "", -1))
|
||||
str = strings.TrimSpace(strings.ReplaceAll(str, `"`, ""))
|
||||
} else {
|
||||
// if not regexp, then it needs to parse into a quantity and comments will
|
||||
// break that
|
||||
|
||||
@@ -75,6 +75,16 @@ type Pipeline struct {
|
||||
|
||||
// Outputs are where the transformed Resource Configuration is written.
|
||||
Outputs []Writer `yaml:"outputs,omitempty"`
|
||||
|
||||
// ContinueOnEmptyResult configures what happens when a filter in the pipeline
|
||||
// returns an empty result.
|
||||
// If it is false (default), subsequent filters will be skipped and the result
|
||||
// will be returned immediately. This is useful as an optimization when you
|
||||
// know that subsequent filters will not alter the empty result.
|
||||
// If it is true, the empty result will be provided as input to the next
|
||||
// filter in the list. This is useful when subsequent functions in the
|
||||
// pipeline may generate new resources.
|
||||
ContinueOnEmptyResult bool `yaml:"continueOnEmptyResult,omitempty"`
|
||||
}
|
||||
|
||||
// Execute executes each step in the sequence, returning immediately after encountering
|
||||
@@ -111,7 +121,7 @@ func (p Pipeline) ExecuteWithCallback(callback PipelineExecuteCallbackFunc) erro
|
||||
// TODO (issue 2872): This len(result) == 0 should be removed and empty result list should be
|
||||
// handled by outputs. However currently some writer like LocalPackageReadWriter
|
||||
// will clear the output directory and which will cause unpredictable results
|
||||
if len(result) == 0 || err != nil {
|
||||
if len(result) == 0 && !p.ContinueOnEmptyResult || err != nil {
|
||||
return errors.Wrap(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,3 +149,41 @@ items:
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
func TestContinueOnEmptyBehavior(t *testing.T) {
|
||||
cases := map[string]struct {
|
||||
continueOnEmptyResult bool
|
||||
expected string
|
||||
}{
|
||||
"quit on empty": {continueOnEmptyResult: false, expected: ""},
|
||||
"continue on empty": {continueOnEmptyResult: true, expected: "foo: bar"},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
actual := &bytes.Buffer{}
|
||||
output := ByteWriter{Writer: actual}
|
||||
|
||||
generatorFunc := FilterFunc(func(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
|
||||
nodes = append(nodes, yaml.NewMapRNode(&map[string]string{
|
||||
"foo": "bar",
|
||||
}))
|
||||
return nodes, nil
|
||||
})
|
||||
emptyFunc := FilterFunc(func(nodes []*yaml.RNode) ([]*yaml.RNode, error) { return nodes, nil })
|
||||
|
||||
p := Pipeline{
|
||||
Outputs: []Writer{output},
|
||||
Filters: []Filter{emptyFunc, generatorFunc},
|
||||
ContinueOnEmptyResult: tc.continueOnEmptyResult,
|
||||
}
|
||||
|
||||
err := p.Execute()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !assert.Equal(t,
|
||||
tc.expected, strings.TrimSpace(actual.String())) {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ package kio_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -69,7 +68,7 @@ spec:
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
if !assert.Equal(t, fmt.Sprintf(`
|
||||
if !assert.Equal(t, `
|
||||
├── bar-package
|
||||
│ └── [f2.yaml] Deployment bar
|
||||
└── foo-package
|
||||
@@ -77,7 +76,7 @@ spec:
|
||||
├── [f1.yaml] Service default/foo
|
||||
└── 3
|
||||
└── [f3.yaml] Deployment default/foo
|
||||
`), out.String()) {
|
||||
`, out.String()) {
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
62
kyaml/openapi/Makefile
Normal file
62
kyaml/openapi/Makefile
Normal file
@@ -0,0 +1,62 @@
|
||||
# Copyright 2020 The Kubernetes Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
MYGOBIN := $(shell go env GOPATH)/bin
|
||||
|
||||
.PHONY: all
|
||||
all: \
|
||||
kustomizationapi/swagger.go \
|
||||
kubernetesapi/swagger.go \
|
||||
kubernetesapi/openapiinfo.go
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm kustomizationapi/swagger.go
|
||||
rm kubernetesapi/swagger.go
|
||||
rm kubernetesapi/openapiinfo.go
|
||||
|
||||
# To get swagger.json, we need a cluster at the correct version,
|
||||
# so think twice before deleting.
|
||||
.PHONY: nuke
|
||||
nuke: clean
|
||||
rm kubernetesapi/swagger.json
|
||||
|
||||
$(MYGOBIN)/go-bindata:
|
||||
go install github.com/go-bindata/go-bindata/v3/go-bindata
|
||||
|
||||
$(MYGOBIN)/kind:
|
||||
( \
|
||||
set -e; \
|
||||
d=$(shell mktemp -d); cd $$d; \
|
||||
wget -O ./kind https://github.com/kubernetes-sigs/kind/releases/download/v0.7.0/kind-$(shell uname)-amd64; \
|
||||
chmod +x ./kind; \
|
||||
mv ./kind $(MYGOBIN); \
|
||||
rm -rf $$d; \
|
||||
)
|
||||
|
||||
$(MYGOBIN)/kpt:
|
||||
../../hack/install_kpt.sh 0.34.0 $(MYGOBIN)
|
||||
|
||||
kubernetesapi/swagger.go: $(MYGOBIN)/go-bindata kubernetesapi/swagger.json
|
||||
$(MYGOBIN)/go-bindata \
|
||||
--pkg kubernetesapi \
|
||||
-o kubernetesapi/swagger.go \
|
||||
kubernetesapi/swagger.json
|
||||
|
||||
kustomizationapi/swagger.go: $(MYGOBIN)/go-bindata kustomizationapi/swagger.json
|
||||
$(MYGOBIN)/go-bindata \
|
||||
--pkg kustomizationapi \
|
||||
-o kustomizationapi/swagger.go \
|
||||
kustomizationapi/swagger.json
|
||||
|
||||
kubernetesapi/openapiinfo.go: kubernetesapi/swagger.json
|
||||
./makeOpenApiInfoDotGo.sh kubernetesapi/swagger.json
|
||||
|
||||
API_VERSION="v1.19.1"
|
||||
kubernetesapi/swagger.json: $(MYGOBIN)/kind $(MYGOBIN)/kpt
|
||||
cp $(HOME)/.kube/config /tmp/kubeconfig.txt | true
|
||||
$(MYGOBIN)/kind create cluster --image kindest/node:$(API_VERSION) --name=getopenapidata
|
||||
$(MYGOBIN)/kpt live fetch-k8s-schema --pretty-print > /tmp/new_swagger.json
|
||||
$(MYGOBIN)/kind delete cluster --name=getopenapidata
|
||||
cp /tmp/kubeconfig.txt $(HOME)/.kube/config | true
|
||||
cp /tmp/new_swagger.json kubernetesapi/swagger.json
|
||||
@@ -1,36 +1,42 @@
|
||||
# Sampling New OpenAPI Data
|
||||
|
||||
[kyaml]: ../
|
||||
[OpenAPI schema]: ./kubernetesapi/swagger.json
|
||||
[home]: ../../
|
||||
|
||||
This document describes how to fetch OpenAPI data from
|
||||
a particular kubernetes version number.
|
||||
a particular kubernetes version number.
|
||||
|
||||
### Fetching the Schema
|
||||
|
||||
In this directory, fetch the openapi schema for the kubernetes api:
|
||||
|
||||
### Fetching the Schema
|
||||
In the [kyaml] directory, fetch the schema
|
||||
```
|
||||
make schema
|
||||
make nuke
|
||||
make kubernetesapi/swagger.json
|
||||
```
|
||||
|
||||
You can specify a specific version with the "API_VERSION"
|
||||
You can specify a specific version with the "API_VERSION"
|
||||
parameter. The default version is v1.19.1. Here is an
|
||||
example for fetching the data for v1.14.1.
|
||||
|
||||
```
|
||||
make schema API_VERSION=v1.14.1
|
||||
make kubernetesapi/swagger.json API_VERSION=v1.14.1
|
||||
```
|
||||
|
||||
This will update the [OpenAPI schema].
|
||||
This will update the [OpenAPI schema].
|
||||
|
||||
### Generating Swagger.go
|
||||
In the [kyaml] directory, generate the swagger.go files.
|
||||
|
||||
In this directory, generate the swagger.go files.
|
||||
|
||||
```
|
||||
make openapi
|
||||
make
|
||||
```
|
||||
|
||||
### Run all tests
|
||||
In the [home] directory, run the tests.
|
||||
|
||||
At the top of the repository, run the tests.
|
||||
|
||||
```
|
||||
make prow-presubmit-check >& /tmp/k.txt; echo $?
|
||||
# The exit code should be zero; if not examine /tmp/k.txt
|
||||
```
|
||||
```
|
||||
|
||||
8
kyaml/openapi/kubernetesapi/openapiinfo.go
Normal file
8
kyaml/openapi/kubernetesapi/openapiinfo.go
Normal file
@@ -0,0 +1,8 @@
|
||||
// Copyright 2020 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Code generated by ./makeOpenApiInfoDotGo.sh; DO NOT EDIT.
|
||||
|
||||
package kubernetesapi
|
||||
|
||||
const Info = "{title:Kubernetes,version:v1.17.0}"
|
||||
File diff suppressed because one or more lines are too long
@@ -3,7 +3,7 @@
|
||||
|
||||
// Code generated for package kustomizationapi by go-bindata DO NOT EDIT. (@generated)
|
||||
// sources:
|
||||
// openapi/kustomizationapi/swagger.json
|
||||
// kustomizationapi/swagger.json
|
||||
package kustomizationapi
|
||||
|
||||
import (
|
||||
@@ -80,22 +80,22 @@ func (fi bindataFileInfo) Sys() interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
var _openapiKustomizationapiSwaggerJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xdc\x54\xb1\x6e\xdb\x30\x10\xdd\xfd\x15\x04\xdb\xd1\x52\xe0\xad\xf0\x56\x74\xe8\x10\x04\x08\x90\x6e\x45\x86\xb3\x7c\x52\xae\x92\x49\xf6\x78\x12\xea\x16\xfe\xf7\x42\xac\xa5\x88\xb6\xd4\xb4\x46\x1c\x24\x1e\x0c\x18\xd4\xdd\x7b\xbc\x7b\x8f\xef\xd7\x4c\x29\xbd\xc6\x9c\x0c\x09\x59\xe3\xf5\x52\xb5\x47\x4a\x69\xb2\x69\xf9\xc1\xa7\xe0\x28\x05\xe7\x7c\xda\x2c\xd2\x4f\xd6\xe4\x54\xdc\x80\xfb\xc8\xc5\x63\xa5\x52\xda\xb1\x75\xc8\x42\x38\x3c\x55\x4a\x7f\x46\x83\x0c\x62\xf9\xa0\x21\x7c\x7c\xcf\x98\xeb\xa5\xd2\xef\xae\x06\xfc\x57\x23\xb4\x31\x4a\x0f\xb1\xdb\xff\xdb\xcd\xbb\x6b\xc0\x7a\x1d\x50\xa0\xba\x1d\x5e\x28\x87\xca\x63\x5f\x24\x5b\x87\x2d\xad\x5d\x7d\xc3\x4c\x74\x7f\xfe\x23\x29\xeb\x15\xb2\x41\x41\x9f\x14\x6c\x6b\x97\x34\xc8\x9e\xac\x49\x4a\x32\x6b\xbd\x54\x5f\x7b\xea\x68\x8e\x50\xdb\x22\x96\xb5\x17\xbb\xa1\x9f\x98\x66\x61\x51\x61\x10\xb2\x3d\x45\xa8\xde\x63\xe9\x78\x97\x51\xc9\x9e\xb6\xad\x6a\x16\x2b\x14\x58\x1c\x0f\x7d\x3f\x1b\x8c\x3e\xa6\xd5\x1d\x66\x8c\xf2\x3a\x84\x7a\x9c\xae\xdb\x7e\x84\xdf\x29\xe2\x85\xc9\x14\x97\x22\xf0\x40\x80\xe7\x57\x77\x4a\xaf\x49\x81\x0d\x6c\xd0\x3b\xc8\xfe\x7d\xf9\xf3\xb8\xf9\x94\xbe\x15\x3e\x40\x43\x96\x4f\xe9\xbd\x6e\x6e\x81\xf8\xce\xd6\x9c\xe1\xe9\x8e\x8c\x51\x2e\xc4\x59\xb1\xf8\xcf\x6f\xae\xeb\xfd\x65\x40\xfe\x40\xf5\xe6\x62\xfc\x5e\x13\x63\x3c\x90\xfe\xb2\x75\x78\x83\x02\x1d\xd3\xfd\xfc\x29\x33\x66\x5d\xf6\xf5\x93\x1c\x0a\x4c\x82\x9b\x43\xd5\xff\x47\xf7\x38\x5d\x07\x20\xbb\xf9\x98\x11\x81\x19\xb6\xf1\x26\x23\x4d\x1d\x48\xf6\x90\x6c\x90\x0b\x4c\x4a\xdc\xb6\x2d\xe1\x4d\x3c\xd5\xe1\x85\x41\xb0\x08\x0d\xa1\x7b\xdc\xeb\x3e\x44\xc5\xd9\x96\x31\x48\xa2\x57\xb9\x89\x37\xfd\x18\xe3\xc7\x72\x86\xc7\x38\x91\x83\x93\x8f\xab\x22\x41\x86\xea\x28\x33\x27\x5c\x34\x95\xc5\x7f\x37\xc8\xa8\x8d\x73\xaa\x8e\xa3\xfa\xfc\xb4\x68\x9a\x97\x62\x7d\xdb\x4e\x8d\x9c\x74\xaa\x53\x67\xed\x6f\xf7\x3b\x00\x00\xff\xff\xfe\x97\xce\xec\x37\x0c\x00\x00")
|
||||
var _kustomizationapiSwaggerJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xdc\x54\xb1\x6e\xdb\x30\x10\xdd\xfd\x15\x04\xdb\xd1\x52\xe0\xad\xf0\x56\x74\xe8\x10\x04\x08\x90\x6e\x45\x86\xb3\x7c\x52\xae\x92\x49\xf6\x78\x12\xea\x16\xfe\xf7\x42\xac\xa5\x88\xb6\xd4\xb4\x46\x1c\x24\x1e\x0c\x18\xd4\xdd\x7b\xbc\x7b\x8f\xef\xd7\x4c\x29\xbd\xc6\x9c\x0c\x09\x59\xe3\xf5\x52\xb5\x47\x4a\x69\xb2\x69\xf9\xc1\xa7\xe0\x28\x05\xe7\x7c\xda\x2c\xd2\x4f\xd6\xe4\x54\xdc\x80\xfb\xc8\xc5\x63\xa5\x52\xda\xb1\x75\xc8\x42\x38\x3c\x55\x4a\x7f\x46\x83\x0c\x62\xf9\xa0\x21\x7c\x7c\xcf\x98\xeb\xa5\xd2\xef\xae\x06\xfc\x57\x23\xb4\x31\x4a\x0f\xb1\xdb\xff\xdb\xcd\xbb\x6b\xc0\x7a\x1d\x50\xa0\xba\x1d\x5e\x28\x87\xca\x63\x5f\x24\x5b\x87\x2d\xad\x5d\x7d\xc3\x4c\x74\x7f\xfe\x23\x29\xeb\x15\xb2\x41\x41\x9f\x14\x6c\x6b\x97\x34\xc8\x9e\xac\x49\x4a\x32\x6b\xbd\x54\x5f\x7b\xea\x68\x8e\x50\xdb\x22\x96\xb5\x17\xbb\xa1\x9f\x98\x66\x61\x51\x61\x10\xb2\x3d\x45\xa8\xde\x63\xe9\x78\x97\x51\xc9\x9e\xb6\xad\x6a\x16\x2b\x14\x58\x1c\x0f\x7d\x3f\x1b\x8c\x3e\xa6\xd5\x1d\x66\x8c\xf2\x3a\x84\x7a\x9c\xae\xdb\x7e\x84\xdf\x29\xe2\x85\xc9\x14\x97\x22\xf0\x40\x80\xe7\x57\x77\x4a\xaf\x49\x81\x0d\x6c\xd0\x3b\xc8\xfe\x7d\xf9\xf3\xb8\xf9\x94\xbe\x15\x3e\x40\x43\x96\x4f\xe9\xbd\x6e\x6e\x81\xf8\xce\xd6\x9c\xe1\xe9\x8e\x8c\x51\x2e\xc4\x59\xb1\xf8\xcf\x6f\xae\xeb\xfd\x65\x40\xfe\x40\xf5\xe6\x62\xfc\x5e\x13\x63\x3c\x90\xfe\xb2\x75\x78\x83\x02\x1d\xd3\xfd\xfc\x29\x33\x66\x5d\xf6\xf5\x93\x1c\x0a\x4c\x82\x9b\x43\xd5\xff\x47\xf7\x38\x5d\x07\x20\xbb\xf9\x98\x11\x81\x19\xb6\xf1\x26\x23\x4d\x1d\x48\xf6\x90\x6c\x90\x0b\x4c\x4a\xdc\xb6\x2d\xe1\x4d\x3c\xd5\xe1\x85\x41\xb0\x08\x0d\xa1\x7b\xdc\xeb\x3e\x44\xc5\xd9\x96\x31\x48\xa2\x57\xb9\x89\x37\xfd\x18\xe3\xc7\x72\x86\xc7\x38\x91\x83\x93\x8f\xab\x22\x41\x86\xea\x28\x33\x27\x5c\x34\x95\xc5\x7f\x37\xc8\xa8\x8d\x73\xaa\x8e\xa3\xfa\xfc\xb4\x68\x9a\x97\x62\x7d\xdb\x4e\x8d\x9c\x74\xaa\x53\x67\xed\x6f\xf7\x3b\x00\x00\xff\xff\xfe\x97\xce\xec\x37\x0c\x00\x00")
|
||||
|
||||
func openapiKustomizationapiSwaggerJsonBytes() ([]byte, error) {
|
||||
func kustomizationapiSwaggerJsonBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_openapiKustomizationapiSwaggerJson,
|
||||
"openapi/kustomizationapi/swagger.json",
|
||||
_kustomizationapiSwaggerJson,
|
||||
"kustomizationapi/swagger.json",
|
||||
)
|
||||
}
|
||||
|
||||
func openapiKustomizationapiSwaggerJson() (*asset, error) {
|
||||
bytes, err := openapiKustomizationapiSwaggerJsonBytes()
|
||||
func kustomizationapiSwaggerJson() (*asset, error) {
|
||||
bytes, err := kustomizationapiSwaggerJsonBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "openapi/kustomizationapi/swagger.json", size: 3127, mode: os.FileMode(420), modTime: time.Unix(1602011464, 0)}
|
||||
info := bindataFileInfo{name: "kustomizationapi/swagger.json", size: 3127, mode: os.FileMode(420), modTime: time.Unix(1602011464, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@@ -152,7 +152,7 @@ func AssetNames() []string {
|
||||
|
||||
// _bindata is a table, holding each asset generator, mapped to its name.
|
||||
var _bindata = map[string]func() (*asset, error){
|
||||
"openapi/kustomizationapi/swagger.json": openapiKustomizationapiSwaggerJson,
|
||||
"kustomizationapi/swagger.json": kustomizationapiSwaggerJson,
|
||||
}
|
||||
|
||||
// AssetDir returns the file names below a certain
|
||||
@@ -196,10 +196,8 @@ type bintree struct {
|
||||
}
|
||||
|
||||
var _bintree = &bintree{nil, map[string]*bintree{
|
||||
"openapi": &bintree{nil, map[string]*bintree{
|
||||
"kustomizationapi": &bintree{nil, map[string]*bintree{
|
||||
"swagger.json": &bintree{openapiKustomizationapiSwaggerJson, map[string]*bintree{}},
|
||||
}},
|
||||
"kustomizationapi": &bintree{nil, map[string]*bintree{
|
||||
"swagger.json": &bintree{kustomizationapiSwaggerJson, map[string]*bintree{}},
|
||||
}},
|
||||
}}
|
||||
|
||||
|
||||
27
kyaml/openapi/makeOpenApiInfoDotGo.sh
Executable file
27
kyaml/openapi/makeOpenApiInfoDotGo.sh
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
# Copyright 2020 The Kubernetes Authors.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
set -e
|
||||
|
||||
if ! command -v jq &> /dev/null ; then
|
||||
echo Please install jq
|
||||
echo on ubuntu: sudo apt-get install jq
|
||||
exit 1
|
||||
fi
|
||||
|
||||
OPEN_API_INFO=$(\
|
||||
jq -r '.info' $1 | \
|
||||
sed 's/[\" *]//g' | \
|
||||
tr -d '\n' )
|
||||
|
||||
cat <<EOF >kubernetesapi/openapiinfo.go
|
||||
// Copyright 2020 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Code generated by $0; DO NOT EDIT.
|
||||
|
||||
package kubernetesapi
|
||||
|
||||
const Info = "$OPEN_API_INFO"
|
||||
EOF
|
||||
@@ -363,11 +363,11 @@ func (rs *ResourceSchema) PatchStrategyAndKey() (string, string) {
|
||||
const (
|
||||
// kubernetesAPIAssetName is the name of the asset containing the statically compiled in
|
||||
// OpenAPI definitions for Kubernetes built-in types
|
||||
kubernetesAPIAssetName = "openapi/kubernetesapi/swagger.json"
|
||||
kubernetesAPIAssetName = "kubernetesapi/swagger.json"
|
||||
|
||||
// kustomizationAPIAssetName is the name of the asset containing the statically compiled in
|
||||
// OpenAPI definitions for Kustomization built-in types
|
||||
kustomizationAPIAssetName = "openapi/kustomizationapi/swagger.json"
|
||||
kustomizationAPIAssetName = "kustomizationapi/swagger.json"
|
||||
|
||||
// kubernetesGVKExtensionKey is the key to lookup the kubernetes group version kind extension
|
||||
// -- the extension is an array of objects containing a gvk
|
||||
|
||||
@@ -114,7 +114,7 @@ func (fs *fieldSetter) set(
|
||||
}
|
||||
|
||||
// be sure to set the tag to the matching type so the yaml doesn't incorrectly quote
|
||||
//integers or booleans as strings
|
||||
// integers or booleans as strings
|
||||
fType := fieldmeta.FieldValueType(f.Schema.Type[0])
|
||||
if err := fType.Validate(field.YNode().Value); err != nil {
|
||||
return err
|
||||
|
||||
@@ -172,6 +172,9 @@ type SetterDefinition struct {
|
||||
// live apply/preview. This field is added to the setter definition to record
|
||||
// the package publisher's intent to make the setter required to be set.
|
||||
Required bool `yaml:"required,omitempty"`
|
||||
|
||||
// IsSet indicates the specified field has been explicitly assigned.
|
||||
IsSet bool `yaml:"isSet,omitempty"`
|
||||
}
|
||||
|
||||
func (sd SetterDefinition) AddToFile(path string) error {
|
||||
|
||||
@@ -281,13 +281,13 @@ packageMetadata:
|
||||
func TestAdd_Filter2(t *testing.T) {
|
||||
path := filepath.Join(os.TempDir(), "resourcefile")
|
||||
|
||||
//write initial resourcefile to temp path
|
||||
// write initial resourcefile to temp path
|
||||
err := ioutil.WriteFile(path, []byte(resourcefile), 0666)
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
//add a setter definition
|
||||
// add a setter definition
|
||||
sd := SetterDefinition{
|
||||
Name: "image",
|
||||
Value: "1",
|
||||
|
||||
@@ -353,6 +353,8 @@ type SetOpenAPI struct {
|
||||
Description string `yaml:"description"`
|
||||
|
||||
SetBy string `yaml:"setBy"`
|
||||
|
||||
IsSet bool `yaml:"isSet"`
|
||||
}
|
||||
|
||||
// UpdateFile updates the OpenAPI definitions in a file with the given setter value.
|
||||
@@ -458,8 +460,10 @@ func (s SetOpenAPI) Filter(object *yaml.RNode) (*yaml.RNode, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := def.PipeE(&yaml.FieldSetter{Name: "isSet", StringValue: "true"}); err != nil {
|
||||
return nil, err
|
||||
if s.IsSet {
|
||||
if err := def.PipeE(&yaml.FieldSetter{Name: "isSet", StringValue: "true"}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if s.Description != "" {
|
||||
|
||||
@@ -971,11 +971,13 @@ func TestSetOpenAPI_Filter(t *testing.T) {
|
||||
description string
|
||||
setBy string
|
||||
err string
|
||||
isSet bool
|
||||
}{
|
||||
{
|
||||
name: "set-replicas",
|
||||
setter: "replicas",
|
||||
value: "3",
|
||||
isSet: true,
|
||||
input: `
|
||||
openAPI:
|
||||
definitions:
|
||||
@@ -1023,6 +1025,7 @@ openAPI:
|
||||
name: "set-annotation-quoted",
|
||||
setter: "replicas",
|
||||
value: "3",
|
||||
isSet: true,
|
||||
input: `
|
||||
openAPI:
|
||||
definitions:
|
||||
@@ -1048,6 +1051,7 @@ openAPI:
|
||||
setter: "replicas",
|
||||
value: "3",
|
||||
description: "hello world",
|
||||
isSet: true,
|
||||
input: `
|
||||
openAPI:
|
||||
definitions:
|
||||
@@ -1094,6 +1098,7 @@ openAPI:
|
||||
setter: "replicas",
|
||||
value: "3",
|
||||
setBy: "carl",
|
||||
isSet: true,
|
||||
input: `
|
||||
openAPI:
|
||||
definitions:
|
||||
@@ -1139,6 +1144,7 @@ openAPI:
|
||||
name: "set-replicas-set-by-empty",
|
||||
setter: "replicas",
|
||||
value: "3",
|
||||
isSet: true,
|
||||
input: `
|
||||
openAPI:
|
||||
definitions:
|
||||
@@ -1229,7 +1235,6 @@ openAPI:
|
||||
enumValues:
|
||||
foo: bar
|
||||
baz: biz
|
||||
isSet: true
|
||||
io.k8s.cli.setters.no-match-2':
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
@@ -1242,6 +1247,7 @@ openAPI:
|
||||
name: "set-replicas-fail",
|
||||
setter: "replicas",
|
||||
value: "hello",
|
||||
isSet: true,
|
||||
input: `
|
||||
openAPI:
|
||||
definitions:
|
||||
@@ -1272,6 +1278,7 @@ openAPI:
|
||||
name: "error",
|
||||
setter: "replicas",
|
||||
err: `setter "replicas" is not found`,
|
||||
isSet: true,
|
||||
input: `
|
||||
openAPI:
|
||||
definitions:
|
||||
@@ -1328,7 +1335,6 @@ openAPI:
|
||||
name: args
|
||||
listValues: ["2", "3", "4"]
|
||||
required: true
|
||||
isSet: true
|
||||
`,
|
||||
},
|
||||
}
|
||||
@@ -1343,7 +1349,7 @@ openAPI:
|
||||
// invoke the setter
|
||||
instance := &SetOpenAPI{
|
||||
Name: test.setter, Value: test.value, ListValues: test.values,
|
||||
SetBy: test.setBy, Description: test.description}
|
||||
SetBy: test.setBy, Description: test.description, IsSet: test.isSet}
|
||||
result, err := instance.Filter(in)
|
||||
if test.err != "" {
|
||||
if !assert.EqualError(t, err, test.err) {
|
||||
|
||||
@@ -38,6 +38,8 @@ type FieldSetter struct {
|
||||
ResourcesPath string
|
||||
|
||||
RecurseSubPackages bool
|
||||
|
||||
IsSet bool
|
||||
}
|
||||
|
||||
func (fs *FieldSetter) Filter(input []*yaml.RNode) ([]*yaml.RNode, error) {
|
||||
@@ -54,6 +56,7 @@ func (fs FieldSetter) Set() (int, error) {
|
||||
ListValues: fs.ListValues,
|
||||
Description: fs.Description,
|
||||
SetBy: fs.SetBy,
|
||||
IsSet: fs.IsSet,
|
||||
}
|
||||
|
||||
// the input field value is updated in the openAPI file and then parsed
|
||||
@@ -156,6 +159,7 @@ func syncOpenAPIValuesWithSchema(openAPIPath string) error {
|
||||
Name: cliExt.Setter.Name,
|
||||
Value: cliExt.Setter.Value,
|
||||
ListValues: cliExt.Setter.ListValues,
|
||||
IsSet: true,
|
||||
}
|
||||
if err := soa.UpdateFile(openAPIPath); err != nil {
|
||||
return err
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user