mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-29 09:40:49 +00:00
Merge remote-tracking branch 'upstream/master' into release-cmd/config-v0.1
This commit is contained in:
6
Makefile
6
Makefile
@@ -35,12 +35,12 @@ verify-kustomize-e2e: test-examples-e2e-kustomize
|
||||
# since everything uses the same implicit GOPATH.
|
||||
# This installs in a temp dir to avoid overwriting someone else's
|
||||
# linter, then installs in MYGOBIN with a new name.
|
||||
# Version pinned by api/go.mod
|
||||
# Version pinned by hack/go.mod
|
||||
$(MYGOBIN)/golangci-lint-kustomize:
|
||||
( \
|
||||
set -e; \
|
||||
export GOBIN=$$(mktemp -d) \
|
||||
cd api; \
|
||||
export GOBIN=$$(mktemp -d); \
|
||||
cd hack; \
|
||||
GO111MODULE=on go install github.com/golangci/golangci-lint/cmd/golangci-lint; \
|
||||
mv $$GOBIN/golangci-lint $(MYGOBIN)/golangci-lint-kustomize \
|
||||
)
|
||||
|
||||
@@ -107,7 +107,7 @@ Take the work from step (1) above, move it into a
|
||||
`someApp` subdirectory called `base`, then
|
||||
place overlays in a sibling directory.
|
||||
|
||||
An overlay is just another kustomization, refering to
|
||||
An overlay is just another kustomization, referring to
|
||||
the base, and referring to patches to apply to that
|
||||
base.
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ func (p *NamespaceTransformerPlugin) Transform(m resmap.ResMap) error {
|
||||
|
||||
matches := m.GetMatchingResourcesByCurrentId(r.CurId().Equals)
|
||||
if len(matches) != 1 {
|
||||
return fmt.Errorf("namespace tranformation produces ID conflict: %+v", matches)
|
||||
return fmt.Errorf("namespace transformation produces ID conflict: %+v", matches)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -209,7 +209,7 @@ but they are functional.
|
||||
|
||||
## Technical details
|
||||
|
||||
### Overall design and imlpementation
|
||||
### Overall design and implementations
|
||||
|
||||
There are a few components that are all running together in order to get
|
||||
the overall application to work smoothly. This section will provide a brief
|
||||
|
||||
@@ -11,7 +11,7 @@ metadata:
|
||||
spec:
|
||||
storage:
|
||||
gcs:
|
||||
# the bucket must exist for the snapshot respository to be created successfully.
|
||||
# the bucket must exist for the snapshot repository to be created successfully.
|
||||
bucket: kustomize-backup
|
||||
# the path does not need to exist.
|
||||
# If the path does not exist, the controller will create the folder in the GCS bucket.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Find all the trasnformer files whose `kinds` field includes `HelmValues`, and
|
||||
Find all the transformer files whose `kinds` field includes `HelmValues`, and
|
||||
only output certain fields of each document:
|
||||
```
|
||||
curl -s -X GET "${ElasticSearchURL}:9200/${INDEXNAME}/_search?pretty" -H 'Content-Type: application/json' -d'
|
||||
|
||||
@@ -38,10 +38,7 @@ func (f *Factory) MakeConfigMap(
|
||||
return nil, errors.Wrap(err, "trouble mapping")
|
||||
}
|
||||
}
|
||||
if f.options != nil {
|
||||
cm.SetLabels(f.options.Labels)
|
||||
cm.SetAnnotations(f.options.Annotations)
|
||||
}
|
||||
f.setLabelsAndAnnnotations(cm, args.GeneratorOptions)
|
||||
return cm, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ BAR=baz
|
||||
}
|
||||
}
|
||||
|
||||
func makeLiteralConfigMap(name string) *corev1.ConfigMap {
|
||||
func makeLiteralConfigMap(name string, labels, annotations map[string]string) *corev1.ConfigMap {
|
||||
cm := &corev1.ConfigMap{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: "v1",
|
||||
@@ -69,7 +69,12 @@ func makeLiteralConfigMap(name string) *corev1.ConfigMap {
|
||||
"d": "true",
|
||||
},
|
||||
}
|
||||
cm.SetLabels(map[string]string{"foo": "bar"})
|
||||
if labels != nil {
|
||||
cm.SetLabels(labels)
|
||||
}
|
||||
if annotations != nil {
|
||||
cm.SetAnnotations(annotations)
|
||||
}
|
||||
return cm
|
||||
}
|
||||
|
||||
@@ -128,7 +133,49 @@ func TestConstructConfigMap(t *testing.T) {
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
expected: makeLiteralConfigMap("literalConfigMap"),
|
||||
expected: makeLiteralConfigMap("literalConfigMap", map[string]string{
|
||||
"foo": "bar",
|
||||
}, nil),
|
||||
},
|
||||
{
|
||||
description: "construct config map from literal with GeneratorOptions in ConfigMapArgs",
|
||||
input: types.ConfigMapArgs{
|
||||
GeneratorArgs: types.GeneratorArgs{
|
||||
Name: "literalConfigMap",
|
||||
KvPairSources: types.KvPairSources{
|
||||
LiteralSources: []string{"a=x", "b=y", "c=\"Hello World\"", "d='true'"},
|
||||
},
|
||||
GeneratorOptions: &types.GeneratorOptions{
|
||||
Labels: map[string]string{
|
||||
"foo": "changed",
|
||||
"cat": "dog",
|
||||
},
|
||||
Annotations: map[string]string{
|
||||
"foo": "changed",
|
||||
"cat": "dog",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
options: &types.GeneratorOptions{
|
||||
Labels: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
Annotations: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
// GeneratorOptions from the ConfigMapArgs take precedence over the
|
||||
// factory level GeneratorOptions and should overwrite
|
||||
// labels/annotations set in the factory level if there are common
|
||||
// labels/annotations
|
||||
expected: makeLiteralConfigMap("literalConfigMap", map[string]string{
|
||||
"foo": "changed",
|
||||
"cat": "dog",
|
||||
}, map[string]string{
|
||||
"foo": "changed",
|
||||
"cat": "dog",
|
||||
}),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package configmapandsecret
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"sigs.k8s.io/kustomize/api/ifc"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
)
|
||||
@@ -20,4 +21,35 @@ func NewFactory(
|
||||
return &Factory{kvLdr: kvLdr, options: o}
|
||||
}
|
||||
|
||||
// setLabelsAndAnnnotations will take the labels and annotations from
|
||||
// global GeneratorOptions and resource level GeneratorOptions and merge them
|
||||
// with the resource level taking precedence, and then set them on the provided
|
||||
// obj.
|
||||
func (f *Factory) setLabelsAndAnnnotations(obj metav1.Object, opts *types.GeneratorOptions) {
|
||||
labels := make(map[string]string)
|
||||
annotations := make(map[string]string)
|
||||
if f.options != nil {
|
||||
for k, v := range f.options.Labels {
|
||||
labels[k] = v
|
||||
}
|
||||
for k, v := range f.options.Annotations {
|
||||
annotations[k] = v
|
||||
}
|
||||
}
|
||||
if opts != nil {
|
||||
for k, v := range opts.Labels {
|
||||
labels[k] = v
|
||||
}
|
||||
for k, v := range opts.Annotations {
|
||||
annotations[k] = v
|
||||
}
|
||||
}
|
||||
if len(labels) != 0 {
|
||||
obj.SetLabels(labels)
|
||||
}
|
||||
if len(annotations) != 0 {
|
||||
obj.SetAnnotations(annotations)
|
||||
}
|
||||
}
|
||||
|
||||
const keyExistsErrorMsg = "cannot add key %s, another key by that name already exists: %v"
|
||||
|
||||
@@ -39,10 +39,7 @@ func (f *Factory) MakeSecret(
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if f.options != nil {
|
||||
s.SetLabels(f.options.Labels)
|
||||
s.SetAnnotations(f.options.Annotations)
|
||||
}
|
||||
f.setLabelsAndAnnnotations(s, args.GeneratorOptions)
|
||||
return s, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ BAR=baz
|
||||
}
|
||||
}
|
||||
|
||||
func makeLiteralSecret(name string) *corev1.Secret {
|
||||
func makeLiteralSecret(name string, labels, annotations map[string]string) *corev1.Secret {
|
||||
s := &corev1.Secret{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: "v1",
|
||||
@@ -66,7 +66,12 @@ func makeLiteralSecret(name string) *corev1.Secret {
|
||||
},
|
||||
Type: "Opaque",
|
||||
}
|
||||
s.SetLabels(map[string]string{"foo": "bar"})
|
||||
if labels != nil {
|
||||
s.SetLabels(labels)
|
||||
}
|
||||
if annotations != nil {
|
||||
s.SetAnnotations(annotations)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
@@ -120,7 +125,49 @@ func TestConstructSecret(t *testing.T) {
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
expected: makeLiteralSecret("literalSecret"),
|
||||
expected: makeLiteralSecret("literalSecret", map[string]string{
|
||||
"foo": "bar",
|
||||
}, nil),
|
||||
},
|
||||
{
|
||||
description: "construct secret from literal with GeneratorOptions in SecretArgs",
|
||||
input: types.SecretArgs{
|
||||
GeneratorArgs: types.GeneratorArgs{
|
||||
Name: "literalSecret",
|
||||
KvPairSources: types.KvPairSources{
|
||||
LiteralSources: []string{"a=x", "b=y"},
|
||||
},
|
||||
GeneratorOptions: &types.GeneratorOptions{
|
||||
Labels: map[string]string{
|
||||
"foo": "changed",
|
||||
"cat": "dog",
|
||||
},
|
||||
Annotations: map[string]string{
|
||||
"foo": "changed",
|
||||
"cat": "dog",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
options: &types.GeneratorOptions{
|
||||
Labels: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
Annotations: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
// GeneratorOptions from the SecretArgs take precedence over the
|
||||
// factory level GeneratorOptions and should overwrite
|
||||
// labels/annotations set in the factory level if there are common
|
||||
// labels/annotations
|
||||
expected: makeLiteralSecret("literalSecret", map[string]string{
|
||||
"foo": "changed",
|
||||
"cat": "dog",
|
||||
}, map[string]string{
|
||||
"foo": "changed",
|
||||
"cat": "dog",
|
||||
}),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
@@ -302,18 +301,15 @@ func (kt *KustTarget) configureExternalTransformers() ([]resmap.Transformer, err
|
||||
func (kt *KustTarget) accumulateResources(
|
||||
ra *accumulator.ResAccumulator, paths []string) error {
|
||||
for _, path := range paths {
|
||||
ldr, err := kt.ldr.New(path)
|
||||
if err == nil {
|
||||
err = kt.accumulateDirectory(ra, ldr)
|
||||
if err != nil {
|
||||
return err
|
||||
// try loading resource as file then as base (directory or git repository)
|
||||
if errF := kt.accumulateFile(ra, path); errF != nil {
|
||||
ldr, errL := kt.ldr.New(path)
|
||||
if errL != nil {
|
||||
return fmt.Errorf("accumulateFile %q, loader.New %q", errF, errL)
|
||||
}
|
||||
} else {
|
||||
err2 := kt.accumulateFile(ra, path)
|
||||
if err2 != nil {
|
||||
// Log ldr.New() error to highlight git failures.
|
||||
log.Print(err.Error())
|
||||
return err2
|
||||
errD := kt.accumulateDirectory(ra, ldr)
|
||||
if errD != nil {
|
||||
return fmt.Errorf("accumulateFile %q, accumulateDirector: %q", errF, errD)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,9 @@ varReference:
|
||||
- path: spec/jobTemplate/spec/template/spec/initContainers/volumeMounts/mountPath
|
||||
kind: CronJob
|
||||
|
||||
- path: spec/jobTemplate/spec/template/volumes/nfs/server
|
||||
kind: CronJob
|
||||
|
||||
- path: spec/template/spec/containers/args
|
||||
kind: DaemonSet
|
||||
|
||||
@@ -54,6 +57,9 @@ varReference:
|
||||
- path: spec/template/spec/initContainers/volumeMounts/mountPath
|
||||
kind: DaemonSet
|
||||
|
||||
- path: spec/template/spec/volumes/nfs/server
|
||||
kind: DaemonSet
|
||||
|
||||
- path: spec/template/spec/containers/args
|
||||
kind: Deployment
|
||||
|
||||
@@ -78,6 +84,9 @@ varReference:
|
||||
- path: spec/template/spec/initContainers/volumeMounts/mountPath
|
||||
kind: Deployment
|
||||
|
||||
- path: spec/template/spec/volumes/nfs/server
|
||||
kind: Deployment
|
||||
|
||||
- path: spec/rules/host
|
||||
kind: Ingress
|
||||
|
||||
@@ -111,6 +120,9 @@ varReference:
|
||||
- path: spec/template/spec/initContainers/volumeMounts/mountPath
|
||||
kind: Job
|
||||
|
||||
- path: spec/template/spec/volumes/nfs/server
|
||||
kind: Job
|
||||
|
||||
- path: spec/containers/args
|
||||
kind: Pod
|
||||
|
||||
@@ -135,6 +147,9 @@ varReference:
|
||||
- path: spec/initContainers/volumeMounts/mountPath
|
||||
kind: Pod
|
||||
|
||||
- path: spec/volumes/nfs/server
|
||||
kind: Pod
|
||||
|
||||
- path: spec/template/spec/containers/args
|
||||
kind: ReplicaSet
|
||||
|
||||
@@ -159,6 +174,9 @@ varReference:
|
||||
- path: spec/template/spec/initContainers/volumeMounts/mountPath
|
||||
kind: ReplicaSet
|
||||
|
||||
- path: spec/template/spec/volumes/nfs/server
|
||||
kind: ReplicaSet
|
||||
|
||||
- path: spec/ports/port
|
||||
kind: Service
|
||||
|
||||
@@ -189,6 +207,12 @@ varReference:
|
||||
- path: spec/template/spec/initContainers/volumeMounts/mountPath
|
||||
kind: StatefulSet
|
||||
|
||||
- path: spec/volumeClaimTemplates/spec/nfs/server
|
||||
kind: StatefulSet
|
||||
|
||||
- path: spec/nfs/server
|
||||
kind: PersistentVolume
|
||||
|
||||
- path: metadata/labels
|
||||
|
||||
- path: metadata/annotations
|
||||
|
||||
@@ -74,7 +74,7 @@ spec:
|
||||
if err == nil {
|
||||
t.Fatalf("expected an error")
|
||||
}
|
||||
if !IsMissingKustomizationFileError(err) {
|
||||
if !strings.Contains(err.Error(), "accumulating resources") {
|
||||
t.Fatalf("unexpected error: %q", err)
|
||||
}
|
||||
}
|
||||
@@ -89,7 +89,7 @@ resources:
|
||||
if err == nil {
|
||||
t.Fatalf("expected an error")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "'/app/deployment.yaml' doesn't exist") {
|
||||
if !strings.Contains(err.Error(), "accumulating resources") {
|
||||
t.Fatalf("unexpected error: %q", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1336,3 +1336,637 @@ spec:
|
||||
protocol: TCP
|
||||
`)
|
||||
}
|
||||
|
||||
func TestVariableRefNFSServer(t *testing.T) {
|
||||
th := kusttest_test.MakeHarness(t)
|
||||
th.WriteK("/app/base", `
|
||||
resources:
|
||||
- pv_pvc.yaml
|
||||
- nfs_deployment.yaml
|
||||
- nfs_service.yaml
|
||||
- Deployment.yaml
|
||||
- CronJob.yaml
|
||||
- DaemonSet.yaml
|
||||
- ReplicaSet.yaml
|
||||
- StatefulSet.yaml
|
||||
- Pod.yaml
|
||||
- Job.yaml
|
||||
- nfs_pv.yaml
|
||||
|
||||
vars:
|
||||
- name: NFS_SERVER_SERVICE_NAME
|
||||
objref:
|
||||
kind: Service
|
||||
name: nfs-server-service
|
||||
apiVersion: v1
|
||||
fieldref:
|
||||
fieldpath: metadata.name
|
||||
`)
|
||||
th.WriteF("/app/base/pv_pvc.yaml", `
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: shared-volume-claim
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
`)
|
||||
th.WriteF("/app/base/nfs_deployment.yaml", `
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nfs-server
|
||||
spec:
|
||||
replicas: 1
|
||||
template:
|
||||
spec:
|
||||
metadata:
|
||||
labels:
|
||||
role: nfs-server
|
||||
containers:
|
||||
- name: nfs-server
|
||||
image: gcr.io/google_containers/volume-nfs:0.8
|
||||
ports:
|
||||
- name: nfs
|
||||
containerPort: 2049
|
||||
- name: mountd
|
||||
containerPort: 20048
|
||||
- name: rpcbind
|
||||
containerPort: 111
|
||||
securityContext:
|
||||
privileged: true
|
||||
volumeMounts:
|
||||
- mountPath: /exports
|
||||
name: shared-files
|
||||
volumes:
|
||||
- name: shared-files
|
||||
persistentVolumeClaim:
|
||||
claimName: shared-volume-claim
|
||||
`)
|
||||
th.WriteF("/app/base/nfs_service.yaml", `
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nfs-server-service
|
||||
spec:
|
||||
ports:
|
||||
- name: nfs
|
||||
port: 2049
|
||||
- name: mountd
|
||||
port: 20048
|
||||
- name: rpcbind
|
||||
port: 111
|
||||
selector:
|
||||
role: nfs-server
|
||||
`)
|
||||
th.WriteF("/app/base/Deployment.yaml", `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx
|
||||
labels:
|
||||
app.kubernetes.io/component: nginx
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/component: nginx
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/component: nginx
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.15.7-alpine
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 80
|
||||
volumeMounts:
|
||||
- mountPath: /app/shared-files
|
||||
name: nfs-files-vol
|
||||
volumes:
|
||||
- name: nfs-files-vol
|
||||
nfs:
|
||||
server: $(NFS_SERVER_SERVICE_NAME).default.srv.cluster.local
|
||||
path: /
|
||||
readOnly: false
|
||||
`)
|
||||
th.WriteF("/app/base/CronJob.yaml", `
|
||||
apiVersion: batch/v1beta1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: hello
|
||||
spec:
|
||||
schedule: "*/1 * * * *"
|
||||
jobTemplate:
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: hello
|
||||
image: busybox
|
||||
args:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- date; echo Hello from the Kubernetes cluster
|
||||
restartPolicy: OnFailure
|
||||
volumeMounts:
|
||||
- mountPath: /app/shared-files
|
||||
name: nfs-files-vol
|
||||
volumes:
|
||||
- name: nfs-files-vol
|
||||
nfs:
|
||||
server: $(NFS_SERVER_SERVICE_NAME).default.srv.cluster.local
|
||||
path: /
|
||||
readOnly: false
|
||||
`)
|
||||
th.WriteF("/app/base/DaemonSet.yaml", `
|
||||
apiVersion: apps/v1
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
name: fluentd-elasticsearch
|
||||
namespace: kube-system
|
||||
labels:
|
||||
k8s-app: fluentd-logging
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
name: fluentd-elasticsearch
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
name: fluentd-elasticsearch
|
||||
spec:
|
||||
tolerations:
|
||||
- key: node-role.kubernetes.io/master
|
||||
effect: NoSchedule
|
||||
containers:
|
||||
- name: fluentd-elasticsearch
|
||||
image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
|
||||
resources:
|
||||
limits:
|
||||
memory: 200Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 200Mi
|
||||
volumeMounts:
|
||||
- name: varlog
|
||||
mountPath: /var/log
|
||||
- name: varlibdockercontainers
|
||||
mountPath: /var/lib/docker/containers
|
||||
readOnly: true
|
||||
- mountPath: /app/shared-files
|
||||
name: nfs-files-vol
|
||||
terminationGracePeriodSeconds: 30
|
||||
volumes:
|
||||
- name: varlog
|
||||
hostPath:
|
||||
path: /var/log
|
||||
- name: varlibdockercontainers
|
||||
hostPath:
|
||||
path: /var/lib/docker/containers
|
||||
- name: nfs-files-vol
|
||||
nfs:
|
||||
server: $(NFS_SERVER_SERVICE_NAME).default.srv.cluster.local
|
||||
path: /
|
||||
readOnly: false
|
||||
`)
|
||||
th.WriteF("/app/base/ReplicaSet.yaml", `
|
||||
apiVersion: apps/v1
|
||||
kind: ReplicaSet
|
||||
metadata:
|
||||
name: frontend
|
||||
labels:
|
||||
app: guestbook
|
||||
tier: frontend
|
||||
spec:
|
||||
# modify replicas according to your case
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
tier: frontend
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
tier: frontend
|
||||
spec:
|
||||
containers:
|
||||
- name: php-redis
|
||||
image: gcr.io/google_samples/gb-frontend:v3
|
||||
volumeMounts:
|
||||
- mountPath: /app/shared-files
|
||||
name: nfs-files-vol
|
||||
volumes:
|
||||
- name: nfs-files-vol
|
||||
nfs:
|
||||
server: $(NFS_SERVER_SERVICE_NAME).default.srv.cluster.local
|
||||
path: /
|
||||
readOnly: false
|
||||
`)
|
||||
|
||||
th.WriteF("/app/base/Job.yaml", `
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: pi
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: pi
|
||||
image: perl
|
||||
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
|
||||
volumeMounts:
|
||||
- mountPath: /app/shared-files
|
||||
name: nfs-files-vol
|
||||
restartPolicy: Never
|
||||
volumes:
|
||||
- name: nfs-files-vol
|
||||
nfs:
|
||||
server: $(NFS_SERVER_SERVICE_NAME).default.srv.cluster.local
|
||||
path: /
|
||||
readOnly: false
|
||||
backoffLimit: 4
|
||||
`)
|
||||
th.WriteF("/app/base/StatefulSet.yaml", `
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: web
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx # has to match .spec.template.metadata.labels
|
||||
serviceName: "nginx"
|
||||
replicas: 3 # by default is 1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx # has to match .spec.selector.matchLabels
|
||||
spec:
|
||||
terminationGracePeriodSeconds: 10
|
||||
containers:
|
||||
- name: nginx
|
||||
image: k8s.gcr.io/nginx-slim:0.8
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: web
|
||||
volumeMounts:
|
||||
- name: www
|
||||
mountPath: /usr/share/nginx/html
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: www
|
||||
spec:
|
||||
accessModes: [ "ReadWriteMany" ]
|
||||
nfs:
|
||||
server: $(NFS_SERVER_SERVICE_NAME).default.srv.cluster.local
|
||||
path: /
|
||||
readOnly: false
|
||||
`)
|
||||
th.WriteF("/app/base/Pod.yaml", `
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: myapp-pod
|
||||
labels:
|
||||
app: myapp
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.15.7-alpine
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 80
|
||||
volumeMounts:
|
||||
- name: nfs-files-vol
|
||||
mountPath: /app/shared-files
|
||||
volumes:
|
||||
- name: nfs-files-vol
|
||||
nfs:
|
||||
server: $(NFS_SERVER_SERVICE_NAME).default.srv.cluster.local
|
||||
path: /
|
||||
readOnly: false
|
||||
`)
|
||||
th.WriteF("/app/base/nfs_pv.yaml", `
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: nfs-files-pv
|
||||
spec:
|
||||
capacity:
|
||||
storage: 10Gi
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
nfs:
|
||||
server: $(NFS_SERVER_SERVICE_NAME).default.srv.cluster.local
|
||||
path: /
|
||||
readOnly: false
|
||||
`)
|
||||
th.WriteK("/app/overlay", `
|
||||
nameprefix: kustomized-
|
||||
resources:
|
||||
- ../base
|
||||
`)
|
||||
m := th.Run("/app/overlay", th.MakeDefaultOptions())
|
||||
th.AssertActualEqualsExpected(m, `
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: kustomized-shared-volume-claim
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
---
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: kustomized-nfs-server
|
||||
spec:
|
||||
replicas: 1
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- image: gcr.io/google_containers/volume-nfs:0.8
|
||||
name: nfs-server
|
||||
ports:
|
||||
- containerPort: 2049
|
||||
name: nfs
|
||||
- containerPort: 20048
|
||||
name: mountd
|
||||
- containerPort: 111
|
||||
name: rpcbind
|
||||
securityContext:
|
||||
privileged: true
|
||||
volumeMounts:
|
||||
- mountPath: /exports
|
||||
name: shared-files
|
||||
metadata:
|
||||
labels:
|
||||
role: nfs-server
|
||||
volumes:
|
||||
- name: shared-files
|
||||
persistentVolumeClaim:
|
||||
claimName: kustomized-shared-volume-claim
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: kustomized-nfs-server-service
|
||||
spec:
|
||||
ports:
|
||||
- name: nfs
|
||||
port: 2049
|
||||
- name: mountd
|
||||
port: 20048
|
||||
- name: rpcbind
|
||||
port: 111
|
||||
selector:
|
||||
role: nfs-server
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/component: nginx
|
||||
name: kustomized-nginx
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/component: nginx
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/component: nginx
|
||||
spec:
|
||||
containers:
|
||||
- image: nginx:1.15.7-alpine
|
||||
name: nginx
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: http
|
||||
volumeMounts:
|
||||
- mountPath: /app/shared-files
|
||||
name: nfs-files-vol
|
||||
volumes:
|
||||
- name: nfs-files-vol
|
||||
nfs:
|
||||
path: /
|
||||
readOnly: false
|
||||
server: kustomized-nfs-server-service.default.srv.cluster.local
|
||||
---
|
||||
apiVersion: batch/v1beta1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: kustomized-hello
|
||||
spec:
|
||||
jobTemplate:
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- args:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- date; echo Hello from the Kubernetes cluster
|
||||
image: busybox
|
||||
name: hello
|
||||
restartPolicy: OnFailure
|
||||
volumeMounts:
|
||||
- mountPath: /app/shared-files
|
||||
name: nfs-files-vol
|
||||
volumes:
|
||||
- name: nfs-files-vol
|
||||
nfs:
|
||||
path: /
|
||||
readOnly: false
|
||||
server: kustomized-nfs-server-service.default.srv.cluster.local
|
||||
schedule: '*/1 * * * *'
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: fluentd-logging
|
||||
name: kustomized-fluentd-elasticsearch
|
||||
namespace: kube-system
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
name: fluentd-elasticsearch
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
name: fluentd-elasticsearch
|
||||
spec:
|
||||
containers:
|
||||
- image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
|
||||
name: fluentd-elasticsearch
|
||||
resources:
|
||||
limits:
|
||||
memory: 200Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 200Mi
|
||||
volumeMounts:
|
||||
- mountPath: /var/log
|
||||
name: varlog
|
||||
- mountPath: /var/lib/docker/containers
|
||||
name: varlibdockercontainers
|
||||
readOnly: true
|
||||
- mountPath: /app/shared-files
|
||||
name: nfs-files-vol
|
||||
terminationGracePeriodSeconds: 30
|
||||
tolerations:
|
||||
- effect: NoSchedule
|
||||
key: node-role.kubernetes.io/master
|
||||
volumes:
|
||||
- hostPath:
|
||||
path: /var/log
|
||||
name: varlog
|
||||
- hostPath:
|
||||
path: /var/lib/docker/containers
|
||||
name: varlibdockercontainers
|
||||
- name: nfs-files-vol
|
||||
nfs:
|
||||
path: /
|
||||
readOnly: false
|
||||
server: kustomized-nfs-server-service.default.srv.cluster.local
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: ReplicaSet
|
||||
metadata:
|
||||
labels:
|
||||
app: guestbook
|
||||
tier: frontend
|
||||
name: kustomized-frontend
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
tier: frontend
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
tier: frontend
|
||||
spec:
|
||||
containers:
|
||||
- image: gcr.io/google_samples/gb-frontend:v3
|
||||
name: php-redis
|
||||
volumeMounts:
|
||||
- mountPath: /app/shared-files
|
||||
name: nfs-files-vol
|
||||
volumes:
|
||||
- name: nfs-files-vol
|
||||
nfs:
|
||||
path: /
|
||||
readOnly: false
|
||||
server: kustomized-nfs-server-service.default.srv.cluster.local
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: kustomized-web
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx
|
||||
serviceName: nginx
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx
|
||||
spec:
|
||||
containers:
|
||||
- image: k8s.gcr.io/nginx-slim:0.8
|
||||
name: nginx
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: web
|
||||
volumeMounts:
|
||||
- mountPath: /usr/share/nginx/html
|
||||
name: www
|
||||
terminationGracePeriodSeconds: 10
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: www
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
nfs:
|
||||
path: /
|
||||
readOnly: false
|
||||
server: kustomized-nfs-server-service.default.srv.cluster.local
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
labels:
|
||||
app: myapp
|
||||
name: kustomized-myapp-pod
|
||||
spec:
|
||||
containers:
|
||||
- image: nginx:1.15.7-alpine
|
||||
name: nginx
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: http
|
||||
volumeMounts:
|
||||
- mountPath: /app/shared-files
|
||||
name: nfs-files-vol
|
||||
volumes:
|
||||
- name: nfs-files-vol
|
||||
nfs:
|
||||
path: /
|
||||
readOnly: false
|
||||
server: kustomized-nfs-server-service.default.srv.cluster.local
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: kustomized-pi
|
||||
spec:
|
||||
backoffLimit: 4
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- command:
|
||||
- perl
|
||||
- -Mbignum=bpi
|
||||
- -wle
|
||||
- print bpi(2000)
|
||||
image: perl
|
||||
name: pi
|
||||
volumeMounts:
|
||||
- mountPath: /app/shared-files
|
||||
name: nfs-files-vol
|
||||
restartPolicy: Never
|
||||
volumes:
|
||||
- name: nfs-files-vol
|
||||
nfs:
|
||||
path: /
|
||||
readOnly: false
|
||||
server: kustomized-nfs-server-service.default.srv.cluster.local
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: kustomized-nfs-files-pv
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
capacity:
|
||||
storage: 10Gi
|
||||
nfs:
|
||||
path: /
|
||||
readOnly: false
|
||||
server: kustomized-nfs-server-service.default.srv.cluster.local
|
||||
`)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,10 @@ package loader
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
@@ -86,6 +89,9 @@ type fileLoader struct {
|
||||
// File system utilities.
|
||||
fSys filesys.FileSystem
|
||||
|
||||
// Used to load from HTTP
|
||||
http *http.Client
|
||||
|
||||
// Used to clone repositories.
|
||||
cloner git.Cloner
|
||||
|
||||
@@ -293,6 +299,25 @@ func (fl *fileLoader) errIfRepoCycle(newRepoSpec *git.RepoSpec) error {
|
||||
// else an error. Relative paths are taken relative
|
||||
// to the root.
|
||||
func (fl *fileLoader) Load(path string) ([]byte, error) {
|
||||
if u, err := url.Parse(path); err == nil && (u.Scheme == "http" || u.Scheme == "https") {
|
||||
var hc *http.Client
|
||||
if fl.http != nil {
|
||||
hc = fl.http
|
||||
} else {
|
||||
hc = &http.Client{}
|
||||
}
|
||||
resp, err := hc.Get(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return body, nil
|
||||
}
|
||||
|
||||
if !filepath.IsAbs(path) {
|
||||
path = fl.root.Join(path)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
package loader
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
@@ -54,6 +56,7 @@ func makeLoader() *fileLoader {
|
||||
return NewFileLoaderAtRoot(MakeFakeFs(testCases))
|
||||
|
||||
}
|
||||
|
||||
func TestLoaderLoad(t *testing.T) {
|
||||
l1 := makeLoader()
|
||||
if "/" != l1.Root() {
|
||||
@@ -579,3 +582,93 @@ func TestRepoIndirectCycleDetection(t *testing.T) {
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Inspired by https://hassansin.github.io/Unit-Testing-http-client-in-Go
|
||||
type fakeRoundTripper func(req *http.Request) *http.Response
|
||||
|
||||
func (f fakeRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
return f(req), nil
|
||||
}
|
||||
|
||||
func makeFakeHTTPClient(fn fakeRoundTripper) *http.Client {
|
||||
return &http.Client{
|
||||
Transport: fn,
|
||||
}
|
||||
}
|
||||
|
||||
// TestLoaderHTTP test http file loader
|
||||
func TestLoaderHTTP(t *testing.T) {
|
||||
var testCasesFile = []testData{
|
||||
{
|
||||
path: "http/file.yaml",
|
||||
expectedContent: "file content",
|
||||
},
|
||||
}
|
||||
|
||||
l1 := NewFileLoaderAtRoot(MakeFakeFs(testCasesFile))
|
||||
if "/" != l1.Root() {
|
||||
t.Fatalf("incorrect root: '%s'\n", l1.Root())
|
||||
}
|
||||
for _, x := range testCasesFile {
|
||||
b, err := l1.Load(x.path)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected load error: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual([]byte(x.expectedContent), b) {
|
||||
t.Fatalf("in load expected %s, but got %s", x.expectedContent, b)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesHTTP = []testData{
|
||||
{
|
||||
path: "http://example.com/resource.yaml",
|
||||
expectedContent: "http content",
|
||||
},
|
||||
{
|
||||
path: "https://example.com/resource.yaml",
|
||||
expectedContent: "https content",
|
||||
},
|
||||
}
|
||||
|
||||
for _, x := range testCasesHTTP {
|
||||
hc := makeFakeHTTPClient(func(req *http.Request) *http.Response {
|
||||
u := req.URL.String()
|
||||
if x.path != u {
|
||||
t.Fatalf("expected URL %s, but got %s", x.path, u)
|
||||
}
|
||||
return &http.Response{
|
||||
StatusCode: 200,
|
||||
Body: ioutil.NopCloser(bytes.NewBufferString(x.expectedContent)),
|
||||
Header: make(http.Header),
|
||||
}
|
||||
})
|
||||
l2 := l1
|
||||
l2.http = hc
|
||||
b, err := l2.Load(x.path)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected load error: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual([]byte(x.expectedContent), b) {
|
||||
t.Fatalf("in load expected %s, but got %s", x.expectedContent, b)
|
||||
}
|
||||
}
|
||||
|
||||
var testCaseUnsupported = []testData{
|
||||
{
|
||||
path: "httpsnotreal://example.com/resource.yaml",
|
||||
expectedContent: "invalid",
|
||||
},
|
||||
}
|
||||
for _, x := range testCaseUnsupported {
|
||||
hc := makeFakeHTTPClient(func(req *http.Request) *http.Response {
|
||||
t.Fatalf("unexpected request to URL %s", req.URL.String())
|
||||
return nil
|
||||
})
|
||||
l2 := l1
|
||||
l2.http = hc
|
||||
_, err := l2.Load(x.path)
|
||||
if err == nil {
|
||||
t.Fatalf("expect error but get %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,4 +21,7 @@ type GeneratorArgs struct {
|
||||
|
||||
// KvPairSources for the generator.
|
||||
KvPairSources `json:",inline,omitempty" yaml:",inline,omitempty"`
|
||||
|
||||
// GeneratorOptions modify this generator
|
||||
GeneratorOptions *GeneratorOptions `json:"generatorOptions,omitempty" yaml:"generatorOptions,omitempty"`
|
||||
}
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
github.com/360EntSecGroup-Skylar/excelize v1.4.1/go.mod h1:vnax29X2usfl7HHkBrX5EvSCJcmH3dT9luvxzu8iGAE=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||
github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg=
|
||||
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
@@ -16,6 +22,7 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
|
||||
github.com/dustmop/soup v1.1.2-0.20190516214245-38228baa104e/go.mod h1:CgNC6SGbT+Xb8wGGvzilttZL1mc5sQ/5KkcxsZttMIk=
|
||||
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
||||
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
@@ -82,6 +89,7 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
|
||||
github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
||||
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||
github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8=
|
||||
@@ -91,6 +99,7 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
|
||||
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/paulmach/orb v0.1.3/go.mod h1:VFlX/8C+IQ1p6FTRRKzKoOPJnvEtA5G0Veuqwbu//Vk=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
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=
|
||||
@@ -100,6 +109,7 @@ github.com/posener/complete/v2 v2.0.1-alpha.12 h1:0wvkuDfHb5vSZlNBYgpEH4XQHpF46M
|
||||
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/qri-io/starlib v0.4.2-0.20200213133954-ff2e8cd5ef8d/go.mod h1:7DPO4domFU579Ga6E61sB9VFNaniPVwJP5C4bBCu3wA=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
@@ -116,6 +126,7 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.2.3-0.20181224173747-660f15d67dbb/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
@@ -123,10 +134,15 @@ github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljT
|
||||
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI=
|
||||
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
go.starlark.net v0.0.0-20190528202925-30ae18b8564f/go.mod h1:c1/X6cHgvdXj6pUlmWKMkuqRnW4K8x2vwt6JAaaircg=
|
||||
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI=
|
||||
@@ -137,6 +153,7 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/olekukonko/tablewriter"
|
||||
"github.com/spf13/cobra"
|
||||
@@ -67,8 +68,15 @@ func (r *ListSettersRunner) runE(c *cobra.Command, args []string) error {
|
||||
table.SetHeader([]string{"NAME", "VALUE", "SET BY", "DESCRIPTION", "COUNT"})
|
||||
for i := range r.List.Setters {
|
||||
s := r.List.Setters[i]
|
||||
v := s.Value
|
||||
|
||||
// if the setter is for a list, populate the values
|
||||
if len(s.ListValues) > 0 {
|
||||
v = strings.Join(s.ListValues, ",")
|
||||
v = fmt.Sprintf("[%s]", v)
|
||||
}
|
||||
table.Append([]string{
|
||||
s.Name, s.Value, s.SetBy, s.Description, fmt.Sprintf("%d", s.Count)})
|
||||
s.Name, v, s.SetBy, s.Description, fmt.Sprintf("%d", s.Count)})
|
||||
}
|
||||
table.Render()
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ func NewSetRunner(parent string) *SetRunner {
|
||||
r := &SetRunner{}
|
||||
c := &cobra.Command{
|
||||
Use: "set DIR NAME [VALUE]",
|
||||
Args: cobra.RangeArgs(1, 3),
|
||||
Args: cobra.MinimumNArgs(3),
|
||||
Short: commands.SetShort,
|
||||
Long: commands.SetLong,
|
||||
Example: commands.SetExamples,
|
||||
@@ -94,6 +94,11 @@ func (r *SetRunner) preRunE(c *cobra.Command, args []string) error {
|
||||
var err error
|
||||
r.Set.Name = args[1]
|
||||
r.Set.Value = args[2]
|
||||
|
||||
// set remaining values as list values
|
||||
if len(args) > 3 {
|
||||
r.Set.ListValues = args[3:]
|
||||
}
|
||||
r.Set.Description = r.Perform.Description
|
||||
r.Set.SetBy = r.Perform.SetBy
|
||||
r.OpenAPIFile, err = ext.GetOpenAPIFile(args)
|
||||
|
||||
@@ -89,6 +89,14 @@ func (r *RunFnRunner) getFunctions(c *cobra.Command, args, dataItems []string) (
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Network {
|
||||
err = fn.PipeE(
|
||||
yaml.LookupCreate(yaml.MappingNode, "container", "network"),
|
||||
yaml.SetField("required", yaml.NewScalarRNode("true")))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// create the function config
|
||||
rc, err := yaml.Parse(`
|
||||
|
||||
@@ -101,7 +101,7 @@ metadata:
|
||||
name: function-input
|
||||
annotations:
|
||||
config.kubernetes.io/function: |
|
||||
container: {image: 'foo:bar'}
|
||||
container: {image: 'foo:bar', network: {required: true}}
|
||||
data: {}
|
||||
kind: ConfigMap
|
||||
apiVersion: v1
|
||||
@@ -118,7 +118,7 @@ metadata:
|
||||
name: function-input
|
||||
annotations:
|
||||
config.kubernetes.io/function: |
|
||||
container: {image: 'foo:bar'}
|
||||
container: {image: 'foo:bar', network: {required: true}}
|
||||
data: {}
|
||||
kind: ConfigMap
|
||||
apiVersion: v1
|
||||
|
||||
@@ -18,7 +18,7 @@ cluster
|
||||
Resources (including configmap and secret generators)
|
||||
can _still be shared_ via the recommended best practice
|
||||
of placing them in a directory with their own
|
||||
kustomization file, and refering to this directory as a
|
||||
kustomization file, and referring to this directory as a
|
||||
[`base`](glossary.md#base) from any kustomization that
|
||||
wants to use it. This encourages modularity and
|
||||
relocatability.
|
||||
|
||||
@@ -48,7 +48,7 @@ like adding labels or annotatations, get dedicated
|
||||
transformer plugins - `LabelTransformer`,
|
||||
`AnnotationsTransformer`, etc.
|
||||
These accept relatively simple YAML configuration
|
||||
allowing easy targetting of any number of resources.
|
||||
allowing easy targeting of any number of resources.
|
||||
|
||||
Another class of edits take data from one specific
|
||||
object's field and use it in another (e.g. a service
|
||||
|
||||
@@ -131,6 +131,10 @@ crds:
|
||||
Modifies behavior of all [ConfigMap](#configmapgenerator)
|
||||
and [Secret](#secretgenerator) generators.
|
||||
|
||||
Additionally, generatorOptions can be set on a per resource level within each
|
||||
generator. For details on per-resource generatorOptions usage see
|
||||
[field-name-configMapGenerator] and See [field-name-secretGenerator].
|
||||
|
||||
```
|
||||
generatorOptions:
|
||||
# labels to add to all generated resources
|
||||
@@ -202,7 +206,7 @@ See [field-name-replicas].
|
||||
### resources
|
||||
|
||||
Each entry in this list must be a path to a
|
||||
_file_, or a path (or URL) refering to another
|
||||
_file_, or a path (or URL) referring to another
|
||||
kustomization _directory_, e.g.
|
||||
|
||||
```
|
||||
|
||||
@@ -273,9 +273,9 @@ more than one version).
|
||||
|
||||
_kustomize_ is a command line tool supporting
|
||||
template-free, structured customization of declarative
|
||||
configuration targetted to k8s-style objects.
|
||||
configuration targeted to k8s-style objects.
|
||||
|
||||
_Targetted to k8s means_ that kustomize has some
|
||||
_Targeted to k8s means_ that kustomize has some
|
||||
understanding of API resources, k8s concepts like
|
||||
names, labels, namespaces, etc. and the semantics of
|
||||
resource patching.
|
||||
|
||||
@@ -209,7 +209,7 @@ a YAML file containing its configuration (the file name
|
||||
provided in the kustomization file).
|
||||
|
||||
> TODO: restrictions on plugin to allow the _same exec
|
||||
> plugin_ to be targetted by both the
|
||||
> plugin_ to be targeted by both the
|
||||
> `generators` and `transformers` fields.
|
||||
>
|
||||
> - first arg could be the fixed string
|
||||
|
||||
@@ -90,9 +90,9 @@ commonAnnotations:
|
||||
Each entry in this list results in the creation of
|
||||
one ConfigMap resource (it's a generator of n maps).
|
||||
|
||||
The example below creates two ConfigMaps. One with the
|
||||
names and contents of the given files, the other with
|
||||
key/value as data.
|
||||
The example below creates three ConfigMaps. One with the names and contents of
|
||||
the given files, one with key/value as data, and a third which sets an
|
||||
annotation and label via generatorOptions for that single ConfigMap.
|
||||
|
||||
Each configMapGenerator item accepts a parameter of
|
||||
`behavior: [create|replace|merge]`.
|
||||
@@ -109,6 +109,14 @@ configMapGenerator:
|
||||
literals:
|
||||
- JAVA_HOME=/opt/java/jdk
|
||||
- JAVA_TOOL_OPTIONS=-agentlib:hprof
|
||||
- name: dashboards
|
||||
files:
|
||||
- mydashboard.json
|
||||
generatorOptions:
|
||||
annotations:
|
||||
dashboard: "1"
|
||||
labels:
|
||||
app.kubernetes.io/name: "app1"
|
||||
```
|
||||
|
||||
It is also possible to
|
||||
@@ -651,6 +659,15 @@ secretGenerator:
|
||||
envs:
|
||||
- env.txt
|
||||
type: Opaque
|
||||
- name: secret-with-annotation
|
||||
files:
|
||||
- app-config.yaml
|
||||
type: Opaque
|
||||
generatorOptions:
|
||||
annotations:
|
||||
app_config: "true"
|
||||
labels:
|
||||
app.kubernetes.io/name: "app2"
|
||||
```
|
||||
|
||||
### Usage via plugin
|
||||
|
||||
@@ -78,7 +78,7 @@ a7a2589e Fix yaml in generator examples.
|
||||
529db049 Introduce envs field.
|
||||
6d309b52 Introduce stacked transformers.
|
||||
abf538d8 Keep backward compatibility for image transformer
|
||||
7e12918f Keep var refernce in resources
|
||||
7e12918f Keep var references in resources
|
||||
7130e3ff Leave defautconfig empty for images
|
||||
3e85c458 Load default config for image transformer
|
||||
4162dbc2 Maintain resources in order loaded.
|
||||
|
||||
@@ -37,7 +37,7 @@ the _kustomize Go API_.
|
||||
|
||||
[import path]: https://github.com/golang/go/wiki/Modules#releasing-modules-v2-or-higher
|
||||
|
||||
In `kustomize/v3` (and preceeding major versions), the
|
||||
In `kustomize/v3` (and preceding major versions), the
|
||||
kustomize program and the API live the same Go
|
||||
module at `sigs.k8s.io/kustomize`, at [import path]
|
||||
`sigs.k8s.io/kustomize/v3`.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# Demo: Inline Patch
|
||||
|
||||
A kustomization file supports patching in three ways:
|
||||
- patchesStrategicMerge: A list of patch files where each file is parsed as a [Stragetic Merge Patch].
|
||||
- patchesStrategicMerge: A list of patch files where each file is parsed as a [Strategic Merge Patch].
|
||||
- patchesJSON6902: A list of patches and associated targetes, where each file is parsed as a [JSON Patch] and can only be applied to one target resource.
|
||||
- patches: A list of patches and their associated targets. The patch can be applied to multiple objects. It auto detects whether the patch is a [Strategic Merge Patch] or [JSON Patch].
|
||||
|
||||
|
||||
25
examples/loadHttp.md
Normal file
25
examples/loadHttp.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# load file from http
|
||||
|
||||
Resource and patch files could be loaded from http
|
||||
|
||||
<!-- @loadHttp -->
|
||||
```sh
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
|
||||
cat <<EOF >$DEMO_HOME/kustomization.yaml
|
||||
resources:
|
||||
- https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/examples/helloWorld/configMap.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
<!-- @loadHttp -->
|
||||
```sh
|
||||
test 1 == \
|
||||
$(kustomize build $DEMO_HOME | grep "Good Morning!" | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
|
||||
Kustomize will try loading resource as a file either from local or http. If it
|
||||
fails, try to load it as a directory or git repository.
|
||||
|
||||
Http load applies to patches as well. See full example in [loadHttp](loadHttp/).
|
||||
15
examples/loadHttp/kustomization.yaml
Normal file
15
examples/loadHttp/kustomization.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/examples/wordpress/wordpress/deployment.yaml
|
||||
- https://github.com/knative/serving/releases/download/v0.12.0/serving.yaml # redirects to s3
|
||||
patches:
|
||||
- https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/examples/wordpress/patch.yaml
|
||||
patchesStrategicMerge:
|
||||
- |-
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: custom-metrics-auth-reader
|
||||
namespace: kube-system
|
||||
$patch: delete
|
||||
7
hack/go.mod
Normal file
7
hack/go.mod
Normal file
@@ -0,0 +1,7 @@
|
||||
module sigs.k8s.io/kustomize/hack
|
||||
|
||||
go 1.14
|
||||
|
||||
require github.com/golangci/golangci-lint v1.23.8
|
||||
|
||||
exclude github.com/golangci/golangci-lint v1.24.0
|
||||
351
hack/go.sum
Normal file
351
hack/go.sum
Normal file
@@ -0,0 +1,351 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/OpenPeeDeeP/depguard v1.0.1 h1:VlW4R6jmBIv3/u1JNlawEvJMM4J+dPORPaZasQee8Us=
|
||||
github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM=
|
||||
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/bombsimon/wsl/v2 v2.0.0 h1:+Vjcn+/T5lSrO8Bjzhk4v14Un/2UyCA1E3V5j9nwTkQ=
|
||||
github.com/bombsimon/wsl/v2 v2.0.0/go.mod h1:mf25kr/SqFEPhhcxW1+7pxzGlW+hIl/hYTKY95VwV8U=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-critic/go-critic v0.4.1 h1:4DTQfT1wWwLg/hzxwD9bkdhDQrdJtxe6DUTadPlrIeE=
|
||||
github.com/go-critic/go-critic v0.4.1/go.mod h1:7/14rZGnZbY6E38VEGk2kVhoq6itzc1E68facVDK23g=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-lintpack/lintpack v0.5.2 h1:DI5mA3+eKdWeJ40nU4d6Wc26qmdG8RCi/btYq0TuRN0=
|
||||
github.com/go-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
|
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-toolsmith/astcast v1.0.0 h1:JojxlmI6STnFVG9yOImLeGREv8W2ocNUM+iOhR6jE7g=
|
||||
github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4=
|
||||
github.com/go-toolsmith/astcopy v1.0.0 h1:OMgl1b1MEpjFQ1m5ztEO06rz5CUd3oBv9RF7+DyvdG8=
|
||||
github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ=
|
||||
github.com/go-toolsmith/astequal v0.0.0-20180903214952-dcb477bfacd6/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY=
|
||||
github.com/go-toolsmith/astequal v1.0.0 h1:4zxD8j3JRFNyLN46lodQuqz3xdKSrur7U/sr0SDS/gQ=
|
||||
github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY=
|
||||
github.com/go-toolsmith/astfmt v0.0.0-20180903215011-8f8ee99c3086/go.mod h1:mP93XdblcopXwlyN4X4uodxXQhldPGZbcEJIimQHrkg=
|
||||
github.com/go-toolsmith/astfmt v1.0.0 h1:A0vDDXt+vsvLEdbMFJAUBI/uTbRw1ffOPnxsILnFL6k=
|
||||
github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw=
|
||||
github.com/go-toolsmith/astinfo v0.0.0-20180906194353-9809ff7efb21/go.mod h1:dDStQCHtmZpYOmjRP/8gHHnCCch3Zz3oEgCdZVdtweU=
|
||||
github.com/go-toolsmith/astp v0.0.0-20180903215135-0af7e3c24f30/go.mod h1:SV2ur98SGypH1UjcPpCatrV5hPazG6+IfNHbkDXBRrk=
|
||||
github.com/go-toolsmith/astp v1.0.0 h1:alXE75TXgcmupDsMK1fRAy0YUzLzqPVvBKoyWV+KPXg=
|
||||
github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI=
|
||||
github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8/go.mod h1:WoMrjiy4zvdS+Bg6z9jZH82QXwkcgCBX6nOfnmdaHks=
|
||||
github.com/go-toolsmith/pkgload v1.0.0/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc=
|
||||
github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUDxe2Jb4=
|
||||
github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8=
|
||||
github.com/go-toolsmith/typep v1.0.0 h1:zKymWyA1TRYvqYrYDrfEMZULyrhcnGY3x7LDKU2XQaA=
|
||||
github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU=
|
||||
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||
github.com/gofrs/flock v0.0.0-20190320160742-5135e617513b h1:ekuhfTjngPhisSjOJ0QWKpPQE8/rbknHaes6WVJj5Hw=
|
||||
github.com/gofrs/flock v0.0.0-20190320160742-5135e617513b/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0=
|
||||
github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4=
|
||||
github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM=
|
||||
github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk=
|
||||
github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6 h1:YYWNAGTKWhKpcLLt7aSj/odlKrSrelQwlovBpDuf19w=
|
||||
github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6/go.mod h1:DbHgvLiFKX1Sh2T1w8Q/h4NAI8MHIpzCdnBUDTXU3I0=
|
||||
github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613 h1:9kfjN3AdxcbsZBf8NjltjWihK2QfBBBZuv91cMFfDHw=
|
||||
github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613/go.mod h1:SyvUF2NxV+sN8upjjeVYr5W7tyxaT1JVtvhKhOn2ii8=
|
||||
github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3 h1:pe9JHs3cHHDQgOFXJJdYkK6fLz2PWyYtP4hthoCMvs8=
|
||||
github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3/go.mod h1:JXrF4TWy4tXYn62/9x8Wm/K/dm06p8tCKwFRDPZG/1o=
|
||||
github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee h1:J2XAy40+7yz70uaOiMbNnluTg7gyQhtGqLQncQh+4J8=
|
||||
github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee/go.mod h1:ozx7R9SIwqmqf5pRP90DhR2Oay2UIjGuKheCBCNwAYU=
|
||||
github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a h1:iR3fYXUjHCR97qWS8ch1y9zPNsgXThGwjKPrYfqMPks=
|
||||
github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU=
|
||||
github.com/golangci/golangci-lint v1.23.8 h1:NlD+Ld2TKH8qVmADy4iEvPxVmXaqPIeQu3d1cGQP4jc=
|
||||
github.com/golangci/golangci-lint v1.23.8/go.mod h1:g/38bxfhp4rI7zeWSxcdIeHTQGS58TCak8FYcyCmavQ=
|
||||
github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc h1:gLLhTLMk2/SutryVJ6D4VZCU3CUqr8YloG7FPIBWFpI=
|
||||
github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc/go.mod h1:e5tpTHCfVze+7EpLEozzMB3eafxo2KT5veNg1k6byQU=
|
||||
github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA=
|
||||
github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg=
|
||||
github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA=
|
||||
github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o=
|
||||
github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770 h1:EL/O5HGrF7Jaq0yNhBLucz9hTuRzj2LdwGBOaENgxIk=
|
||||
github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA=
|
||||
github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21 h1:leSNB7iYzLYSSx3J/s5sVf4Drkc68W2wm4Ixh/mr0us=
|
||||
github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21/go.mod h1:tf5+bzsHdTM0bsB7+8mt0GUMvjCgwLpTapNZHU8AajI=
|
||||
github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0 h1:HVfrLniijszjS1aiNg8JbBMO2+E1WIQ+j/gL4SQqGPg=
|
||||
github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4=
|
||||
github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys=
|
||||
github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3 h1:JVnpOZS+qxli+rgVl98ILOXVNbW+kb5wcxeGx8ShUIw=
|
||||
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE=
|
||||
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/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jingyugao/rowserrcheck v0.0.0-20191204022205-72ab7603b68a h1:GmsqmapfzSJkm28dhRoHz2tLRbJmqhU86IPgBtN3mmk=
|
||||
github.com/jingyugao/rowserrcheck v0.0.0-20191204022205-72ab7603b68a/go.mod h1:xRskid8CManxVta/ALEhJha/pweKBaVG6fWgc0yH25s=
|
||||
github.com/jirfag/go-printf-func-name v0.0.0-20191110105641-45db9963cdd3 h1:jNYPNLe3d8smommaoQlK7LOA5ESyUJJ+Wf79ZtA7Vp4=
|
||||
github.com/jirfag/go-printf-func-name v0.0.0-20191110105641-45db9963cdd3/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0=
|
||||
github.com/jmoiron/sqlx v1.2.1-0.20190826204134-d7d95172beb5/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb h1:RHba4YImhrUVQDHUCe2BNSOz4tVy2yGyXhvYDvxGgeE=
|
||||
github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s=
|
||||
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk=
|
||||
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d h1:AREM5mwr4u1ORQBMvzfzBgpsctsbQikCVpvC+tX285E=
|
||||
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
|
||||
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 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
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/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=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/securego/gosec v0.0.0-20200103095621-79fbf3af8d83 h1:AtnWoOvTioyDXFvu96MWEeE8qj4COSQnJogzLy/u41A=
|
||||
github.com/securego/gosec v0.0.0-20200103095621-79fbf3af8d83/go.mod h1:vvbZ2Ae7AzSq3/kywjUDxSNq2SJ27RxCz2un0H3ePqE=
|
||||
github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc=
|
||||
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
|
||||
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
|
||||
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/sourcegraph/go-diff v0.5.1 h1:gO6i5zugwzo1RVTvgvfwCOSVegNuvnNi6bAD1QCmkHs=
|
||||
github.com/sourcegraph/go-diff v0.5.1/go.mod h1:j2dHj3m8aZgQO8lMTcTnBcXkRRRqi34cd2MNlA9u1mE=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s=
|
||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||
github.com/spf13/viper v1.6.1 h1:VPZzIkznI1YhVMRi6vNFLHSwhnhReBfgTxIPccpfdZk=
|
||||
github.com/spf13/viper v1.6.1/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e h1:RumXZ56IrCj4CL+g1b9OL/oH0QnsF976bC8xQFYUD5Q=
|
||||
github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tommy-muehle/go-mnd v1.1.1 h1:4D0wuPKjOTiK2garzuPGGvm4zZ/wLYDOH8TJSABC7KU=
|
||||
github.com/tommy-muehle/go-mnd v1.1.1/go.mod h1:dSUh0FtTP8VhvkL1S+gUR1OKd9ZnSaozuI6r3m6wOig=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/ultraware/funlen v0.0.2 h1:Av96YVBwwNSe4MLR7iI/BIa3VyI7/djnto/pK3Uxbdo=
|
||||
github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA=
|
||||
github.com/ultraware/whitespace v0.0.4 h1:If7Va4cM03mpgrNH9k49/VOicWpGoG70XPBFFODYDsg=
|
||||
github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA=
|
||||
github.com/uudashr/gocognit v1.0.1 h1:MoG2fZ0b/Eo7NXoIwCVFLG5JED3qgQz5/NEE+rOsjPs=
|
||||
github.com/uudashr/gocognit v1.0.1/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s=
|
||||
github.com/valyala/quicktemplate v1.2.0/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4=
|
||||
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69 h1:rOhMmluY6kLMhdnrivzec6lLgaVbMHMn2ISQXJeJ5EM=
|
||||
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190221204921-83362c3779f5/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190719005602-e377ae9d6386/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
|
||||
golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191113232020-e2727e816f5a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200102140908-9497f49d5709/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200204192400-7124308813f3 h1:Ms82wn6YK4ZycO6Bxyh0kxX3gFFVGo79CCuc52xgcys=
|
||||
golang.org/x/tools v0.0.0-20200204192400-7124308813f3/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
|
||||
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
|
||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I=
|
||||
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc=
|
||||
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo=
|
||||
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=
|
||||
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4 h1:JPJh2pk3+X4lXAkZIk2RuE/7/FoK9maXw+TNPJhVS/c=
|
||||
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=
|
||||
56
kyaml/comments/comments.go
Normal file
56
kyaml/comments/comments.go
Normal file
@@ -0,0 +1,56 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package comments
|
||||
|
||||
import (
|
||||
"sigs.k8s.io/kustomize/kyaml/openapi"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml/walk"
|
||||
)
|
||||
|
||||
// CopyComments recursively copies the comments on fields in from to fields in to
|
||||
func CopyComments(from, to *yaml.RNode) error {
|
||||
// walk the fields copying comments
|
||||
_, err := walk.Walker{
|
||||
Sources: []*yaml.RNode{from, to},
|
||||
Visitor: &copier{},
|
||||
VisitKeysAsScalars: true}.Walk()
|
||||
return err
|
||||
}
|
||||
|
||||
// copier implements walk.Visitor, and copies comments to fields shared between 2 instances
|
||||
// of a resource
|
||||
type copier struct{}
|
||||
|
||||
func (c *copier) VisitMap(s walk.Sources, _ *openapi.ResourceSchema) (*yaml.RNode, error) {
|
||||
copy(s.Dest(), s.Origin())
|
||||
return s.Dest(), nil
|
||||
}
|
||||
|
||||
func (c *copier) VisitScalar(s walk.Sources, _ *openapi.ResourceSchema) (*yaml.RNode, error) {
|
||||
copy(s.Dest(), s.Origin())
|
||||
return s.Dest(), nil
|
||||
}
|
||||
|
||||
func (c *copier) VisitList(s walk.Sources, _ *openapi.ResourceSchema, _ walk.ListKind) (
|
||||
*yaml.RNode, error) {
|
||||
copy(s.Dest(), s.Origin())
|
||||
return s.Dest(), nil
|
||||
}
|
||||
|
||||
// copy copies the comment from one field to another
|
||||
func copy(from, to *yaml.RNode) {
|
||||
if from == nil || to == nil {
|
||||
return
|
||||
}
|
||||
if from.YNode().LineComment != "" {
|
||||
to.YNode().LineComment = from.YNode().LineComment
|
||||
}
|
||||
if from.YNode().HeadComment != "" {
|
||||
to.YNode().HeadComment = from.YNode().HeadComment
|
||||
}
|
||||
if from.YNode().FootComment != "" {
|
||||
to.YNode().FootComment = from.YNode().FootComment
|
||||
}
|
||||
}
|
||||
@@ -140,11 +140,11 @@ func (it FieldValueType) Validate(value string) error {
|
||||
func (it FieldValueType) Tag() string {
|
||||
switch it {
|
||||
case String:
|
||||
return "!!str"
|
||||
return yaml.StringTag
|
||||
case Bool:
|
||||
return "!!bool"
|
||||
return yaml.BoolTag
|
||||
case Int:
|
||||
return "!!int"
|
||||
return yaml.IntTag
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -152,17 +152,17 @@ func (it FieldValueType) Tag() string {
|
||||
func (it FieldValueType) TagForValue(value string) string {
|
||||
switch it {
|
||||
case String:
|
||||
return "!!str"
|
||||
return yaml.StringTag
|
||||
case Bool:
|
||||
if _, err := strconv.ParseBool(string(it)); err != nil {
|
||||
return ""
|
||||
}
|
||||
return "!!bool"
|
||||
return yaml.BoolTag
|
||||
case Int:
|
||||
if _, err := strconv.ParseInt(string(it), 0, 32); err != nil {
|
||||
return ""
|
||||
}
|
||||
return "!!int"
|
||||
return yaml.IntTag
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -6,9 +6,11 @@ require (
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/go-errors/errors v1.0.1
|
||||
github.com/go-openapi/spec v0.19.5
|
||||
github.com/qri-io/starlib v0.4.2-0.20200213133954-ff2e8cd5ef8d
|
||||
github.com/sergi/go-diff v1.1.0
|
||||
github.com/stretchr/testify v1.4.0
|
||||
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca
|
||||
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5
|
||||
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 // indirect
|
||||
gopkg.in/yaml.v2 v2.2.7
|
||||
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2
|
||||
|
||||
25
kyaml/go.sum
25
kyaml/go.sum
@@ -1,10 +1,21 @@
|
||||
github.com/360EntSecGroup-Skylar/excelize v1.4.1 h1:l55mJb6rkkaUzOpSsgEeKYtS6/0gHwBYyfo5Jcjv/Ks=
|
||||
github.com/360EntSecGroup-Skylar/excelize v1.4.1/go.mod h1:vnax29X2usfl7HHkBrX5EvSCJcmH3dT9luvxzu8iGAE=
|
||||
github.com/PuerkitoBio/goquery v1.5.0 h1:uGvmFXOA73IKluu/F84Xd1tt/z07GYm8X49XKHP7EJk=
|
||||
github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg=
|
||||
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/andybalholm/cascadia v1.0.0 h1:hOCXnnZ5A+3eVDX8pvgl4kofXv2ELss0bKcqRySc45o=
|
||||
github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dustmop/soup v1.1.2-0.20190516214245-38228baa104e h1:44fmjqDtdCiUNlSjJVp+w1AOs6na3Y6Ai0aIeseFjkI=
|
||||
github.com/dustmop/soup v1.1.2-0.20190516214245-38228baa104e/go.mod h1:CgNC6SGbT+Xb8wGGvzilttZL1mc5sQ/5KkcxsZttMIk=
|
||||
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
|
||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
|
||||
@@ -25,23 +36,37 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8=
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
||||
github.com/paulmach/orb v0.1.3 h1:Wa1nzU269Zv7V9paVEY1COWW8FCqv4PC/KJRbJSimpM=
|
||||
github.com/paulmach/orb v0.1.3/go.mod h1:VFlX/8C+IQ1p6FTRRKzKoOPJnvEtA5G0Veuqwbu//Vk=
|
||||
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/qri-io/starlib v0.4.2-0.20200213133954-ff2e8cd5ef8d h1:K6eOUihrFLdZjZnA4XlRp864fmWXv9YTIk7VPLhRacA=
|
||||
github.com/qri-io/starlib v0.4.2-0.20200213133954-ff2e8cd5ef8d/go.mod h1:7DPO4domFU579Ga6E61sB9VFNaniPVwJP5C4bBCu3wA=
|
||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.3-0.20181224173747-660f15d67dbb/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI=
|
||||
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
|
||||
go.starlark.net v0.0.0-20190528202925-30ae18b8564f/go.mod h1:c1/X6cHgvdXj6pUlmWKMkuqRnW4K8x2vwt6JAaaircg=
|
||||
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 h1:+FNtrFTmVw0YZGpBGX56XDee331t6JAXeK2bcyhLOOc=
|
||||
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM=
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI=
|
||||
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
|
||||
@@ -210,6 +210,10 @@ func (rs *ResourceSchema) Elements() *ResourceSchema {
|
||||
// either not an array, or array has multiple types
|
||||
return nil
|
||||
}
|
||||
if rs == nil || rs.Schema == nil || rs.Schema.Items == nil {
|
||||
// no-scheme for the items
|
||||
return nil
|
||||
}
|
||||
s := *rs.Schema.Items.Schema
|
||||
for s.Ref.String() != "" {
|
||||
sc, e := Resolve(&s.Ref)
|
||||
|
||||
@@ -43,9 +43,14 @@ func (a *Add) Filter(object *yaml.RNode) (*yaml.RNode, error) {
|
||||
return object, accept(a, object)
|
||||
}
|
||||
|
||||
func (a *Add) visitSequence(_ *yaml.RNode, _ string, _ *openapi.ResourceSchema) error {
|
||||
// no-op
|
||||
return nil
|
||||
}
|
||||
|
||||
// visitScalar implements visitor
|
||||
// visitScalar will set the field metadata on each scalar field whose name + value match
|
||||
func (a *Add) visitScalar(object *yaml.RNode, p string) error {
|
||||
func (a *Add) visitScalar(object *yaml.RNode, p string, _ *openapi.ResourceSchema) error {
|
||||
// check if the field matches
|
||||
if a.FieldName != "" && !strings.HasSuffix(p, a.FieldName) {
|
||||
return nil
|
||||
@@ -96,6 +101,9 @@ type SetterDefinition struct {
|
||||
// Value is the value of the setter.
|
||||
Value string `yaml:"value"`
|
||||
|
||||
// ListValues are the value of a list setter.
|
||||
ListValues []string `yaml:"listValues,omitempty"`
|
||||
|
||||
// SetBy is the person or role that last set the value.
|
||||
SetBy string `yaml:"setBy,omitempty"`
|
||||
|
||||
|
||||
@@ -8,7 +8,10 @@ import (
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio/kioutil"
|
||||
"sigs.k8s.io/kustomize/kyaml/openapi"
|
||||
"sigs.k8s.io/kustomize/kyaml/sets"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
|
||||
@@ -27,10 +30,36 @@ func (s *Set) Filter(object *yaml.RNode) (*yaml.RNode, error) {
|
||||
return object, accept(s, object)
|
||||
}
|
||||
|
||||
// visitSequence will perform setters for sequences
|
||||
func (s *Set) visitSequence(object *yaml.RNode, p string, schema *openapi.ResourceSchema) error {
|
||||
ext, err := getExtFromComment(schema)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ext == nil || ext.Setter == nil || ext.Setter.Name != s.Name ||
|
||||
len(ext.Setter.ListValues) == 0 {
|
||||
// setter was not invoked for this sequence
|
||||
return nil
|
||||
}
|
||||
s.Count++
|
||||
|
||||
// set the values on the sequences
|
||||
var elements []*yaml.Node
|
||||
for i := range ext.Setter.ListValues {
|
||||
v := ext.Setter.ListValues[i]
|
||||
n := yaml.NewScalarRNode(v).YNode()
|
||||
n.Style = yaml.DoubleQuotedStyle
|
||||
elements = append(elements, n)
|
||||
}
|
||||
object.YNode().Content = elements
|
||||
object.YNode().Style = yaml.FoldedStyle
|
||||
return nil
|
||||
}
|
||||
|
||||
// visitScalar
|
||||
func (s *Set) visitScalar(object *yaml.RNode, p string) error {
|
||||
func (s *Set) visitScalar(object *yaml.RNode, p string, schema *openapi.ResourceSchema) error {
|
||||
// get the openAPI for this field describing how to apply the setter
|
||||
ext, sch, err := getExtFromComment(object)
|
||||
ext, err := getExtFromComment(schema)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -39,13 +68,13 @@ func (s *Set) visitScalar(object *yaml.RNode, p string) error {
|
||||
}
|
||||
|
||||
// perform a direct set of the field if it matches
|
||||
if s.set(object, ext, sch) {
|
||||
if s.set(object, ext, schema.Schema) {
|
||||
s.Count++
|
||||
return nil
|
||||
}
|
||||
|
||||
// perform a substitution of the field if it matches
|
||||
sub, err := s.substitute(object, ext, sch)
|
||||
sub, err := s.substitute(object, ext, schema.Schema)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -111,7 +140,7 @@ func (s *Set) substitute(field *yaml.RNode, ext *cliExtension, _ *spec.Schema) (
|
||||
field.YNode().Value = p
|
||||
|
||||
// substitutions are always strings
|
||||
field.YNode().Tag = "!!str"
|
||||
field.YNode().Tag = yaml.StringTag
|
||||
|
||||
return true, nil
|
||||
}
|
||||
@@ -147,6 +176,9 @@ type SetOpenAPI struct {
|
||||
// Value is the current value of the setter
|
||||
Value string `yaml:"value"`
|
||||
|
||||
// ListValue is the current value for a list of items
|
||||
ListValues []string `yaml:"listValue"`
|
||||
|
||||
Description string `yaml:"description"`
|
||||
|
||||
SetBy string `yaml:"setBy"`
|
||||
@@ -159,8 +191,14 @@ func (s SetOpenAPI) UpdateFile(path string) error {
|
||||
|
||||
func (s SetOpenAPI) Filter(object *yaml.RNode) (*yaml.RNode, error) {
|
||||
key := SetterDefinitionPrefix + s.Name
|
||||
def, err := object.Pipe(yaml.Lookup(
|
||||
"openAPI", "definitions", key, "x-k8s-cli", "setter"))
|
||||
oa, err := object.Pipe(yaml.Lookup("openAPI", "definitions", key))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if oa == nil {
|
||||
return nil, errors.Errorf("no setter %s found", s.Name)
|
||||
}
|
||||
def, err := oa.Pipe(yaml.Lookup("x-k8s-cli", "setter"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -168,9 +206,16 @@ func (s SetOpenAPI) Filter(object *yaml.RNode) (*yaml.RNode, error) {
|
||||
return nil, errors.Errorf("no setter %s found", s.Name)
|
||||
}
|
||||
|
||||
// record the OpenAPI type for the setter
|
||||
var t string
|
||||
if n := oa.Field("type"); n != nil {
|
||||
t = n.Value.YNode().Value
|
||||
}
|
||||
|
||||
// if the setter contains an enumValues map, then ensure the set value appears
|
||||
// as a key in the map
|
||||
if values, err := def.Pipe(yaml.Lookup("enumValues")); err != nil {
|
||||
if values, err := def.Pipe(
|
||||
yaml.Lookup("enumValues")); err != nil {
|
||||
// error looking up the enumValues
|
||||
return nil, err
|
||||
} else if values != nil {
|
||||
@@ -202,11 +247,40 @@ func (s SetOpenAPI) Filter(object *yaml.RNode) (*yaml.RNode, error) {
|
||||
// values are always represented as strings the OpenAPI
|
||||
// since the are unmarshalled into strings. Use double quote style to
|
||||
// ensure this consistently.
|
||||
v.YNode().Tag = "!!str"
|
||||
v.YNode().Tag = yaml.StringTag
|
||||
v.YNode().Style = yaml.DoubleQuotedStyle
|
||||
|
||||
if err := def.PipeE(&yaml.FieldSetter{Name: "value", Value: v}); err != nil {
|
||||
return nil, err
|
||||
if t != "array" {
|
||||
// set a scalar value
|
||||
if err := def.PipeE(&yaml.FieldSetter{Name: "value", Value: v}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
// set a list value
|
||||
if err := def.PipeE(&yaml.FieldClearer{Name: "value"}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// create the list values
|
||||
var elements []*yaml.Node
|
||||
n := yaml.NewScalarRNode(s.Value).YNode()
|
||||
n.Tag = yaml.StringTag
|
||||
n.Style = yaml.DoubleQuotedStyle
|
||||
elements = append(elements, n)
|
||||
for i := range s.ListValues {
|
||||
v := s.ListValues[i]
|
||||
n := yaml.NewScalarRNode(v).YNode()
|
||||
n.Style = yaml.DoubleQuotedStyle
|
||||
elements = append(elements, n)
|
||||
}
|
||||
l := yaml.NewRNode(&yaml.Node{
|
||||
Kind: yaml.SequenceNode,
|
||||
Content: elements,
|
||||
})
|
||||
|
||||
def.YNode().Style = yaml.FoldedStyle
|
||||
if err := def.PipeE(&yaml.FieldSetter{Name: "listValues", Value: l}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if err := def.PipeE(&yaml.FieldSetter{Name: "setBy", StringValue: s.SetBy}); err != nil {
|
||||
@@ -226,3 +300,39 @@ func (s SetOpenAPI) Filter(object *yaml.RNode) (*yaml.RNode, error) {
|
||||
|
||||
return object, nil
|
||||
}
|
||||
|
||||
// SetAll applies the set filter for all yaml nodes and only returns the nodes whose
|
||||
// corresponding file has at least one node with input setter
|
||||
func SetAll(s *Set) kio.Filter {
|
||||
return kio.FilterFunc(func(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
|
||||
filesToUpdate := sets.String{}
|
||||
// for each node record the set fields count before and after filter is applied and
|
||||
// store the corresponding file paths if there is an increment in setters count
|
||||
for i := range nodes {
|
||||
preCount := s.Count
|
||||
_, err := s.Filter(nodes[i])
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
if s.Count > preCount {
|
||||
path, _, err := kioutil.GetFileAnnotations(nodes[i])
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
filesToUpdate.Insert(path)
|
||||
}
|
||||
}
|
||||
var nodesInUpdatedFiles []*yaml.RNode
|
||||
// return only the nodes whose corresponding file has at least one node with input setter
|
||||
for i := range nodes {
|
||||
path, _, err := kioutil.GetFileAnnotations(nodes[i])
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
if filesToUpdate.Has(path) {
|
||||
nodesInUpdatedFiles = append(nodesInUpdatedFiles, nodes[i])
|
||||
}
|
||||
}
|
||||
return nodesInUpdatedFiles, nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -595,6 +595,76 @@ spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.8.1 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image"}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "set-args-list",
|
||||
setter: "args",
|
||||
openapi: `
|
||||
openAPI:
|
||||
definitions:
|
||||
io.k8s.cli.setters.args:
|
||||
x-k8s-cli:
|
||||
type: array
|
||||
setter:
|
||||
name: args
|
||||
listValues: ["1", "2", "3"]
|
||||
`,
|
||||
input: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
spec:
|
||||
# {"$ref": "#/definitions/io.k8s.cli.setters.args"}
|
||||
replicas: []
|
||||
`,
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
spec:
|
||||
# {"$ref": "#/definitions/io.k8s.cli.setters.args"}
|
||||
replicas:
|
||||
- "1"
|
||||
- "2"
|
||||
- "3"
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "set-args-list-replace",
|
||||
setter: "args",
|
||||
openapi: `
|
||||
openAPI:
|
||||
definitions:
|
||||
io.k8s.cli.setters.args:
|
||||
x-k8s-cli:
|
||||
type: array
|
||||
setter:
|
||||
name: args
|
||||
listValues: ["1", "2", "3"]
|
||||
`,
|
||||
input: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
spec:
|
||||
# {"$ref": "#/definitions/io.k8s.cli.setters.args"}
|
||||
replicas: ["4", "5"]
|
||||
`,
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
spec:
|
||||
# {"$ref": "#/definitions/io.k8s.cli.setters.args"}
|
||||
replicas:
|
||||
- "1"
|
||||
- "2"
|
||||
- "3"
|
||||
`,
|
||||
},
|
||||
}
|
||||
@@ -632,6 +702,160 @@ spec:
|
||||
}
|
||||
}
|
||||
|
||||
func TestSet_SetAll(t *testing.T) {
|
||||
var tests = []struct {
|
||||
name string
|
||||
description string
|
||||
setter string
|
||||
openapi string
|
||||
input []string
|
||||
expected []string
|
||||
}{
|
||||
{
|
||||
name: "set-replicas-same-file",
|
||||
setter: "replicas",
|
||||
openapi: `
|
||||
openAPI:
|
||||
definitions:
|
||||
io.k8s.cli.setters.replicas:
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: replicas
|
||||
value: "4"
|
||||
`,
|
||||
input: []string{`
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
annotations:
|
||||
config.kubernetes.io/index: '0'
|
||||
config.kubernetes.io/path: 'cluster.yaml'
|
||||
spec:
|
||||
replicas: 3 # {"$ref": "#/definitions/io.k8s.cli.setters.replicas"}
|
||||
`, `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment2
|
||||
annotations:
|
||||
config.kubernetes.io/index: '1'
|
||||
config.kubernetes.io/path: 'cluster.yaml'
|
||||
spec:
|
||||
replicas: 10
|
||||
`},
|
||||
expected: []string{`
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
annotations:
|
||||
config.kubernetes.io/index: '0'
|
||||
config.kubernetes.io/path: 'cluster.yaml'
|
||||
spec:
|
||||
replicas: 4 # {"$ref": "#/definitions/io.k8s.cli.setters.replicas"}
|
||||
`, `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment2
|
||||
annotations:
|
||||
config.kubernetes.io/index: '1'
|
||||
config.kubernetes.io/path: 'cluster.yaml'
|
||||
spec:
|
||||
replicas: 10
|
||||
`},
|
||||
},
|
||||
{
|
||||
name: "set-replicas-different-file",
|
||||
setter: "replicas",
|
||||
openapi: `
|
||||
openAPI:
|
||||
definitions:
|
||||
io.k8s.cli.setters.replicas:
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: replicas
|
||||
value: "4"
|
||||
`,
|
||||
input: []string{`
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
annotations:
|
||||
config.kubernetes.io/index: '0'
|
||||
config.kubernetes.io/path: 'cluster.yaml'
|
||||
spec:
|
||||
replicas: 3 # {"$ref": "#/definitions/io.k8s.cli.setters.replicas"}
|
||||
`, `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment2
|
||||
annotations:
|
||||
config.kubernetes.io/index: '1'
|
||||
config.kubernetes.io/path: 'another_cluster.yaml'
|
||||
spec:
|
||||
replicas: 10
|
||||
`},
|
||||
expected: []string{`
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
annotations:
|
||||
config.kubernetes.io/index: '0'
|
||||
config.kubernetes.io/path: 'cluster.yaml'
|
||||
spec:
|
||||
replicas: 4 # {"$ref": "#/definitions/io.k8s.cli.setters.replicas"}
|
||||
`},
|
||||
},
|
||||
}
|
||||
for i := range tests {
|
||||
test := tests[i]
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
// reset the openAPI afterward
|
||||
defer openapi.ResetOpenAPI()
|
||||
initSchema(t, test.openapi)
|
||||
|
||||
// parse the input to be modified
|
||||
var inputNodes []*yaml.RNode
|
||||
for _, s := range test.input {
|
||||
r, err := yaml.Parse(s)
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
inputNodes = append(inputNodes, r)
|
||||
}
|
||||
|
||||
// invoke the setter
|
||||
instance := &Set{Name: test.setter}
|
||||
result, err := SetAll(instance).Filter(inputNodes)
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// compare the actual and expected output
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
if !assert.Equal(t, len(result), len(test.expected)) {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
for i := range result {
|
||||
actual, _ := result[i].String()
|
||||
actual = strings.TrimSpace(actual)
|
||||
expected := strings.TrimSpace(test.expected[i])
|
||||
if !assert.Equal(t, expected, actual) {
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// initSchema initializes the openAPI with the definitions from s
|
||||
func initSchema(t *testing.T, s string) {
|
||||
// parse out the schema from the input openAPI
|
||||
@@ -678,6 +902,7 @@ func TestSetOpenAPI_Filter(t *testing.T) {
|
||||
name string
|
||||
setter string
|
||||
value string
|
||||
values []string
|
||||
input string
|
||||
expected string
|
||||
description string
|
||||
@@ -1004,6 +1229,33 @@ openAPI:
|
||||
value: "2"
|
||||
`,
|
||||
},
|
||||
|
||||
{
|
||||
name: "set-args-list",
|
||||
setter: "args",
|
||||
value: "2",
|
||||
values: []string{"3", "4"},
|
||||
input: `
|
||||
openAPI:
|
||||
definitions:
|
||||
io.k8s.cli.setters.args:
|
||||
type: array
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: args
|
||||
listValues: ["1"]
|
||||
`,
|
||||
expected: `
|
||||
openAPI:
|
||||
definitions:
|
||||
io.k8s.cli.setters.args:
|
||||
type: array
|
||||
x-k8s-cli:
|
||||
setter:
|
||||
name: args
|
||||
listValues: ["2", "3", "4"]
|
||||
`,
|
||||
},
|
||||
}
|
||||
for i := range tests {
|
||||
test := tests[i]
|
||||
@@ -1015,7 +1267,7 @@ openAPI:
|
||||
|
||||
// invoke the setter
|
||||
instance := &SetOpenAPI{
|
||||
Name: test.setter, Value: test.value,
|
||||
Name: test.setter, Value: test.value, ListValues: test.values,
|
||||
SetBy: test.setBy, Description: test.description}
|
||||
result, err := instance.Filter(in)
|
||||
if test.err != "" {
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
"sigs.k8s.io/kustomize/kyaml/openapi"
|
||||
"sigs.k8s.io/kustomize/kyaml/setters2"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
|
||||
// FieldSetter sets the value for a field setter.
|
||||
@@ -17,16 +18,35 @@ type FieldSetter struct {
|
||||
// Value is the value to set
|
||||
Value string
|
||||
|
||||
// ListValues contains a list of values to set on a Sequence
|
||||
ListValues []string
|
||||
|
||||
Description string
|
||||
|
||||
SetBy string
|
||||
|
||||
Count int
|
||||
|
||||
OpenAPIPath string
|
||||
|
||||
ResourcesPath string
|
||||
}
|
||||
|
||||
func (fs *FieldSetter) Filter(input []*yaml.RNode) ([]*yaml.RNode, error) {
|
||||
fs.Count, _ = fs.Set(fs.OpenAPIPath, fs.ResourcesPath)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Set updates the OpenAPI definitions and resources with the new setter value
|
||||
func (fs FieldSetter) Set(openAPIPath, resourcesPath string) (int, error) {
|
||||
// Update the OpenAPI definitions
|
||||
soa := setters2.SetOpenAPI{
|
||||
Name: fs.Name, Value: fs.Value, Description: fs.Description, SetBy: fs.SetBy}
|
||||
Name: fs.Name,
|
||||
Value: fs.Value,
|
||||
ListValues: fs.ListValues,
|
||||
Description: fs.Description,
|
||||
SetBy: fs.SetBy,
|
||||
}
|
||||
if err := soa.UpdateFile(openAPIPath); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -37,11 +57,13 @@ func (fs FieldSetter) Set(openAPIPath, resourcesPath string) (int, error) {
|
||||
}
|
||||
|
||||
// Update the resources with the new value
|
||||
inout := &kio.LocalPackageReadWriter{PackagePath: resourcesPath}
|
||||
// Set NoDeleteFiles to true as SetAll will return only the nodes of files which should be updated and
|
||||
// hence, rest of the files should not be deleted
|
||||
inout := &kio.LocalPackageReadWriter{PackagePath: resourcesPath, NoDeleteFiles: true}
|
||||
s := &setters2.Set{Name: fs.Name}
|
||||
err := kio.Pipeline{
|
||||
Inputs: []kio.Reader{inout},
|
||||
Filters: []kio.Filter{kio.FilterAll(s)},
|
||||
Filters: []kio.Filter{setters2.SetAll(s)},
|
||||
Outputs: []kio.Writer{inout},
|
||||
}.Execute()
|
||||
return s.Count, err
|
||||
|
||||
@@ -8,9 +8,7 @@ import (
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
|
||||
"sigs.k8s.io/kustomize/kyaml/openapi"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
|
||||
type cliExtension struct {
|
||||
@@ -21,6 +19,7 @@ type cliExtension struct {
|
||||
type setter struct {
|
||||
Name string `yaml:"name,omitempty" json:"name,omitempty"`
|
||||
Value string `yaml:"value,omitempty" json:"value,omitempty"`
|
||||
ListValues []string `yaml:"listValues,omitempty" json:"listValues,omitempty"`
|
||||
EnumValues map[string]string `yaml:"enumValues,omitempty" json:"enumValues,omitempty"`
|
||||
}
|
||||
|
||||
@@ -57,32 +56,17 @@ func getExtFromSchema(schema *spec.Schema) (*cliExtension, error) {
|
||||
|
||||
// getExtFromComment returns the cliExtension openAPI extension if it is present as
|
||||
// a comment on the field.
|
||||
func getExtFromComment(object *yaml.RNode) (*cliExtension, *spec.Schema, error) {
|
||||
// TODO(pwittrock): also use path to the field to get openapi, not just comments
|
||||
// parse comment containing the extended openapi for this field
|
||||
fm := fieldmeta.FieldMeta{}
|
||||
if err := fm.Read(object); err != nil {
|
||||
return nil, nil, errors.Wrap(err)
|
||||
}
|
||||
if fm.Schema.Ref.String() == "" {
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
// resolve the comment reference to the extended openapi definitions
|
||||
r, err := openapi.Resolve(&fm.Schema.Ref)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err)
|
||||
}
|
||||
if r == nil {
|
||||
func getExtFromComment(schema *openapi.ResourceSchema) (*cliExtension, error) {
|
||||
if schema == nil {
|
||||
// no schema found
|
||||
// TODO(pwittrock): should this be an error if it doesn't resolve?
|
||||
return nil, nil, nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// get the cli extension from the openapi (contains setter information)
|
||||
ext, err := getExtFromSchema(r)
|
||||
ext, err := getExtFromSchema(schema.Schema)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err)
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
return ext, r, nil
|
||||
return ext, nil
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
package setters2
|
||||
|
||||
import (
|
||||
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
|
||||
"sigs.k8s.io/kustomize/kyaml/openapi"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
|
||||
@@ -13,33 +15,100 @@ type visitor interface {
|
||||
// visitScalar is called for each scalar field value on a resource
|
||||
// node is the scalar field value
|
||||
// path is the path to the field; path elements are separated by '.'
|
||||
visitScalar(node *yaml.RNode, path string) error
|
||||
// oa is the OpenAPI schema for the field
|
||||
visitScalar(node *yaml.RNode, path string, oa *openapi.ResourceSchema) error
|
||||
|
||||
// visitSequence is called for each sequence field value on a resource
|
||||
// node is the sequence field value
|
||||
// path is the path to the field
|
||||
// oa is the OpenAPI schema for the field
|
||||
visitSequence(node *yaml.RNode, path string, oa *openapi.ResourceSchema) error
|
||||
}
|
||||
|
||||
// accept invokes the appropriate function on v for each field in object
|
||||
func accept(v visitor, object *yaml.RNode) error {
|
||||
return acceptImpl(v, object, "")
|
||||
// get the OpenAPI for the type if it exists
|
||||
oa := getSchema(object, nil, "")
|
||||
return acceptImpl(v, object, "", oa)
|
||||
}
|
||||
|
||||
// acceptImpl implements accept using recursion
|
||||
func acceptImpl(v visitor, object *yaml.RNode, p string) error {
|
||||
func acceptImpl(v visitor, object *yaml.RNode, p string, oa *openapi.ResourceSchema) error {
|
||||
switch object.YNode().Kind {
|
||||
case yaml.DocumentNode:
|
||||
// Traverse the child of the document
|
||||
return accept(v, yaml.NewRNode(object.YNode()))
|
||||
case yaml.MappingNode:
|
||||
return object.VisitFields(func(node *yaml.MapNode) error {
|
||||
// get the schema for the field and propagate it
|
||||
oa = getSchema(node.Key, oa, node.Key.YNode().Value)
|
||||
// Traverse each field value
|
||||
return acceptImpl(v, node.Value, p+"."+node.Key.YNode().Value)
|
||||
return acceptImpl(v, node.Value, p+"."+node.Key.YNode().Value, oa)
|
||||
})
|
||||
case yaml.SequenceNode:
|
||||
// get the schema for the sequence node, use the schema provided if not present
|
||||
// on the field
|
||||
if err := v.visitSequence(object, p, oa); err != nil {
|
||||
return err
|
||||
}
|
||||
// get the schema for the elements
|
||||
oa = getSchema(object, oa, "")
|
||||
return object.VisitElements(func(node *yaml.RNode) error {
|
||||
// Traverse each list element
|
||||
return acceptImpl(v, node, p)
|
||||
return acceptImpl(v, node, p, oa)
|
||||
})
|
||||
case yaml.ScalarNode:
|
||||
// Visit the scalar field
|
||||
return v.visitScalar(object, p)
|
||||
oa = getSchema(object, oa, "")
|
||||
return v.visitScalar(object, p, oa)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// getSchema returns OpenAPI schema for an RNode or field of the
|
||||
// RNode. It will overriding the provide schema with field specific values
|
||||
// if they are found
|
||||
// r is the Node to get the Schema for
|
||||
// s is the provided schema for the field if known
|
||||
// field is the name of the field
|
||||
func getSchema(r *yaml.RNode, s *openapi.ResourceSchema, field string) *openapi.ResourceSchema {
|
||||
// get the override schema if it exists on the field
|
||||
fm := fieldmeta.FieldMeta{}
|
||||
if err := fm.Read(r); err == nil && !fm.IsEmpty() {
|
||||
// per-field schema, this is fine
|
||||
if fm.Schema.Ref.String() != "" {
|
||||
// resolve the reference
|
||||
s, err := openapi.Resolve(&fm.Schema.Ref)
|
||||
if err == nil && s != nil {
|
||||
fm.Schema = *s
|
||||
}
|
||||
}
|
||||
return &openapi.ResourceSchema{Schema: &fm.Schema}
|
||||
}
|
||||
|
||||
// get the schema for a field of the node if the field is provided
|
||||
if s != nil && field != "" {
|
||||
return s.Field(field)
|
||||
}
|
||||
|
||||
// get the schema for the elements if this is a list
|
||||
if s != nil && r.YNode().Kind == yaml.SequenceNode {
|
||||
return s.Elements()
|
||||
}
|
||||
|
||||
// use the provided schema if present
|
||||
if s != nil {
|
||||
return s
|
||||
}
|
||||
|
||||
if yaml.IsEmpty(r) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// lookup the schema for the type
|
||||
m, _ := r.GetMeta()
|
||||
if m.Kind == "" || m.APIVersion == "" {
|
||||
return nil
|
||||
}
|
||||
return openapi.SchemaForResourceType(yaml.TypeMeta{Kind: m.Kind, APIVersion: m.APIVersion})
|
||||
}
|
||||
|
||||
36
kyaml/starlark/doc.go
Normal file
36
kyaml/starlark/doc.go
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package starlark contains a kio.Filter which can be applied to resources to transform
|
||||
// them through starlark program.
|
||||
//
|
||||
// Starlark has become a popular runtime embedding in go programs, especially for Kubernetes
|
||||
// and data processing.
|
||||
// Examples: https://github.com/cruise-automation/isopod, https://qri.io/docs/starlark/starlib,
|
||||
// https://github.com/stripe/skycfg, https://github.com/k14s/ytt
|
||||
//
|
||||
// The resources are provided to the starlark program through the global variable "resourceList".
|
||||
// "resourceList" is a dictionary containing an "items" field with a list of resources.
|
||||
// The starlark modified "resourceList" is the Filter output.
|
||||
//
|
||||
// After being run through the starlark program, the filter will copy the comments from the input
|
||||
// resources to restore them -- due to them being dropped as a result of serializing the resources
|
||||
// as starlark values.
|
||||
//
|
||||
// "resourceList" may also contain a "functionConfig" entry to configure the starlark script itself.
|
||||
// Changes made by the starlark program to the "functionConfig" will be reflected in the
|
||||
// Filter.FunctionConfig value.
|
||||
//
|
||||
// The Filter will also format the output so that output has the preferred field ordering
|
||||
// rather than an alphabetical field ordering.
|
||||
//
|
||||
// The resourceList variable adheres to the kustomize function spec as specified by:
|
||||
// https://github.com/kubernetes-sigs/kustomize/blob/master/cmd/config/docs/api-conventions/functions-spec.md
|
||||
//
|
||||
// All items in the resourceList are resources represented as starlark dictionaries/
|
||||
// The items in the resourceList respect the io spec specified by:
|
||||
// https://github.com/kubernetes-sigs/kustomize/blob/master/cmd/config/docs/api-conventions/config-io.md
|
||||
//
|
||||
// The starlark language spec can be found here:
|
||||
// https://github.com/google/starlark-go/blob/master/doc/spec.md
|
||||
package starlark
|
||||
290
kyaml/starlark/example_test.go
Normal file
290
kyaml/starlark/example_test.go
Normal file
@@ -0,0 +1,290 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package starlark_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
"sigs.k8s.io/kustomize/kyaml/starlark"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
|
||||
func ExampleFilter_Filter() {
|
||||
// input contains the items that will provided to the starlark program
|
||||
input := bytes.NewBufferString(`
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deployment-1
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.8.1 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image-1"}
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deployment-2
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.7.9 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image-2"}
|
||||
`)
|
||||
|
||||
// fltr transforms the input using a starlark program
|
||||
fltr := &starlark.Filter{
|
||||
Name: "annotate",
|
||||
Program: `
|
||||
def run(items):
|
||||
for item in items:
|
||||
item["metadata"]["annotations"]["foo"] = "bar"
|
||||
|
||||
run(resourceList["items"])
|
||||
`,
|
||||
}
|
||||
|
||||
// output contains the transformed resources
|
||||
output := &bytes.Buffer{}
|
||||
|
||||
// run the fltr against the inputs using a kio.Pipeline
|
||||
err := kio.Pipeline{
|
||||
Inputs: []kio.Reader{&kio.ByteReader{Reader: input}},
|
||||
Filters: []kio.Filter{fltr},
|
||||
Outputs: []kio.Writer{&kio.ByteWriter{Writer: output}}}.Execute()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println(output.String())
|
||||
|
||||
// Output:
|
||||
// apiVersion: apps/v1
|
||||
// kind: Deployment
|
||||
// metadata:
|
||||
// name: deployment-1
|
||||
// annotations:
|
||||
// foo: bar
|
||||
// spec:
|
||||
// template:
|
||||
// spec:
|
||||
// containers:
|
||||
// - name: nginx
|
||||
// image: nginx:1.8.1 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image-1"}
|
||||
//---
|
||||
// apiVersion: apps/v1
|
||||
// kind: Deployment
|
||||
// metadata:
|
||||
// name: deployment-2
|
||||
// annotations:
|
||||
// foo: bar
|
||||
// spec:
|
||||
// template:
|
||||
// spec:
|
||||
// containers:
|
||||
// - name: nginx
|
||||
// image: nginx:1.7.9 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image-2"}
|
||||
}
|
||||
|
||||
func ExampleFilter_Filter_functionConfig() {
|
||||
// input contains the items that will provided to the starlark program
|
||||
input := bytes.NewBufferString(`
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deployment-1
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.8.1 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image-1"}
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deployment-2
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.7.9 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image-2"}
|
||||
`)
|
||||
|
||||
fc, err := yaml.Parse(`
|
||||
kind: AnnotationSetter
|
||||
spec:
|
||||
value: "hello world"
|
||||
`)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// fltr transforms the input using a starlark program
|
||||
fltr := &starlark.Filter{
|
||||
Name: "annotate",
|
||||
Program: `
|
||||
def run(items, value):
|
||||
for item in items:
|
||||
item["metadata"]["annotations"]["foo"] = value
|
||||
|
||||
run(resourceList["items"], resourceList["functionConfig"]["spec"]["value"])
|
||||
`,
|
||||
FunctionConfig: fc,
|
||||
}
|
||||
|
||||
// output contains the transformed resources
|
||||
output := &bytes.Buffer{}
|
||||
|
||||
// run the fltr against the inputs using a kio.Pipeline
|
||||
err = kio.Pipeline{
|
||||
Inputs: []kio.Reader{&kio.ByteReader{Reader: input}},
|
||||
Filters: []kio.Filter{fltr},
|
||||
Outputs: []kio.Writer{&kio.ByteWriter{Writer: output}}}.Execute()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println(output.String())
|
||||
|
||||
// Output:
|
||||
// apiVersion: apps/v1
|
||||
// kind: Deployment
|
||||
// metadata:
|
||||
// name: deployment-1
|
||||
// annotations:
|
||||
// foo: hello world
|
||||
// spec:
|
||||
// template:
|
||||
// spec:
|
||||
// containers:
|
||||
// - name: nginx
|
||||
// image: nginx:1.8.1 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image-1"}
|
||||
//---
|
||||
// apiVersion: apps/v1
|
||||
// kind: Deployment
|
||||
// metadata:
|
||||
// name: deployment-2
|
||||
// annotations:
|
||||
// foo: hello world
|
||||
// spec:
|
||||
// template:
|
||||
// spec:
|
||||
// containers:
|
||||
// - name: nginx
|
||||
// image: nginx:1.7.9 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image-2"}
|
||||
}
|
||||
|
||||
// ExampleFilter_Filter_file applies a starlark program in a local file to a collection of
|
||||
// resource configuration read from a directory.
|
||||
func ExampleFilter_Filter_file() {
|
||||
// setup the configuration
|
||||
d, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(d)
|
||||
|
||||
err = ioutil.WriteFile(filepath.Join(d, "deploy1.yaml"), []byte(`
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deployment-1
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.8.1 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image-1"}
|
||||
`), 0600)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(filepath.Join(d, "deploy2.yaml"), []byte(`
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deployment-2
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.7.9 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image-2"}
|
||||
`), 0600)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(filepath.Join(d, "annotate.star"), []byte(`
|
||||
def run(items):
|
||||
for item in items:
|
||||
item["metadata"]["annotations"]["foo"] = "bar"
|
||||
|
||||
run(resourceList["items"])
|
||||
`), 0600)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fltr := &starlark.Filter{
|
||||
Name: "annotate",
|
||||
Path: filepath.Join(d, "annotate.star"),
|
||||
}
|
||||
|
||||
// output contains the transformed resources
|
||||
output := &bytes.Buffer{}
|
||||
|
||||
// run the fltr against the inputs using a kio.Pipeline
|
||||
err = kio.Pipeline{
|
||||
Inputs: []kio.Reader{&kio.LocalPackageReader{PackagePath: d}},
|
||||
Filters: []kio.Filter{fltr},
|
||||
Outputs: []kio.Writer{&kio.ByteWriter{
|
||||
Writer: output,
|
||||
ClearAnnotations: []string{"config.kubernetes.io/path"},
|
||||
}}}.Execute()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println(output.String())
|
||||
|
||||
// Output:
|
||||
// apiVersion: apps/v1
|
||||
// kind: Deployment
|
||||
// metadata:
|
||||
// name: deployment-1
|
||||
// annotations:
|
||||
// foo: bar
|
||||
// spec:
|
||||
// template:
|
||||
// spec:
|
||||
// containers:
|
||||
// - name: nginx
|
||||
// image: nginx:1.8.1 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image-1"}
|
||||
//---
|
||||
// apiVersion: apps/v1
|
||||
// kind: Deployment
|
||||
// metadata:
|
||||
// name: deployment-2
|
||||
// annotations:
|
||||
// foo: bar
|
||||
// spec:
|
||||
// template:
|
||||
// spec:
|
||||
// containers:
|
||||
// - name: nginx
|
||||
// image: nginx:1.7.9 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image-2"}
|
||||
}
|
||||
251
kyaml/starlark/starlark.go
Normal file
251
kyaml/starlark/starlark.go
Normal file
@@ -0,0 +1,251 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package starlark
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/qri-io/starlib/util"
|
||||
"go.starlark.net/starlark"
|
||||
"sigs.k8s.io/kustomize/kyaml/comments"
|
||||
"sigs.k8s.io/kustomize/kyaml/errors"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio/filters"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
|
||||
// Filter transforms a set of resources through the provided program
|
||||
type Filter struct {
|
||||
Name string
|
||||
|
||||
// Program is a starlark script which will be run against the resources
|
||||
Program string
|
||||
|
||||
// URL is the url of a starlark program to fetch and run
|
||||
URL string
|
||||
|
||||
// Path is the path to a starlark program to read and run
|
||||
Path string
|
||||
|
||||
// FunctionConfig is the value to be provided for resourceList.functionConfig as specified by
|
||||
// https://github.com/kubernetes-sigs/kustomize/blob/master/cmd/config/docs/api-conventions/functions-spec.md.
|
||||
FunctionConfig *yaml.RNode
|
||||
}
|
||||
|
||||
func (sf *Filter) Filter(input []*yaml.RNode) ([]*yaml.RNode, error) {
|
||||
if sf.URL != "" && sf.Path != "" ||
|
||||
sf.URL != "" && sf.Program != "" ||
|
||||
sf.Path != "" && sf.Program != "" {
|
||||
return nil, errors.Errorf("Filter Path, Program and URL are mutually exclusive")
|
||||
}
|
||||
|
||||
// read the program from a file
|
||||
if sf.Path != "" {
|
||||
b, err := ioutil.ReadFile(sf.Path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sf.Program = string(b)
|
||||
}
|
||||
|
||||
// read the program from a URL
|
||||
if sf.URL != "" {
|
||||
err := func() error {
|
||||
resp, err := http.Get(sf.URL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
b, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sf.Program = string(b)
|
||||
return nil
|
||||
}()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// retain map of inputs to outputs by id so if the name is changed by the
|
||||
// starlark program, we are able to match the same resources
|
||||
value, ids, err := sf.inputToResourceList(input)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
|
||||
// run the starlark as program as transformation function
|
||||
thread := &starlark.Thread{Name: sf.Name}
|
||||
predeclared := starlark.StringDict{"resourceList": value}
|
||||
_, err = starlark.ExecFile(thread, sf.Name, sf.Program, predeclared)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
|
||||
results, err := sf.resourceListToOutput(value, ids)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
|
||||
// starlark will serialize the resources sorting the fields alphabetically,
|
||||
// format them to have a better ordering
|
||||
return filters.FormatFilter{}.Filter(results)
|
||||
}
|
||||
|
||||
// tuple maps an input resource to the output resource
|
||||
type tuple struct {
|
||||
// in is the RNode provided to the starlark program
|
||||
in *yaml.RNode
|
||||
// out is the RNode emitted by the starlark program with the id matching in
|
||||
out *yaml.RNode
|
||||
}
|
||||
|
||||
// inputToResourceList transforms input into a starlark.Value
|
||||
func (sf *Filter) inputToResourceList(
|
||||
input []*yaml.RNode) (starlark.Value, map[int]*tuple, error) {
|
||||
var id int
|
||||
ids := map[int]*tuple{}
|
||||
|
||||
// convert into a ResourceList which will be converted to a starlark dictionary
|
||||
// create the ResourceList
|
||||
resourceList, err := yaml.Parse(`kind: ResourceList`)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err)
|
||||
}
|
||||
|
||||
// set the functionConfig
|
||||
if sf.FunctionConfig != nil {
|
||||
if err := resourceList.PipeE(
|
||||
yaml.FieldSetter{Name: "functionConfig", Value: sf.FunctionConfig}); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// the inputs should be provided as the list "items"
|
||||
items, err := resourceList.Pipe(yaml.LookupCreate(yaml.SequenceNode, "items"))
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err)
|
||||
}
|
||||
// add the input as items, give each resource an id
|
||||
for i := range input {
|
||||
item := input[i]
|
||||
|
||||
// create an id for tracking the resource through the program
|
||||
err := item.PipeE(yaml.SetAnnotation("config.k8s.io/id", fmt.Sprintf("%d", id)))
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err)
|
||||
}
|
||||
ids[id] = &tuple{in: item}
|
||||
id++
|
||||
|
||||
items.YNode().Content = append(items.YNode().Content, item.YNode())
|
||||
}
|
||||
|
||||
// convert the ResourceList into a starlark dictionary by
|
||||
// first converting it into a map[string]interface{}
|
||||
s, err := resourceList.String()
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err)
|
||||
}
|
||||
var in map[string]interface{}
|
||||
if err := yaml.Unmarshal([]byte(s), &in); err != nil {
|
||||
return nil, nil, errors.Wrap(err)
|
||||
}
|
||||
value, err := util.Marshal(in)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err)
|
||||
}
|
||||
return value, ids, err
|
||||
}
|
||||
|
||||
// resourceListToOutput converts the output of the starlark program to the filter output
|
||||
func (sf *Filter) resourceListToOutput(
|
||||
value starlark.Value, ids map[int]*tuple) ([]*yaml.RNode, error) {
|
||||
// convert the modified resourceList back into a slice of RNodes
|
||||
// by first converting to a map[string]interface{}
|
||||
out, err := util.Unmarshal(value)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
o := out.(map[string]interface{})
|
||||
|
||||
// parse the function config
|
||||
if _, found := o["functionConfig"]; found {
|
||||
fc := (o["functionConfig"].(map[string]interface{}))
|
||||
b, err := yaml.Marshal(fc)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
sf.FunctionConfig, err = yaml.Parse(string(b))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
}
|
||||
|
||||
// parse the items
|
||||
// copy the items out of the ResourceList, and into the Filter output
|
||||
var results []*yaml.RNode
|
||||
it := (o["items"].([]interface{}))
|
||||
for i := range it {
|
||||
// convert the resource back to the native yaml form
|
||||
b, err := yaml.Marshal(it[i])
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
node, err := yaml.Parse(string(b))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
|
||||
// match it to an input
|
||||
idS, err := node.Pipe(yaml.GetAnnotation("config.k8s.io/id"))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
if idS == nil {
|
||||
// no matching input -- new resource
|
||||
results = append(results, node)
|
||||
continue
|
||||
}
|
||||
|
||||
id, err := strconv.Atoi(idS.YNode().Value)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
if match, found := ids[id]; found {
|
||||
// matching resources
|
||||
match.out = node
|
||||
} else {
|
||||
// no matching input with the same id -- new resource
|
||||
// this may be an error case, the outputs probably shouldn't have ids
|
||||
// assigned by the starlark program
|
||||
results = append(results, node)
|
||||
}
|
||||
}
|
||||
|
||||
// retain the comments instead of dropping them by copying them from the original inputs
|
||||
for i := 0; i < len(ids); i++ {
|
||||
v := ids[i]
|
||||
if v.out == nil {
|
||||
continue
|
||||
}
|
||||
if err := comments.CopyComments(v.in, v.out); err != nil {
|
||||
return nil, errors.Wrap(err)
|
||||
}
|
||||
results = append(results, v.out)
|
||||
}
|
||||
|
||||
// delete the ids from resources, these were only to track through the starlark program
|
||||
// and that is finished.
|
||||
for i := range results {
|
||||
err := results[i].PipeE(yaml.ClearAnnotation("config.k8s.io/id"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
389
kyaml/starlark/starlark_test.go
Normal file
389
kyaml/starlark/starlark_test.go
Normal file
@@ -0,0 +1,389 @@
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package starlark
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"sigs.k8s.io/kustomize/kyaml/kio"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
)
|
||||
|
||||
func TestFilter_Filter(t *testing.T) {
|
||||
var tests = []struct {
|
||||
name string
|
||||
input string
|
||||
functionConfig string
|
||||
script string
|
||||
expected string
|
||||
expectedFunctionConfig string
|
||||
}{
|
||||
{
|
||||
name: "add_annotation",
|
||||
input: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
# head comment
|
||||
image: nginx:1.8.1 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image"}
|
||||
`,
|
||||
script: `
|
||||
# set the foo annotation on each resource
|
||||
def run(r):
|
||||
for resource in r:
|
||||
resource["metadata"]["annotations"]["foo"] = "bar"
|
||||
|
||||
run(resourceList["items"])
|
||||
`,
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
annotations:
|
||||
foo: bar
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
# head comment
|
||||
image: nginx:1.8.1 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image"}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "update_annotation",
|
||||
input: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
annotations:
|
||||
foo: baz
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
# head comment
|
||||
image: nginx:1.8.1 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image"}
|
||||
`,
|
||||
script: `
|
||||
# set the foo annotation on each resource
|
||||
def run(r):
|
||||
for resource in r:
|
||||
resource["metadata"]["annotations"]["foo"] = "bar"
|
||||
|
||||
run(resourceList["items"])
|
||||
`,
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
annotations:
|
||||
foo: bar
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
# head comment
|
||||
image: nginx:1.8.1 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image"}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "update_annotation_multiple",
|
||||
input: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment-1
|
||||
annotations:
|
||||
foo: baz
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
# head comment
|
||||
image: nginx:1.8.1 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image"}
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment-2
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
# head comment
|
||||
image: nginx:1.8.1 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image"}
|
||||
`,
|
||||
script: `
|
||||
# set the foo annotation on each resource
|
||||
def run(r):
|
||||
for resource in r:
|
||||
resource["metadata"]["annotations"]["foo"] = "bar"
|
||||
|
||||
run(resourceList["items"])
|
||||
`,
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment-1
|
||||
annotations:
|
||||
foo: bar
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
# head comment
|
||||
image: nginx:1.8.1 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image"}
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment-2
|
||||
annotations:
|
||||
foo: bar
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
# head comment
|
||||
image: nginx:1.8.1 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image"}`,
|
||||
},
|
||||
{
|
||||
name: "add_resource",
|
||||
input: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment-1
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
# head comment
|
||||
image: nginx:1.8.1 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image"}
|
||||
`,
|
||||
script: `
|
||||
def run(r):
|
||||
d = {
|
||||
"apiVersion": "apps/v1",
|
||||
"kind": "Deployment",
|
||||
"metadata": {
|
||||
"name": "nginx-deployment-2",
|
||||
},
|
||||
}
|
||||
r.append(d)
|
||||
run(resourceList["items"])
|
||||
`,
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment-2
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment-1
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
# head comment
|
||||
image: nginx:1.8.1 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image"}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "remove_resource",
|
||||
input: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment-1
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment-2
|
||||
`,
|
||||
script: `
|
||||
def run(r):
|
||||
r.pop()
|
||||
run(resourceList["items"])
|
||||
`,
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment-1
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "functionConfig",
|
||||
input: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
# head comment
|
||||
image: nginx:1.8.1 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image"}
|
||||
`,
|
||||
functionConfig: `
|
||||
kind: Script
|
||||
spec:
|
||||
value: "hello world"
|
||||
`,
|
||||
script: `
|
||||
# set the foo annotation on each resource
|
||||
def run(r, an):
|
||||
for resource in r:
|
||||
resource["metadata"]["annotations"]["foo"] = an
|
||||
|
||||
an = resourceList["functionConfig"]["spec"]["value"]
|
||||
run(resourceList["items"], an)
|
||||
`,
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
annotations:
|
||||
foo: hello world
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
# head comment
|
||||
image: nginx:1.8.1 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image"}
|
||||
`,
|
||||
expectedFunctionConfig: `
|
||||
kind: Script
|
||||
spec:
|
||||
value: hello world
|
||||
`,
|
||||
},
|
||||
|
||||
{
|
||||
name: "functionConfig_update_functionConfig",
|
||||
input: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
# head comment
|
||||
image: nginx:1.8.1 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image"}
|
||||
`,
|
||||
functionConfig: `
|
||||
kind: Script
|
||||
spec:
|
||||
value: "hello world"
|
||||
`,
|
||||
script: `
|
||||
# set the foo annotation on each resource
|
||||
def run(r, an):
|
||||
for resource in r:
|
||||
resource["metadata"]["annotations"]["foo"] = an
|
||||
|
||||
an = resourceList["functionConfig"]["spec"]["value"]
|
||||
run(resourceList["items"], an)
|
||||
resourceList["functionConfig"]["spec"]["value"] = "updated"
|
||||
`,
|
||||
expected: `
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
annotations:
|
||||
foo: hello world
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
# head comment
|
||||
image: nginx:1.8.1 # {"$ref": "#/definitions/io.k8s.cli.substitutions.image"}
|
||||
`,
|
||||
expectedFunctionConfig: `
|
||||
kind: Script
|
||||
spec:
|
||||
value: updated
|
||||
`,
|
||||
},
|
||||
}
|
||||
for i := range tests {
|
||||
test := tests[i]
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
f := &Filter{Name: test.name, Program: test.script}
|
||||
|
||||
if test.functionConfig != "" {
|
||||
fc, err := yaml.Parse(test.functionConfig)
|
||||
if !assert.NoError(t, err) {
|
||||
t.FailNow()
|
||||
}
|
||||
f.FunctionConfig = fc
|
||||
}
|
||||
|
||||
r := &kio.ByteReader{Reader: bytes.NewBufferString(test.input)}
|
||||
o := &bytes.Buffer{}
|
||||
w := &kio.ByteWriter{Writer: o}
|
||||
p := kio.Pipeline{
|
||||
Inputs: []kio.Reader{r},
|
||||
Filters: []kio.Filter{f},
|
||||
Outputs: []kio.Writer{w},
|
||||
}
|
||||
err := p.Execute()
|
||||
if !assert.NoError(t, err) {
|
||||
if e, ok := err.(*errors.Error); ok {
|
||||
fmt.Fprintf(os.Stderr, "%s\n", e.Stack())
|
||||
}
|
||||
t.FailNow()
|
||||
}
|
||||
if !assert.Equal(t, strings.TrimSpace(test.expected), strings.TrimSpace(o.String())) {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
if test.expectedFunctionConfig != "" {
|
||||
if !assert.Equal(t,
|
||||
strings.TrimSpace(test.expectedFunctionConfig),
|
||||
strings.TrimSpace(f.FunctionConfig.MustString())) {
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -14,9 +14,9 @@ import (
|
||||
|
||||
// typeToTag maps OpenAPI schema types to yaml 1.2 tags
|
||||
var typeToTag = map[string]string{
|
||||
"string": "!!str",
|
||||
"integer": "!!int",
|
||||
"boolean": "!!bool",
|
||||
"string": StringTag,
|
||||
"integer": IntTag,
|
||||
"boolean": BoolTag,
|
||||
"number": "!!float",
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
|
||||
package yaml
|
||||
|
||||
import "gopkg.in/yaml.v3"
|
||||
import (
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// AnnotationClearer removes an annotation at metadata.annotations.
|
||||
// Returns nil if the annotation or field does not exist.
|
||||
@@ -33,7 +35,7 @@ type AnnotationSetter struct {
|
||||
func (s AnnotationSetter) Filter(rn *RNode) (*RNode, error) {
|
||||
// some tools get confused about the type if annotations are not quoted
|
||||
v := NewScalarRNode(s.Value)
|
||||
v.YNode().Tag = "!!str"
|
||||
v.YNode().Tag = StringTag
|
||||
v.YNode().Style = yaml.SingleQuotedStyle
|
||||
return rn.Pipe(
|
||||
PathGetter{Path: []string{"metadata", "annotations"}, Create: yaml.MappingNode},
|
||||
@@ -80,7 +82,7 @@ type LabelSetter struct {
|
||||
func (s LabelSetter) Filter(rn *RNode) (*RNode, error) {
|
||||
// some tools get confused about the type if labels are not quoted
|
||||
v := NewScalarRNode(s.Value)
|
||||
v.YNode().Tag = "!!str"
|
||||
v.YNode().Tag = StringTag
|
||||
v.YNode().Style = yaml.SingleQuotedStyle
|
||||
return rn.Pipe(
|
||||
PathGetter{Path: []string{"metadata", "labels"}, Create: yaml.MappingNode},
|
||||
|
||||
@@ -588,6 +588,12 @@ func (rn *RNode) VisitFields(fn func(node *MapNode) error) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
StringTag = "!!str"
|
||||
BoolTag = "!!bool"
|
||||
IntTag = "!!int"
|
||||
)
|
||||
|
||||
// Elements returns the list of elements in the RNode.
|
||||
// Returns an error for non-SequenceNodes.
|
||||
func (rn *RNode) Elements() ([]*RNode, error) {
|
||||
|
||||
@@ -40,6 +40,7 @@ func (l *Walker) walkAssociativeSequence() (*yaml.RNode, error) {
|
||||
}
|
||||
for _, value := range values {
|
||||
val, err := Walker{
|
||||
VisitKeysAsScalars: l.VisitKeysAsScalars,
|
||||
InferAssociativeLists: l.InferAssociativeLists,
|
||||
Visitor: l,
|
||||
Schema: s,
|
||||
|
||||
@@ -27,6 +27,32 @@ func (l Walker) walkMap() (*yaml.RNode, error) {
|
||||
|
||||
// recursively set the field values on the map
|
||||
for _, key := range l.fieldNames() {
|
||||
if l.VisitKeysAsScalars {
|
||||
// visit the map keys as if they were scalars,
|
||||
// this is necessary if doing things such as copying
|
||||
// comments
|
||||
var keys []*yaml.RNode
|
||||
for i := range l.Sources {
|
||||
// construct the sources from the keys
|
||||
if l.Sources[i] == nil {
|
||||
keys = append(keys, nil)
|
||||
continue
|
||||
}
|
||||
field := l.Sources[i].Field(key)
|
||||
if field == nil || yaml.IsEmpty(field.Key) {
|
||||
keys = append(keys, nil)
|
||||
continue
|
||||
}
|
||||
keys = append(keys, field.Key)
|
||||
}
|
||||
// visit the sources as a scalar
|
||||
// keys don't have any schema --pass in nil
|
||||
_, err := l.Visitor.VisitScalar(keys, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var s *openapi.ResourceSchema
|
||||
if l.Schema != nil {
|
||||
s = l.Schema.Field(key)
|
||||
@@ -36,6 +62,7 @@ func (l Walker) walkMap() (*yaml.RNode, error) {
|
||||
s = commentSch
|
||||
}
|
||||
val, err := Walker{
|
||||
VisitKeysAsScalars: l.VisitKeysAsScalars,
|
||||
InferAssociativeLists: l.InferAssociativeLists,
|
||||
Visitor: l,
|
||||
Schema: s,
|
||||
|
||||
@@ -32,6 +32,10 @@ type Walker struct {
|
||||
// fields which it doesn't have the schema based on the fields in the
|
||||
// list elements.
|
||||
InferAssociativeLists bool
|
||||
|
||||
// VisitKeysAsScalars if true will call VisitScalar on map entry keys,
|
||||
// providing nil as the OpenAPI schema.
|
||||
VisitKeysAsScalars bool
|
||||
}
|
||||
|
||||
func (l Walker) Kind() yaml.Kind {
|
||||
|
||||
@@ -388,3 +388,45 @@ spec:
|
||||
initContainers: null
|
||||
`)
|
||||
}
|
||||
|
||||
func TestImageTagTransformerTagWithBraces(t *testing.T) {
|
||||
th := kusttest_test.MakeEnhancedHarness(t).
|
||||
PrepBuiltin("ImageTagTransformer")
|
||||
defer th.Reset()
|
||||
|
||||
rm := th.LoadAndRunTransformer(`
|
||||
apiVersion: builtin
|
||||
kind: ImageTagTransformer
|
||||
metadata:
|
||||
name: notImportantHere
|
||||
imageTag:
|
||||
name: some.registry.io/my-image
|
||||
newTag: "my-fixed-tag"
|
||||
`, `
|
||||
group: apps
|
||||
apiVersion: v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deploy1
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- image: some.registry.io/my-image:{GENERATED_TAG}
|
||||
name: my-image
|
||||
`)
|
||||
|
||||
th.AssertActualEqualsExpected(rm, `
|
||||
apiVersion: v1
|
||||
group: apps
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deploy1
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- image: some.registry.io/my-image:my-fixed-tag
|
||||
name: my-image
|
||||
`)
|
||||
}
|
||||
@@ -6,3 +6,5 @@ require (
|
||||
sigs.k8s.io/kustomize/api v0.3.1
|
||||
sigs.k8s.io/yaml v1.1.0
|
||||
)
|
||||
|
||||
replace sigs.k8s.io/kustomize/api => ../../../api
|
||||
|
||||
@@ -56,7 +56,7 @@ func (p *plugin) Transform(m resmap.ResMap) error {
|
||||
|
||||
matches := m.GetMatchingResourcesByCurrentId(r.CurId().Equals)
|
||||
if len(matches) != 1 {
|
||||
return fmt.Errorf("namespace tranformation produces ID conflict: %+v", matches)
|
||||
return fmt.Errorf("namespace transformation produces ID conflict: %+v", matches)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
# kyaml version
|
||||
export kyaml_major=0
|
||||
export kyaml_minor=1
|
||||
export kyaml_patch=0
|
||||
export kyaml_patch=1
|
||||
|
||||
# kstatus version
|
||||
export kstatus_major=0
|
||||
@@ -21,7 +21,7 @@ export api_patch=3
|
||||
# cmd/config version
|
||||
export cmd_config_major=0
|
||||
export cmd_config_minor=1
|
||||
export cmd_config_patch=0
|
||||
export cmd_config_patch=1
|
||||
|
||||
# cmd/kubectl version
|
||||
export cmd_kubectl_major=0
|
||||
|
||||
@@ -6,7 +6,7 @@ set -x
|
||||
set -e
|
||||
|
||||
# verify all modules pass validation
|
||||
for i in $(find . -name go.mod); do
|
||||
for i in $(find . -name go.mod -not -path "./hack/*"); do
|
||||
pushd .
|
||||
cd $(dirname $i);
|
||||
go list -m -json all > /dev/null
|
||||
|
||||
Reference in New Issue
Block a user