diff --git a/acceptance.bats b/acceptance.bats index b1db5d2..2092790 100644 --- a/acceptance.bats +++ b/acceptance.bats @@ -4,4 +4,38 @@ run bin/kubeconform -file fixtures/valid.yaml -summary [ "$status" -eq 0 ] [ "$output" = "Run summary - Valid: 1, Invalid: 0, Errors: 0 Skipped: 0" ] -} \ No newline at end of file +} + +@test "Pass when parsing a Kubernetes file with string and integer quantities" { + run bin/kubeconform -verbose -file fixtures/quantity.yaml + [ "$status" -eq 0 ] + [ "$output" = "fixtures/quantity.yaml - LimitRange is valid" ] +} + +@test "Pass when parsing a valid Kubernetes config file with null arrays" { + run bin/kubeconform -verbose -file fixtures/null_string.yaml + [ "$status" -eq 0 ] + [ "$output" = "fixtures/null_string.yaml - Service is valid" ] +} + +@test "Pass when parsing a multi-document config file" { + run bin/kubeconform -summary -file fixtures/multi_valid.yaml + [ "$status" -eq 0 ] + [ "$output" = "Run summary - Valid: 6, Invalid: 0, Errors: 0 Skipped: 0" ] +} + +@test "Fail when parsing a multi-document config file with one invalid resource" { + run bin/kubeconform -file fixtures/multi_invalid.yaml + [ "$status" -eq 1 ] +} + +@test "Fail when parsing an invalid Kubernetes config file" { + run bin/kubeconform -file fixtures/invalid.yaml + [ "$status" -eq 1 ] +} + +@test "Return relevant error for non-existent file" { + run bin/kubeconform -file fixtures/not-here + [ "$status" -eq 1 ] + [ $(expr "$output" : "^failed opening fixtures/not-here") -ne 0 ] +} diff --git a/fixtures/blank.yaml b/fixtures/blank.yaml new file mode 100755 index 0000000..e69de29 diff --git a/fixtures/comment.yaml b/fixtures/comment.yaml new file mode 100755 index 0000000..1c5db03 --- /dev/null +++ b/fixtures/comment.yaml @@ -0,0 +1,3 @@ +--- +# Arbitrary comment + diff --git a/fixtures/duplicates-non-namespaced.yaml b/fixtures/duplicates-non-namespaced.yaml new file mode 100755 index 0000000..5fa69ee --- /dev/null +++ b/fixtures/duplicates-non-namespaced.yaml @@ -0,0 +1,39 @@ +# Two objects with same name in same namespace, resource of non-namespaced kind + +apiVersion: v1 +kind: PersistentVolume +metadata: + name: pv0003 +spec: + capacity: + storage: 5Gi + volumeMode: Filesystem + accessModes: + - ReadWriteOnce + persistentVolumeReclaimPolicy: Recycle + storageClassName: slow + mountOptions: + - hard + - nfsvers=4.1 + nfs: + path: /tmp + server: 172.17.0.2 +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: pv0003 +spec: + capacity: + storage: 5Gi + volumeMode: Filesystem + accessModes: + - ReadWriteOnce + persistentVolumeReclaimPolicy: Recycle + storageClassName: slow + mountOptions: + - hard + - nfsvers=4.1 + nfs: + path: /tmp + server: 172.17.0.2 diff --git a/fixtures/duplicates-skipped-kinds.yaml b/fixtures/duplicates-skipped-kinds.yaml new file mode 100755 index 0000000..2be8950 --- /dev/null +++ b/fixtures/duplicates-skipped-kinds.yaml @@ -0,0 +1,41 @@ +# Two objects with same name in same namespace, but of a kind configured to be skipped + +apiVersion: v1 +kind: SkipThisKind +metadata: + name: "identical" +spec: + replicas: 2 + selector: + app: nginx + template: + metadata: + name: nginx + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx + ports: + - containerPort: 80 +--- +apiVersion: v1 +kind: SkipThisKind +metadata: + name: "identical" +spec: + replicas: 2 + selector: + app: nginx + template: + metadata: + name: nginx + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx + ports: + - containerPort: 80 diff --git a/fixtures/duplicates-with-namespace-default.yaml b/fixtures/duplicates-with-namespace-default.yaml new file mode 100755 index 0000000..30a2df8 --- /dev/null +++ b/fixtures/duplicates-with-namespace-default.yaml @@ -0,0 +1,43 @@ +# Two objects with same name in same namespace (one of them not given, i.e. will use default namespace as passed to kubeval) + +apiVersion: v1 +kind: ReplicationController +metadata: + name: "bob" + namespace: the-default-namespace +spec: + replicas: 2 + selector: + app: nginx + template: + metadata: + name: nginx + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx + ports: + - containerPort: 80 +--- +apiVersion: v1 +kind: ReplicationController +metadata: + name: "bob" + # namespace not given +spec: + replicas: 2 + selector: + app: nginx + template: + metadata: + name: nginx + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx + ports: + - containerPort: 80 diff --git a/fixtures/duplicates-with-namespace.yaml b/fixtures/duplicates-with-namespace.yaml new file mode 100755 index 0000000..6e83448 --- /dev/null +++ b/fixtures/duplicates-with-namespace.yaml @@ -0,0 +1,43 @@ +# Two objects with same name in same namespace + +apiVersion: v1 +kind: ReplicationController +metadata: + name: "bob" + namespace: x +spec: + replicas: 2 + selector: + app: nginx + template: + metadata: + name: nginx + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx + ports: + - containerPort: 80 +--- +apiVersion: v1 +kind: ReplicationController +metadata: + name: "bob" + namespace: x +spec: + replicas: 2 + selector: + app: nginx + template: + metadata: + name: nginx + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx + ports: + - containerPort: 80 diff --git a/fixtures/duplicates.yaml b/fixtures/duplicates.yaml new file mode 100755 index 0000000..d22ac4f --- /dev/null +++ b/fixtures/duplicates.yaml @@ -0,0 +1,41 @@ +# Two objects with same name in same namespace + +apiVersion: v1 +kind: ReplicationController +metadata: + name: "bob" +spec: + replicas: 2 + selector: + app: nginx + template: + metadata: + name: nginx + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx + ports: + - containerPort: 80 +--- +apiVersion: v1 +kind: ReplicationController +metadata: + name: "bob" +spec: + replicas: 2 + selector: + app: nginx + template: + metadata: + name: nginx + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx + ports: + - containerPort: 80 diff --git a/fixtures/extra_property.yaml b/fixtures/extra_property.yaml new file mode 100755 index 0000000..c01fba1 --- /dev/null +++ b/fixtures/extra_property.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: extensions/v1beta1 +kind: DaemonSet +metadata: + name: nginx-ds +spec: + replicas: 2 + template: + spec: + containers: + - image: nginx + name: nginx diff --git a/fixtures/full_domain_group.yaml b/fixtures/full_domain_group.yaml new file mode 100755 index 0000000..982e031 --- /dev/null +++ b/fixtures/full_domain_group.yaml @@ -0,0 +1,13 @@ +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: tiller-binding + namespace: dev2 +subjects: +- kind: ServiceAccount + name: tiller + namespace: dev2 +roleRef: + kind: Role + name: tiller-manager + apiGroup: rbac.authorization.k8s.io diff --git a/fixtures/int_or_string.yaml b/fixtures/int_or_string.yaml new file mode 100755 index 0000000..097d8ee --- /dev/null +++ b/fixtures/int_or_string.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + task: monitoring + # For use as a Cluster add-on (https://github.com/kubernetes/kubernetes/tree/master/cluster/addons) + # If you are NOT using this as an addon, you should comment out this line. + kubernetes.io/cluster-service: 'true' + kubernetes.io/name: Heapster + name: heapster + namespace: kube-system +spec: + ports: + - port: 80 + targetPort: 8082 + selector: + k8s-app: heapster diff --git a/fixtures/invalid.yaml b/fixtures/invalid.yaml new file mode 100755 index 0000000..d0ad352 --- /dev/null +++ b/fixtures/invalid.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: ReplicationController +metadata: + name: "bob" +spec: + replicas: asd" + selector: + app: nginx + templates: + metadata: + name: nginx + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx + ports: + - containerPort: 80 diff --git a/fixtures/list_invalid.yaml b/fixtures/list_invalid.yaml new file mode 100755 index 0000000..ec83741 --- /dev/null +++ b/fixtures/list_invalid.yaml @@ -0,0 +1,39 @@ +apiVersion: v1 +kind: List +items: +- apiVersion: v1 + kind: Service + metadata: + name: redis-master + labels: + app: redis + tier: backend + role: master + spec: + ports: + # the port that this service should serve on + - port: 6379 + targetPort: 6379 + selector: + app: redis + tier: backend + role: master +- apiVersion: v1 + kind: ReplicationController + metadata: + name: "bob" + spec: + replicas: asd" + selector: + app: nginx + templates: + metadata: + name: nginx + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx + ports: + - containerPort: 80 \ No newline at end of file diff --git a/fixtures/list_valid.yaml b/fixtures/list_valid.yaml new file mode 100755 index 0000000..661bfc5 --- /dev/null +++ b/fixtures/list_valid.yaml @@ -0,0 +1,174 @@ +apiVersion: v1 +kind: List +items: +- apiVersion: v1 + kind: Service + metadata: + name: redis-master + labels: + app: redis + tier: backend + role: master + spec: + ports: + # the port that this service should serve on + - port: 6379 + targetPort: 6379 + selector: + app: redis + tier: backend + role: master +- apiVersion: v1 + kind: ReplicationController + metadata: + name: redis-master + # these labels can be applied automatically + # from the labels in the pod template if not set + labels: + app: redis + role: master + tier: backend + spec: + # this replicas value is default + # modify it according to your case + replicas: 1 + # selector can be applied automatically + # from the labels in the pod template if not set + # selector: + # app: guestbook + # role: master + # tier: backend + template: + metadata: + labels: + app: redis + role: master + tier: backend + spec: + containers: + - name: master + image: redis + resources: + requests: + cpu: 100m + memory: 100Mi + ports: + - containerPort: 6379 +- apiVersion: v1 + kind: Service + metadata: + name: redis-slave + labels: + app: redis + tier: backend + role: slave + spec: + ports: + # the port that this service should serve on + - port: 6379 + selector: + app: redis + tier: backend + role: slave +- apiVersion: v1 + kind: ReplicationController + metadata: + name: redis-slave + # these labels can be applied automatically + # from the labels in the pod template if not set + labels: + app: redis + role: slave + tier: backend + spec: + # this replicas value is default + # modify it according to your case + replicas: 2 + # selector can be applied automatically + # from the labels in the pod template if not set + # selector: + # app: guestbook + # role: slave + # tier: backend + template: + metadata: + labels: + app: redis + role: slave + tier: backend + spec: + containers: + - name: slave + image: gcr.io/google_samples/gb-redisslave:v1 + resources: + requests: + cpu: 100m + memory: 100Mi + env: + - name: GET_HOSTS_FROM + value: dns + # If your cluster config does not include a dns service, then to + # instead access an environment variable to find the master + # service's host, comment out the 'value: dns' line above, and + # uncomment the line below. + # value: env + ports: + - containerPort: 6379 +- apiVersion: v1 + kind: Service + metadata: + name: frontend + labels: + app: guestbook + tier: frontend + spec: + # if your cluster supports it, uncomment the following to automatically create + # an external load-balanced IP for the frontend service. + # type: LoadBalancer + ports: + # the port that this service should serve on + - port: 80 + selector: + app: guestbook + tier: frontend +- apiVersion: v1 + kind: ReplicationController + metadata: + name: frontend + # these labels can be applied automatically + # from the labels in the pod template if not set + labels: + app: guestbook + tier: frontend + spec: + # this replicas value is default + # modify it according to your case + replicas: 3 + # selector can be applied automatically + # from the labels in the pod template if not set + # selector: + # app: guestbook + # tier: frontend + template: + metadata: + labels: + app: guestbook + tier: frontend + spec: + containers: + - name: php-redis + image: gcr.io/google_samples/gb-frontend:v3 + resources: + requests: + cpu: 100m + memory: 100Mi + env: + - name: GET_HOSTS_FROM + value: dns + # If your cluster config does not include a dns service, then to + # instead access environment variables to find service host + # info, comment out the 'value: dns' line above, and uncomment the + # line below. + # value: env + ports: + - containerPort: 80 \ No newline at end of file diff --git a/fixtures/missing_kind.yaml b/fixtures/missing_kind.yaml new file mode 100755 index 0000000..b4f46b7 --- /dev/null +++ b/fixtures/missing_kind.yaml @@ -0,0 +1 @@ +key: value diff --git a/fixtures/missing_kind_value.yaml b/fixtures/missing_kind_value.yaml new file mode 100755 index 0000000..65b956a --- /dev/null +++ b/fixtures/missing_kind_value.yaml @@ -0,0 +1 @@ +kind: diff --git a/fixtures/multi_invalid.yaml b/fixtures/multi_invalid.yaml new file mode 100755 index 0000000..d0e3fd6 --- /dev/null +++ b/fixtures/multi_invalid.yaml @@ -0,0 +1,176 @@ +apiVersion: v1 +kind: Service +metadata: + name: redis-master + labels: + app: redis + tier: backend + role: master +spec: + ports: + # the port that this service should serve on + - port: sds + targetPort: 6379 + selector: + app: redis + tier: backend + role: master +--- +apiVersion: v1 +kind: ReplicationController +metadata: + name: redis-master + # these labels can be applied automatically + # from the labels in the pod template if not set + labels: + app: redis + role: master + tier: backend +spec: + # this replicas value is default + # modify it according to your case + replicas: 1 + # selector can be applied automatically + # from the labels in the pod template if not set + # selector: + # app: guestbook + # role: master + # tier: backend + template: + metadata: + labels: + app: redis + role: master + tier: backend + spec: + containers: + - name: master + image: redis + resources: + requests: + cpu: 100m + memory: 100Mi + ports: + - containerPort: 6379 +--- +apiVersion: v1 +kind: Service +metadata: + name: redis-slave + labels: + app: redis + tier: backend + role: slave +spec: + ports: + # the port that this service should serve on + - port: 6379 + selector: + app: redis + tier: backend + role: slave +--- +apiVersion: v1 +kind: ReplicationController +metadata: + name: redis-slave + # these labels can be applied automatically + # from the labels in the pod template if not set + labels: + app: redis + role: slave + tier: backend +spec: + # this replicas value is default + # modify it according to your case + replicas: 2 + # selector can be applied automatically + # from the labels in the pod template if not set + # selector: + # app: guestbook + # role: slave + # tier: backend + template: + metadata: + labels: + app: redis + role: slave + tier: backend + spec: + containers: + - name: slave + image: gcr.io/google_samples/gb-redisslave:v1 + resources: + requests: + cpu: 100m + memory: 100Mi + env: + - name: GET_HOSTS_FROM + value: dns + # If your cluster config does not include a dns service, then to + # instead access an environment variable to find the master + # service's host, comment out the 'value: dns' line above, and + # uncomment the line below. + # value: env + ports: + - containerPort: 6379 +--- +apiVersion: v1 +kind: Service +metadata: + name: frontend + labels: + app: guestbook + tier: frontend +spec: + # if your cluster supports it, uncomment the following to automatically create + # an external load-balanced IP for the frontend service. + # type: LoadBalancer + ports: + # the port that this service should serve on + - port: 80 + selector: + app: guestbook + tier: frontend +--- +apiVersion: v1 +kind: ReplicationController +metadata: + name: frontend + # these labels can be applied automatically + # from the labels in the pod template if not set + labels: + app: guestbook + tier: frontend +spec: + # this replicas value is default + # modify it according to your case + replicas: 3 + # selector can be applied automatically + # from the labels in the pod template if not set + # selector: + # app: guestbook + # tier: frontend + template: + metadata: + labels: + app: guestbook + tier: frontend + spec: + containers: + - name: php-redis + image: gcr.io/google_samples/gb-frontend:v3 + resources: + requests: + cpu: 100m + memory: 100Mi + env: + - name: GET_HOSTS_FROM + value: dns + # If your cluster config does not include a dns service, then to + # instead access environment variables to find service host + # info, comment out the 'value: dns' line above, and uncomment the + # line below. + # value: env + ports: + - containerPort: 80 diff --git a/fixtures/multi_invalid_resources.yaml b/fixtures/multi_invalid_resources.yaml new file mode 100755 index 0000000..b9618ef --- /dev/null +++ b/fixtures/multi_invalid_resources.yaml @@ -0,0 +1,9 @@ +kind: +--- +kind: +--- +kind: +--- +kind: +--- +kind: diff --git a/fixtures/multi_valid.yaml b/fixtures/multi_valid.yaml new file mode 100755 index 0000000..a336388 --- /dev/null +++ b/fixtures/multi_valid.yaml @@ -0,0 +1,181 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: redis-master + labels: + app: redis + tier: backend + role: master +spec: + ports: + # the port that this service should serve on + - port: 6379 + targetPort: 6379 + selector: + app: redis + tier: backend + role: master +--- +apiVersion: v1 +kind: ReplicationController +metadata: + name: redis-master + # these labels can be applied automatically + # from the labels in the pod template if not set + labels: + app: redis + role: master + tier: backend +spec: + # this replicas value is default + # modify it according to your case + replicas: 1 + # selector can be applied automatically + # from the labels in the pod template if not set + # selector: + # app: guestbook + # role: master + # tier: backend + template: + metadata: + labels: + app: redis + role: master + tier: backend + spec: + containers: + - name: master + image: redis + resources: + requests: + cpu: 100m + memory: 100Mi + ports: + - containerPort: 6379 +--- +apiVersion: v1 +kind: Service +metadata: + name: redis-slave + labels: + app: redis + tier: backend + role: slave +spec: + ports: + # the port that this service should serve on + - port: 6379 + selector: + app: redis + tier: backend + role: slave +--- +apiVersion: v1 +kind: ReplicationController +metadata: + name: redis-slave + # these labels can be applied automatically + # from the labels in the pod template if not set + labels: + app: redis + role: slave + tier: backend +spec: + # this replicas value is default + # modify it according to your case + replicas: 2 + # selector can be applied automatically + # from the labels in the pod template if not set + # selector: + # app: guestbook + # role: slave + # tier: backend + template: + metadata: + labels: + app: redis + role: slave + tier: backend + spec: + containers: + - name: slave + image: gcr.io/google_samples/gb-redisslave:v1 + resources: + requests: + cpu: 100m + memory: 100Mi + env: + - name: GET_HOSTS_FROM + value: dns + # If your cluster config does not include a dns service, then to + # instead access an environment variable to find the master + # service's host, comment out the 'value: dns' line above, and + # uncomment the line below. + # value: env + ports: + - containerPort: 6379 +--- +apiVersion: v1 +kind: Service +metadata: + name: frontend + labels: + app: guestbook + tier: frontend +spec: + # if your cluster supports it, uncomment the following to automatically create + # an external load-balanced IP for the frontend service. + # type: LoadBalancer + ports: + # the port that this service should serve on + - port: 80 + selector: + app: guestbook + tier: frontend +--- +apiVersion: v1 +kind: ReplicationController +metadata: + name: frontend + # these labels can be applied automatically + # from the labels in the pod template if not set + labels: + app: guestbook + tier: frontend +spec: + # this replicas value is default + # modify it according to your case + replicas: 3 + # selector can be applied automatically + # from the labels in the pod template if not set + # selector: + # app: guestbook + # tier: frontend + template: + metadata: + labels: + app: guestbook + tier: frontend + spec: + containers: + - name: php-redis + image: gcr.io/google_samples/gb-frontend:v3 + resources: + requests: + cpu: 100m + memory: 100Mi + env: + - name: GET_HOSTS_FROM + value: dns + # If your cluster config does not include a dns service, then to + # instead access environment variables to find service host + # info, comment out the 'value: dns' line above, and uncomment the + # line below. + # value: env + ports: + - containerPort: 80 +--- +--- +# an empty resource with comments +--- diff --git a/fixtures/multi_valid_source.yaml b/fixtures/multi_valid_source.yaml new file mode 100755 index 0000000..2d87f15 --- /dev/null +++ b/fixtures/multi_valid_source.yaml @@ -0,0 +1,184 @@ +--- +# Source: chart/templates/primary.yaml +apiVersion: v1 +kind: Service +metadata: + name: redis-primary + labels: + app: redis + tier: backend + role: primary +spec: + ports: + # the port that this service should serve on + - port: 6379 + targetPort: 6379 + selector: + app: redis + tier: backend + role: primary +--- +apiVersion: v1 +kind: ReplicationController +metadata: + name: redis-primary + # these labels can be applied automatically + # from the labels in the pod template if not set + labels: + app: redis + role: primary + tier: backend +spec: + # this replicas value is default + # modify it according to your case + replicas: 1 + # selector can be applied automatically + # from the labels in the pod template if not set + # selector: + # app: guestbook + # role: primary + # tier: backend + template: + metadata: + labels: + app: redis + role: primary + tier: backend + spec: + containers: + - name: primary + image: redis + resources: + requests: + cpu: 100m + memory: 100Mi + ports: + - containerPort: 6379 +--- +# Source: chart/templates/secondary.yaml +apiVersion: v1 +kind: Service +metadata: + name: redis-secondary + labels: + app: redis + tier: backend + role: secondary +spec: + ports: + # the port that this service should serve on + - port: 6379 + selector: + app: redis + tier: backend + role: secondary +--- +apiVersion: v1 +kind: ReplicationController +metadata: + name: redis-secondary + # these labels can be applied automatically + # from the labels in the pod template if not set + labels: + app: redis + role: secondary + tier: backend +spec: + # this replicas value is default + # modify it according to your case + replicas: 2 + # selector can be applied automatically + # from the labels in the pod template if not set + # selector: + # app: guestbook + # role: secondary + # tier: backend + template: + metadata: + labels: + app: redis + role: secondary + tier: backend + spec: + containers: + - name: secondary + image: gcr.io/google_samples/gb-redissecondary:v1 + resources: + requests: + cpu: 100m + memory: 100Mi + env: + - name: GET_HOSTS_FROM + value: dns + # If your cluster config does not include a dns service, then to + # instead access an environment variable to find the primary + # service's host, comment out the 'value: dns' line above, and + # uncomment the line below. + # value: env + ports: + - containerPort: 6379 +--- +# Source: chart/templates/frontend.yaml +apiVersion: v1 +kind: Service +metadata: + name: frontend + labels: + app: guestbook + tier: frontend +spec: + # if your cluster supports it, uncomment the following to automatically create + # an external load-balanced IP for the frontend service. + # type: LoadBalancer + ports: + # the port that this service should serve on + - port: 80 + selector: + app: guestbook + tier: frontend +--- +apiVersion: v1 +kind: ReplicationController +metadata: + name: frontend + # these labels can be applied automatically + # from the labels in the pod template if not set + labels: + app: guestbook + tier: frontend +spec: + # this replicas value is default + # modify it according to your case + replicas: 3 + # selector can be applied automatically + # from the labels in the pod template if not set + # selector: + # app: guestbook + # tier: frontend + template: + metadata: + labels: + app: guestbook + tier: frontend + spec: + containers: + - name: php-redis + image: gcr.io/google_samples/gb-frontend:v3 + resources: + requests: + cpu: 100m + memory: 100Mi + env: + - name: GET_HOSTS_FROM + value: dns + # If your cluster config does not include a dns service, then to + # instead access environment variables to find service host + # info, comment out the 'value: dns' line above, and uncomment the + # line below. + # value: env + ports: + - containerPort: 80 +--- +--- +# an empty resource with comments +--- diff --git a/fixtures/null_array.yaml b/fixtures/null_array.yaml new file mode 100755 index 0000000..befe9fb --- /dev/null +++ b/fixtures/null_array.yaml @@ -0,0 +1,40 @@ +kind: Deployment +apiVersion: extensions/v1beta1 +metadata: + labels: + k8s-app: kubernetes-dashboard + name: kubernetes-dashboard + namespace: kube-system +spec: + replicas: 1 + revisionHistoryLimit: 10 + selector: + matchLabels: + k8s-app: kubernetes-dashboard + template: + metadata: + labels: + k8s-app: kubernetes-dashboard + spec: + containers: + - name: kubernetes-dashboard + image: gcr.io/google_containers/kubernetes-dashboard-amd64:v1.6.1 + ports: + - containerPort: 9090 + protocol: TCP + args: + # Uncomment the following line to manually specify Kubernetes API server Host + # If not specified, Dashboard will attempt to auto discover the API server and connect + # to it. Uncomment only if the default does not work. + # - --apiserver-host=http://my-address:port + livenessProbe: + httpGet: + path: / + port: 9090 + initialDelaySeconds: 30 + timeoutSeconds: 30 + serviceAccountName: kubernetes-dashboard + # Comment the following tolerations if Dashboard must not be deployed on master + tolerations: + - key: node-role.kubernetes.io/master + effect: NoSchedule diff --git a/fixtures/null_string.yaml b/fixtures/null_string.yaml new file mode 100755 index 0000000..c93d16a --- /dev/null +++ b/fixtures/null_string.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + kompose.service.type: LoadBalancer + creationTimestamp: null + labels: + io.kompose.service: frontend + name: frontend +spec: + ports: + - name: "80" + port: 80 + targetPort: 80 + selector: + io.kompose.service: frontend + type: LoadBalancer +status: + loadBalancer: {} diff --git a/fixtures/quantity.yaml b/fixtures/quantity.yaml new file mode 100755 index 0000000..dc18de0 --- /dev/null +++ b/fixtures/quantity.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: LimitRange +metadata: + name: mem-limit-range +spec: + limits: + - default: + memory: 512Mi + defaultRequest: + memory: 256000 + type: Container diff --git a/fixtures/same-kind-different-api.yaml b/fixtures/same-kind-different-api.yaml new file mode 100755 index 0000000..91c8a62 --- /dev/null +++ b/fixtures/same-kind-different-api.yaml @@ -0,0 +1,49 @@ +# Two objects with same name in same namespace, and having the same kind, but +# of different API (apps/v1 vs. apps/v1beta1). This is important when CRDs +# introduce overlapping `metadata:name` values, e.g. `Deployment` in +# `my-awesome-cd-tool.io/v1` (contrived scenario). + + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment + labels: + app: nginx +spec: + replicas: 3 + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.7.9 + ports: + - containerPort: 80 +--- +apiVersion: apps/v1beta1 +kind: Deployment +metadata: + name: nginx-deployment + labels: + app: nginx +spec: + replicas: 3 + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.7.9 + ports: + - containerPort: 80 diff --git a/fixtures/same-object-different-namespace-default.yaml b/fixtures/same-object-different-namespace-default.yaml new file mode 100755 index 0000000..bfb3694 --- /dev/null +++ b/fixtures/same-object-different-namespace-default.yaml @@ -0,0 +1,43 @@ +# Two objects with same name in different namespace, one of them being the configured default namespace + +apiVersion: v1 +kind: ReplicationController +metadata: + name: "bob" + namespace: a +spec: + replicas: 2 + selector: + app: nginx + template: + metadata: + name: nginx + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx + ports: + - containerPort: 80 +--- +apiVersion: v1 +kind: ReplicationController +metadata: + name: "bob" + namespace: the-default-namespace +spec: + replicas: 2 + selector: + app: nginx + template: + metadata: + name: nginx + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx + ports: + - containerPort: 80 diff --git a/fixtures/same-object-different-namespace.yaml b/fixtures/same-object-different-namespace.yaml new file mode 100755 index 0000000..0b46fca --- /dev/null +++ b/fixtures/same-object-different-namespace.yaml @@ -0,0 +1,43 @@ +# Two objects with same name in different namespace + +apiVersion: v1 +kind: ReplicationController +metadata: + name: "bob" + namespace: a +spec: + replicas: 2 + selector: + app: nginx + template: + metadata: + name: nginx + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx + ports: + - containerPort: 80 +--- +apiVersion: v1 +kind: ReplicationController +metadata: + name: "bob" + namespace: b +spec: + replicas: 2 + selector: + app: nginx + template: + metadata: + name: nginx + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx + ports: + - containerPort: 80 diff --git a/fixtures/test_crd.yaml b/fixtures/test_crd.yaml new file mode 100755 index 0000000..66652c9 --- /dev/null +++ b/fixtures/test_crd.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: bitnami.com/v1alpha1 +kind: SealedSecret +metadata: + name: test-secret + namespace: test-namespace +spec: + encryptedData: + SOME_ENCRYPTED_DATA: c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2 +--- +apiVersion: bitnami.com/v1alpha1 +kind: SealedSecret +metadata: + name: test-secret-clone + namespace: test-namespace +spec: + encryptedData: + SOME_ENCRYPTED_DATA: c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2 diff --git a/fixtures/unconventional_keys.yaml b/fixtures/unconventional_keys.yaml new file mode 100755 index 0000000..aa37f8c --- /dev/null +++ b/fixtures/unconventional_keys.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: unconventional-keys +data: + 5: "integer" + 3.14: "float" + true: "boolean" diff --git a/fixtures/valid.json b/fixtures/valid.json new file mode 100755 index 0000000..deb3101 --- /dev/null +++ b/fixtures/valid.json @@ -0,0 +1,46 @@ +{ + "apiVersion": "apps/v1beta1", + "kind": "Deployment", + "metadata": { + "name": "nginx-deployment", + "namespace": "default" + }, + "spec": { + "replicas": 2, + "template": { + "spec": { + "affinity": { }, + "containers": [ + { + "args": [ ], + "command": [ ], + "env": [ ], + "envFrom": [ ], + "image": "nginx:1.7.9", + "lifecycle": { }, + "livenessProbe": { }, + "name": "nginx", + "ports": [ + { + "containerPort": 80, + "name": "http" + } + ], + "readinessProbe": { }, + "resources": { }, + "securityContext": { }, + "volumeMounts": [ ] + } + ], + "hostMappings": [ ], + "imagePullSecrets": [ ], + "initContainers": [ ], + "nodeSelector": { }, + "securityContext": { }, + "tolerations": [ ], + "volumes": [ ] + } + } + }, + "status": { } +} diff --git a/fixtures/valid_version.yaml b/fixtures/valid_version.yaml new file mode 100755 index 0000000..580390e --- /dev/null +++ b/fixtures/valid_version.yaml @@ -0,0 +1,12 @@ +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: my-app-hpa +spec: + minReplicas: 100 + maxReplicas: 300 + scaleTargetRef: + apiVersion: extensions/v1beta1 + kind: Deployment + name: my-app + targetCPUUtilizationPercentage: 15 diff --git a/main.go b/main.go index a97b79c..10da94b 100644 --- a/main.go +++ b/main.go @@ -156,7 +156,7 @@ func skipKindsMap(skipKindsCSV string) map[string]bool { return skipKinds } -func processResults(o output.Output, validationResults chan []validationResult, result chan<- bool ) { +func processResults(o output.Output, validationResults chan []validationResult, result chan<- bool) { success := true for results := range validationResults { for _, result := range results { @@ -224,14 +224,13 @@ func realMain() int { close(fileBatches) }() - var o output.Output if o, err = getLogger(outputFormat, summary, verbose); err != nil { fmt.Println(err) return 1 } - res := make (chan bool) + res := make(chan bool) validationResults := make(chan []validationResult) go processResults(o, validationResults, res) @@ -246,7 +245,12 @@ func realMain() int { for _, filename := range fileBatch { f, err := os.Open(filename) if err != nil { - log.Printf("failed opening %s\n", filename) + fmt.Printf("failed opening %s\n", filename) + validationResults <- []validationResult{{ + filename: filename, + err: err, + skipped: true, + }} continue }