From ce279b370a5518cc33a5f10f21b6af983259b19d Mon Sep 17 00:00:00 2001 From: Robert Oh Date: Thu, 29 Nov 2018 10:32:26 -0800 Subject: [PATCH] Add incubator helm repo (#728) --- .../jaeger-helm/expected/.ship/state.json | 17 + .../jaeger-helm/expected/base/agent-ds.yaml | 42 ++ .../jaeger-helm/expected/base/agent-svc.yaml | 35 ++ .../expected/base/cassandra-schema-job.yaml | 44 ++ .../charts/cassandra/templates/service.yaml | 31 ++ .../cassandra/templates/statefulset.yaml | 98 ++++ .../expected/base/collector-deploy.yaml | 88 +++ .../expected/base/collector-svc.yaml | 31 ++ .../jaeger-helm/expected/base/common-cm.yaml | 29 + .../expected/base/kustomization.yaml | 13 + .../expected/base/query-deploy.yaml | 69 +++ .../jaeger-helm/expected/base/query-svc.yaml | 23 + .../expected/overlays/ship/kustomization.yaml | 4 + .../init/jaeger-helm/expected/rendered.yaml | 499 ++++++++++++++++++ integration/init/jaeger-helm/metadata.yaml | 3 + pkg/helm/repo_add.go | 140 +++++ pkg/helm/shared.go | 12 + pkg/lifecycle/render/helm/commands.go | 35 +- pkg/lifecycle/render/helm/template.go | 53 +- pkg/lifecycle/render/helm/template_test.go | 49 +- pkg/test-mocks/helm/commands_mock.go | 21 +- 21 files changed, 1306 insertions(+), 30 deletions(-) create mode 100644 integration/init/jaeger-helm/expected/.ship/state.json create mode 100644 integration/init/jaeger-helm/expected/base/agent-ds.yaml create mode 100644 integration/init/jaeger-helm/expected/base/agent-svc.yaml create mode 100644 integration/init/jaeger-helm/expected/base/cassandra-schema-job.yaml create mode 100644 integration/init/jaeger-helm/expected/base/charts/cassandra/templates/service.yaml create mode 100644 integration/init/jaeger-helm/expected/base/charts/cassandra/templates/statefulset.yaml create mode 100644 integration/init/jaeger-helm/expected/base/collector-deploy.yaml create mode 100644 integration/init/jaeger-helm/expected/base/collector-svc.yaml create mode 100644 integration/init/jaeger-helm/expected/base/common-cm.yaml create mode 100644 integration/init/jaeger-helm/expected/base/kustomization.yaml create mode 100644 integration/init/jaeger-helm/expected/base/query-deploy.yaml create mode 100644 integration/init/jaeger-helm/expected/base/query-svc.yaml create mode 100644 integration/init/jaeger-helm/expected/overlays/ship/kustomization.yaml create mode 100644 integration/init/jaeger-helm/expected/rendered.yaml create mode 100644 integration/init/jaeger-helm/metadata.yaml create mode 100644 pkg/helm/repo_add.go diff --git a/integration/init/jaeger-helm/expected/.ship/state.json b/integration/init/jaeger-helm/expected/.ship/state.json new file mode 100644 index 000000000..e323c3446 --- /dev/null +++ b/integration/init/jaeger-helm/expected/.ship/state.json @@ -0,0 +1,17 @@ +{ + "v1": { + "config": {}, + "helmValues": "# Default values for jaeger.\n# This is a YAML-formatted file.\n# Jaeger values are grouped by component. Cassandra values override subchart values\n\nprovisionDataStore:\n cassandra: true\n elasticsearch: false\n\ntag: 1.4.1\n\nstorage:\n # allowed values (cassandra, elasticsearch)\n type: cassandra\n cassandra:\n host: cassandra\n port: 9042\n user: user\n password: password\n elasticsearch:\n scheme: http\n host: elasticsearch\n port: 9200\n user: elastic\n password: changeme\n nodesWanOnly: false\n\n# Begin: Override values on the Cassandra subchart to customize for Jaeger\ncassandra:\n image:\n tag: 3.11\n persistence:\n # To enable persistence, please see the documentation for the Cassandra chart\n enabled: false\n config:\n cluster_name: jaeger\n seed_size: 1\n dc_name: dc1\n rack_name: rack1\n endpoint_snitch: GossipingPropertyFileSnitch\n# End: Override values on the Cassandra subchart to customize for Jaeger\n\n# Begin: Default values for the various components of Jaeger\n# This chart has been based on the Kubernetes integration found in the following repo:\n# https://github.com/jaegertracing/jaeger-kubernetes/blob/master/production/jaeger-production-template.yml\n#\n# This is the jaeger-cassandra-schema Job which sets up the Cassandra schema for\n# use by Jaeger\nschema:\n annotations: {}\n image: jaegertracing/jaeger-cassandra-schema\n pullPolicy: IfNotPresent\n # Acceptable values are test and prod. Default is for production use.\n mode: prod\n resources: {}\n # limits:\n # cpu: 500m\n # memory: 512Mi\n # requests:\n # cpu: 256m\n # memory: 128Mi\n ## Additional pod labels\n ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/\n podLabels: {}\n\n# Begin: Override values on the Elasticsearch subchart to customize for Jaeger\nelasticsearch:\n image:\n tag: \"5.4\"\n cluster:\n name: \"tracing\"\n data:\n persistence:\n enabled: false\n rbac:\n create: false\n\nagent:\n enabled: true\n annotations: {}\n image: jaegertracing/jaeger-agent\n pullPolicy: IfNotPresent\n collector:\n host: null\n port: null\n cmdlineParams: {}\n daemonset:\n useHostPort: false\n service:\n annotations: {}\n # List of IP ranges that are allowed to access the load balancer (if supported)\n loadBalancerSourceRanges: []\n type: ClusterIP\n # zipkinThriftPort :accept zipkin.thrift over compact thrift protocol\n zipkinThriftPort: 5775\n # compactPort: accept jaeger.thrift over compact thrift protocol\n compactPort: 6831\n # binaryPort: accept jaeger.thrift over binary thrift protocol\n binaryPort: 6832\n # samplingPort: (HTTP) serve configs, sampling strategies\n samplingPort: 5778\n resources: {}\n # limits:\n # cpu: 500m\n # memory: 512Mi\n # requests:\n # cpu: 256m\n # memory: 128Mi\n nodeSelector: {}\n podAnnotations: {}\n ## Additional pod labels\n ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/\n podLabels: {}\n ## Allow the scheduling on tainted nodes (requires Kubernetes \u003e= 1.6)\n ## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/\n tolerations: []\n useHostNetwork: false\n dnsPolicy: ClusterFirst\n\ncollector:\n enabled: true\n annotations: {}\n image: jaegertracing/jaeger-collector\n pullPolicy: IfNotPresent\n dnsPolicy: ClusterFirst\n cmdlineParams: {}\n replicaCount: 1\n service:\n annotations: {}\n # List of IP ranges that are allowed to access the load balancer (if supported)\n loadBalancerSourceRanges: []\n type: ClusterIP\n # tchannelPort: used by jaeger-agent to send spans in jaeger.thrift format\n tchannelPort: 14267\n # httpPort: can accept spans directly from clients in jaeger.thrift format\n httpPort: 14268\n # can accept Zipkin spans in JSON or Thrift\n zipkinPort: 9411\n healthCheckPort: 14269\n resources: {}\n # limits:\n # cpu: 1\n # memory: 1Gi\n # requests:\n # cpu: 500m\n # memory: 512Mi\n nodeSelector: {}\n podAnnotations: {}\n ## Additional pod labels\n ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/\n podLabels: {}\n ## Allow the scheduling on tainted nodes (requires Kubernetes \u003e= 1.6)\n ## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/\n tolerations: []\n\nquery:\n enabled: true\n annotations: {}\n image: jaegertracing/jaeger-query\n pullPolicy: IfNotPresent\n dnsPolicy: ClusterFirst\n cmdlineParams: {}\n healthCheckPort: 16687\n replicaCount: 1\n service:\n annotations: {}\n type: ClusterIP\n # List of IP ranges that are allowed to access the load balancer (if supported)\n loadBalancerSourceRanges: []\n # queryPort: externally accessible port for UI and API\n queryPort: 80\n # targetPort: the internal port the UI and API are exposed on\n targetPort: 16686\n ingress:\n enabled: false\n annotations: {}\n # Used to create an Ingress record.\n # hosts:\n # - chart-example.local\n # annotations:\n # kubernetes.io/ingress.class: nginx\n # kubernetes.io/tls-acme: \"true\"\n # tls:\n # Secrets must be manually created in the namespace.\n # - secretName: chart-example-tls\n # hosts:\n # - chart-example.local\n resources: {}\n # limits:\n # cpu: 500m\n # memory: 512Mi\n # requests:\n # cpu: 256m\n # memory: 128Mi\n nodeSelector: {}\n podAnnotations: {}\n ## Additional pod labels\n ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/\n podLabels: {}\n ## Allow the scheduling on tainted nodes (requires Kubernetes \u003e= 1.6)\n ## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/\n tolerations: []\n\nspark:\n enabled: false\n annotations: {}\n image: jaegertracing/spark-dependencies\n tag: latest\n pullPolicy: Always\n schedule: \"49 23 * * *\"\n successfulJobsHistoryLimit: 5\n failedJobsHistoryLimit: 5\n resources: {}\n # limits:\n # cpu: 500m\n # memory: 512Mi\n # requests:\n # cpu: 256m\n # memory: 128Mi\n nodeSelector: {}\n ## Additional pod labels\n ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/\n podLabels: {}\n ## Allow the scheduling on tainted nodes (requires Kubernetes \u003e= 1.6)\n ## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/\n tolerations: []\n# End: Default values for the various components of Jaeger\n\nhotrod:\n enabled: false\n replicaCount: 1\n image:\n repository: jaegertracing/example-hotrod\n tag: latest\n pullPolicy: Always\n service:\n annotations: {}\n name: hotrod\n type: ClusterIP\n # List of IP ranges that are allowed to access the load balancer (if supported)\n loadBalancerSourceRanges: []\n externalPort: 80\n internalPort: 8080\n ingress:\n enabled: false\n # Used to create Ingress record (should be used with service.type: ClusterIP).\n hosts:\n - chart-example.local\n annotations: {}\n # kubernetes.io/ingress.class: nginx\n # kubernetes.io/tls-acme: \"true\"\n tls:\n # Secrets must be manually created in the namespace.\n # - secretName: chart-example-tls\n # hosts:\n # - chart-example.local\n resources: {}\n # We usually recommend not to specify default resources and to leave this as a conscious\n # choice for the user. This also increases chances charts run on environments with little\n # resources, such as Minikube. If you do want to specify resources, uncomment the following\n # lines, adjust them as necessary, and remove the curly braces after 'resources:'.\n # limits:\n # cpu: 100m\n # memory: 128Mi\n # requests:\n # cpu: 100m\n # memory: 128Mi\n tracing:\n host: null\n port: 6831\n", + "releaseName": "jaeger", + "helmValuesDefaults": "# Default values for jaeger.\n# This is a YAML-formatted file.\n# Jaeger values are grouped by component. Cassandra values override subchart values\n\nprovisionDataStore:\n cassandra: true\n elasticsearch: false\n\ntag: 1.4.1\n\nstorage:\n # allowed values (cassandra, elasticsearch)\n type: cassandra\n cassandra:\n host: cassandra\n port: 9042\n user: user\n password: password\n elasticsearch:\n scheme: http\n host: elasticsearch\n port: 9200\n user: elastic\n password: changeme\n nodesWanOnly: false\n\n# Begin: Override values on the Cassandra subchart to customize for Jaeger\ncassandra:\n image:\n tag: 3.11\n persistence:\n # To enable persistence, please see the documentation for the Cassandra chart\n enabled: false\n config:\n cluster_name: jaeger\n seed_size: 1\n dc_name: dc1\n rack_name: rack1\n endpoint_snitch: GossipingPropertyFileSnitch\n# End: Override values on the Cassandra subchart to customize for Jaeger\n\n# Begin: Default values for the various components of Jaeger\n# This chart has been based on the Kubernetes integration found in the following repo:\n# https://github.com/jaegertracing/jaeger-kubernetes/blob/master/production/jaeger-production-template.yml\n#\n# This is the jaeger-cassandra-schema Job which sets up the Cassandra schema for\n# use by Jaeger\nschema:\n annotations: {}\n image: jaegertracing/jaeger-cassandra-schema\n pullPolicy: IfNotPresent\n # Acceptable values are test and prod. Default is for production use.\n mode: prod\n resources: {}\n # limits:\n # cpu: 500m\n # memory: 512Mi\n # requests:\n # cpu: 256m\n # memory: 128Mi\n ## Additional pod labels\n ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/\n podLabels: {}\n\n# Begin: Override values on the Elasticsearch subchart to customize for Jaeger\nelasticsearch:\n image:\n tag: \"5.4\"\n cluster:\n name: \"tracing\"\n data:\n persistence:\n enabled: false\n rbac:\n create: false\n\nagent:\n enabled: true\n annotations: {}\n image: jaegertracing/jaeger-agent\n pullPolicy: IfNotPresent\n collector:\n host: null\n port: null\n cmdlineParams: {}\n daemonset:\n useHostPort: false\n service:\n annotations: {}\n # List of IP ranges that are allowed to access the load balancer (if supported)\n loadBalancerSourceRanges: []\n type: ClusterIP\n # zipkinThriftPort :accept zipkin.thrift over compact thrift protocol\n zipkinThriftPort: 5775\n # compactPort: accept jaeger.thrift over compact thrift protocol\n compactPort: 6831\n # binaryPort: accept jaeger.thrift over binary thrift protocol\n binaryPort: 6832\n # samplingPort: (HTTP) serve configs, sampling strategies\n samplingPort: 5778\n resources: {}\n # limits:\n # cpu: 500m\n # memory: 512Mi\n # requests:\n # cpu: 256m\n # memory: 128Mi\n nodeSelector: {}\n podAnnotations: {}\n ## Additional pod labels\n ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/\n podLabels: {}\n ## Allow the scheduling on tainted nodes (requires Kubernetes \u003e= 1.6)\n ## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/\n tolerations: []\n useHostNetwork: false\n dnsPolicy: ClusterFirst\n\ncollector:\n enabled: true\n annotations: {}\n image: jaegertracing/jaeger-collector\n pullPolicy: IfNotPresent\n dnsPolicy: ClusterFirst\n cmdlineParams: {}\n replicaCount: 1\n service:\n annotations: {}\n # List of IP ranges that are allowed to access the load balancer (if supported)\n loadBalancerSourceRanges: []\n type: ClusterIP\n # tchannelPort: used by jaeger-agent to send spans in jaeger.thrift format\n tchannelPort: 14267\n # httpPort: can accept spans directly from clients in jaeger.thrift format\n httpPort: 14268\n # can accept Zipkin spans in JSON or Thrift\n zipkinPort: 9411\n healthCheckPort: 14269\n resources: {}\n # limits:\n # cpu: 1\n # memory: 1Gi\n # requests:\n # cpu: 500m\n # memory: 512Mi\n nodeSelector: {}\n podAnnotations: {}\n ## Additional pod labels\n ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/\n podLabels: {}\n ## Allow the scheduling on tainted nodes (requires Kubernetes \u003e= 1.6)\n ## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/\n tolerations: []\n\nquery:\n enabled: true\n annotations: {}\n image: jaegertracing/jaeger-query\n pullPolicy: IfNotPresent\n dnsPolicy: ClusterFirst\n cmdlineParams: {}\n healthCheckPort: 16687\n replicaCount: 1\n service:\n annotations: {}\n type: ClusterIP\n # List of IP ranges that are allowed to access the load balancer (if supported)\n loadBalancerSourceRanges: []\n # queryPort: externally accessible port for UI and API\n queryPort: 80\n # targetPort: the internal port the UI and API are exposed on\n targetPort: 16686\n ingress:\n enabled: false\n annotations: {}\n # Used to create an Ingress record.\n # hosts:\n # - chart-example.local\n # annotations:\n # kubernetes.io/ingress.class: nginx\n # kubernetes.io/tls-acme: \"true\"\n # tls:\n # Secrets must be manually created in the namespace.\n # - secretName: chart-example-tls\n # hosts:\n # - chart-example.local\n resources: {}\n # limits:\n # cpu: 500m\n # memory: 512Mi\n # requests:\n # cpu: 256m\n # memory: 128Mi\n nodeSelector: {}\n podAnnotations: {}\n ## Additional pod labels\n ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/\n podLabels: {}\n ## Allow the scheduling on tainted nodes (requires Kubernetes \u003e= 1.6)\n ## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/\n tolerations: []\n\nspark:\n enabled: false\n annotations: {}\n image: jaegertracing/spark-dependencies\n tag: latest\n pullPolicy: Always\n schedule: \"49 23 * * *\"\n successfulJobsHistoryLimit: 5\n failedJobsHistoryLimit: 5\n resources: {}\n # limits:\n # cpu: 500m\n # memory: 512Mi\n # requests:\n # cpu: 256m\n # memory: 128Mi\n nodeSelector: {}\n ## Additional pod labels\n ## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/\n podLabels: {}\n ## Allow the scheduling on tainted nodes (requires Kubernetes \u003e= 1.6)\n ## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/\n tolerations: []\n# End: Default values for the various components of Jaeger\n\nhotrod:\n enabled: false\n replicaCount: 1\n image:\n repository: jaegertracing/example-hotrod\n tag: latest\n pullPolicy: Always\n service:\n annotations: {}\n name: hotrod\n type: ClusterIP\n # List of IP ranges that are allowed to access the load balancer (if supported)\n loadBalancerSourceRanges: []\n externalPort: 80\n internalPort: 8080\n ingress:\n enabled: false\n # Used to create Ingress record (should be used with service.type: ClusterIP).\n hosts:\n - chart-example.local\n annotations: {}\n # kubernetes.io/ingress.class: nginx\n # kubernetes.io/tls-acme: \"true\"\n tls:\n # Secrets must be manually created in the namespace.\n # - secretName: chart-example-tls\n # hosts:\n # - chart-example.local\n resources: {}\n # We usually recommend not to specify default resources and to leave this as a conscious\n # choice for the user. This also increases chances charts run on environments with little\n # resources, such as Minikube. If you do want to specify resources, uncomment the following\n # lines, adjust them as necessary, and remove the curly braces after 'resources:'.\n # limits:\n # cpu: 100m\n # memory: 128Mi\n # requests:\n # cpu: 100m\n # memory: 128Mi\n tracing:\n host: null\n port: 6831\n", + "upstream": "https://github.com/helm/charts/tree/f839d88d087511eb163b12a394c05a63f10d5ee4/incubator/jaeger", + "metadata": { + "applicationType": "helm", + "icon": "https://camo.githubusercontent.com/afa87494e0753b4b1f5719a2f35aa5263859dffb/687474703a2f2f6a61656765722e72656164746865646f63732e696f2f656e2f6c61746573742f696d616765732f6a61656765722d766563746f722e737667", + "name": "jaeger", + "releaseNotes": "Adds tolerations labels for Jaeger pods (#6255)", + "version": "0.7.0" + }, + "contentSHA": "a0b9a245ede7d0965c3766329b78e0be1bcc907f61c559c54c592818c6ed3eb1" + } +} \ No newline at end of file diff --git a/integration/init/jaeger-helm/expected/base/agent-ds.yaml b/integration/init/jaeger-helm/expected/base/agent-ds.yaml new file mode 100644 index 000000000..5f1c21f51 --- /dev/null +++ b/integration/init/jaeger-helm/expected/base/agent-ds.yaml @@ -0,0 +1,42 @@ +apiVersion: extensions/v1beta1 +kind: DaemonSet +metadata: + labels: + app: jaeger + chart: jaeger-0.7.0 + component: agent + heritage: Tiller + jaeger-infra: agent-daemonset + release: jaeger + name: jaeger-agent +spec: + template: + metadata: + labels: + app: jaeger + component: agent + jaeger-infra: agent-instance + release: jaeger + spec: + containers: + - env: + - name: COLLECTOR_HOST_PORT + valueFrom: + configMapKeyRef: + key: collector.host-port + name: jaeger + image: jaegertracing/jaeger-agent:1.4.1 + imagePullPolicy: IfNotPresent + name: jaeger-agent + ports: + - containerPort: 5775 + protocol: UDP + - containerPort: 6831 + protocol: UDP + - containerPort: 6832 + protocol: UDP + - containerPort: 5778 + protocol: TCP + resources: {} + dnsPolicy: ClusterFirst + nodeSelector: {} diff --git a/integration/init/jaeger-helm/expected/base/agent-svc.yaml b/integration/init/jaeger-helm/expected/base/agent-svc.yaml new file mode 100644 index 000000000..f4964ab77 --- /dev/null +++ b/integration/init/jaeger-helm/expected/base/agent-svc.yaml @@ -0,0 +1,35 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app: jaeger + chart: jaeger-0.7.0 + component: agent + heritage: Tiller + jaeger-infra: agent-service + release: jaeger + name: jaeger-agent +spec: + ports: + - name: agent-zipkin-thrift + port: 5775 + protocol: UDP + targetPort: 5775 + - name: agent-compact + port: 6831 + protocol: UDP + targetPort: 6831 + - name: agent-binary + port: 6832 + protocol: UDP + targetPort: 6832 + - name: agent-sampling + port: 5778 + protocol: TCP + targetPort: 5778 + selector: + app: jaeger + component: agent + jaeger-infra: agent-instance + release: jaeger + type: ClusterIP diff --git a/integration/init/jaeger-helm/expected/base/cassandra-schema-job.yaml b/integration/init/jaeger-helm/expected/base/cassandra-schema-job.yaml new file mode 100644 index 000000000..b127b723c --- /dev/null +++ b/integration/init/jaeger-helm/expected/base/cassandra-schema-job.yaml @@ -0,0 +1,44 @@ +apiVersion: batch/v1 +kind: Job +metadata: + labels: + app: jaeger + chart: jaeger-0.7.0 + component: cassandra-schema + heritage: Tiller + jaeger-infra: cassandra-schema-job + release: jaeger + name: jaeger-cassandra-schema +spec: + activeDeadlineSeconds: 120 + template: + metadata: + name: jaeger-cassandra-schema + spec: + containers: + - env: + - name: CQLSH_HOST + valueFrom: + configMapKeyRef: + key: cassandra.servers + name: jaeger + - name: MODE + valueFrom: + configMapKeyRef: + key: cassandra.schema.mode + name: jaeger + - name: DATACENTER + valueFrom: + configMapKeyRef: + key: cassandra.datacenter.name + name: jaeger + - name: CASSANDRA_PORT + valueFrom: + configMapKeyRef: + key: cassandra.port + name: jaeger + image: jaegertracing/jaeger-cassandra-schema:1.4.1 + imagePullPolicy: IfNotPresent + name: jaeger-cassandra-schema + resources: {} + restartPolicy: OnFailure diff --git a/integration/init/jaeger-helm/expected/base/charts/cassandra/templates/service.yaml b/integration/init/jaeger-helm/expected/base/charts/cassandra/templates/service.yaml new file mode 100644 index 000000000..456f359a0 --- /dev/null +++ b/integration/init/jaeger-helm/expected/base/charts/cassandra/templates/service.yaml @@ -0,0 +1,31 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app: cassandra + chart: cassandra-0.9.3 + heritage: Tiller + release: jaeger + name: jaeger-cassandra +spec: + clusterIP: None + ports: + - name: intra + port: 7000 + targetPort: 7000 + - name: tls + port: 7001 + targetPort: 7001 + - name: jmx + port: 7199 + targetPort: 7199 + - name: cql + port: 9042 + targetPort: 9042 + - name: thrift + port: 9160 + targetPort: 9160 + selector: + app: cassandra + release: jaeger + type: ClusterIP diff --git a/integration/init/jaeger-helm/expected/base/charts/cassandra/templates/statefulset.yaml b/integration/init/jaeger-helm/expected/base/charts/cassandra/templates/statefulset.yaml new file mode 100644 index 000000000..20ee7f1d8 --- /dev/null +++ b/integration/init/jaeger-helm/expected/base/charts/cassandra/templates/statefulset.yaml @@ -0,0 +1,98 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + labels: + app: cassandra + chart: cassandra-0.9.3 + heritage: Tiller + release: jaeger + name: jaeger-cassandra +spec: + podManagementPolicy: OrderedReady + replicas: 3 + selector: + matchLabels: + app: cassandra + release: jaeger + serviceName: jaeger-cassandra + template: + metadata: + labels: + app: cassandra + release: jaeger + spec: + containers: + - env: + - name: CASSANDRA_SEEDS + value: jaeger-cassandra-0.jaeger-cassandra.default.svc.cluster.local + - name: MAX_HEAP_SIZE + value: 2048M + - name: HEAP_NEWSIZE + value: 512M + - name: CASSANDRA_ENDPOINT_SNITCH + value: GossipingPropertyFileSnitch + - name: CASSANDRA_CLUSTER_NAME + value: jaeger + - name: CASSANDRA_DC + value: dc1 + - name: CASSANDRA_RACK + value: rack1 + - name: CASSANDRA_START_RPC + value: "false" + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + image: cassandra:3.11 + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - /bin/sh + - -c + - exec nodetool decommission + livenessProbe: + exec: + command: + - /bin/sh + - -c + - nodetool status + failureThreshold: 3 + initialDelaySeconds: 90 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 5 + name: jaeger-cassandra + ports: + - containerPort: 7000 + name: intra + - containerPort: 7001 + name: tls + - containerPort: 7199 + name: jmx + - containerPort: 9042 + name: cql + - containerPort: 9160 + name: thrift + readinessProbe: + exec: + command: + - /bin/sh + - -c + - nodetool status | grep -E "^UN\s+${POD_IP}" + failureThreshold: 3 + initialDelaySeconds: 90 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 5 + resources: {} + volumeMounts: + - mountPath: /var/lib/cassandra + name: data + terminationGracePeriodSeconds: 30 + volumes: + - emptyDir: {} + name: data + updateStrategy: + type: OnDelete diff --git a/integration/init/jaeger-helm/expected/base/collector-deploy.yaml b/integration/init/jaeger-helm/expected/base/collector-deploy.yaml new file mode 100644 index 000000000..3803e6d3d --- /dev/null +++ b/integration/init/jaeger-helm/expected/base/collector-deploy.yaml @@ -0,0 +1,88 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + labels: + app: jaeger + chart: jaeger-0.7.0 + component: collector + heritage: Tiller + jaeger-infra: collector-deployment + release: jaeger + name: jaeger-collector +spec: + replicas: 1 + strategy: + type: Recreate + template: + metadata: + labels: + app: jaeger + component: collector + jaeger-infra: collector-pod + release: jaeger + spec: + containers: + - env: + - name: SPAN_STORAGE_TYPE + valueFrom: + configMapKeyRef: + key: span-storage.type + name: jaeger + - name: CASSANDRA_SERVERS + valueFrom: + configMapKeyRef: + key: cassandra.servers + name: jaeger + - name: CASSANDRA_PORT + valueFrom: + configMapKeyRef: + key: cassandra.port + name: jaeger + - name: CASSANDRA_KEYSPACE + valueFrom: + configMapKeyRef: + key: cassandra.keyspace + name: jaeger + - name: COLLECTOR_PORT + valueFrom: + configMapKeyRef: + key: collector.port + name: jaeger + - name: COLLECTOR_HTTP_PORT + valueFrom: + configMapKeyRef: + key: collector.http-port + name: jaeger + - name: COLLECTOR_ZIPKIN_HTTP_PORT + valueFrom: + configMapKeyRef: + key: collector.zipkin.http-port + name: jaeger + image: jaegertracing/jaeger-collector:1.4.1 + imagePullPolicy: IfNotPresent + livenessProbe: + httpGet: + port: healthcheck + initialDelaySeconds: 10 + name: jaeger-collector + ports: + - containerPort: 14267 + name: tchannel + protocol: TCP + - containerPort: 14268 + name: http + protocol: TCP + - containerPort: 14269 + name: healthcheck + protocol: TCP + - containerPort: 9411 + name: zipkin + protocol: TCP + readinessProbe: + httpGet: + port: healthcheck + initialDelaySeconds: 10 + resources: {} + dnsPolicy: ClusterFirst + nodeSelector: {} + restartPolicy: Always diff --git a/integration/init/jaeger-helm/expected/base/collector-svc.yaml b/integration/init/jaeger-helm/expected/base/collector-svc.yaml new file mode 100644 index 000000000..81b4c141b --- /dev/null +++ b/integration/init/jaeger-helm/expected/base/collector-svc.yaml @@ -0,0 +1,31 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app: jaeger + chart: jaeger-0.7.0 + component: collector + heritage: Tiller + jaeger-infra: collector-service + release: jaeger + name: jaeger-collector +spec: + ports: + - name: jaeger-collector-tchannel + port: 14267 + protocol: TCP + targetPort: tchannel + - name: jaeger-collector-http + port: 14268 + protocol: TCP + targetPort: http + - name: jaeger-collector-zipkin + port: 9411 + protocol: TCP + targetPort: zipkin + selector: + app: jaeger + component: collector + jaeger-infra: collector-pod + release: jaeger + type: ClusterIP diff --git a/integration/init/jaeger-helm/expected/base/common-cm.yaml b/integration/init/jaeger-helm/expected/base/common-cm.yaml new file mode 100644 index 000000000..6e1c496dc --- /dev/null +++ b/integration/init/jaeger-helm/expected/base/common-cm.yaml @@ -0,0 +1,29 @@ +apiVersion: v1 +data: + cassandra.contact-points: jaeger-cassandra:9042 + cassandra.datacenter.name: dc1 + cassandra.keyspace: jaeger_v1_dc1 + cassandra.port: "9042" + cassandra.schema.mode: prod + cassandra.servers: jaeger-cassandra + collector.host-port: jaeger-collector:14267 + collector.http-port: "14268" + collector.port: "14267" + collector.zipkin.http-port: "9411" + es.nodes-wan-only: "false" + es.password: changeme + es.server-urls: http://elasticsearch:9200 + es.username: elastic + hotrod.agent-host-port: jaeger-agent-agent:6831 + query.health-check-http-port: "16687" + query.port: "16686" + span-storage.type: cassandra +kind: ConfigMap +metadata: + labels: + app: jaeger + chart: jaeger-0.7.0 + heritage: Tiller + jaeger-infra: common-configmap + release: jaeger + name: jaeger diff --git a/integration/init/jaeger-helm/expected/base/kustomization.yaml b/integration/init/jaeger-helm/expected/base/kustomization.yaml new file mode 100644 index 000000000..ce5890f66 --- /dev/null +++ b/integration/init/jaeger-helm/expected/base/kustomization.yaml @@ -0,0 +1,13 @@ +kind: "" +apiversion: "" +resources: +- agent-ds.yaml +- agent-svc.yaml +- cassandra-schema-job.yaml +- charts/cassandra/templates/service.yaml +- charts/cassandra/templates/statefulset.yaml +- collector-deploy.yaml +- collector-svc.yaml +- common-cm.yaml +- query-deploy.yaml +- query-svc.yaml diff --git a/integration/init/jaeger-helm/expected/base/query-deploy.yaml b/integration/init/jaeger-helm/expected/base/query-deploy.yaml new file mode 100644 index 000000000..bb4928949 --- /dev/null +++ b/integration/init/jaeger-helm/expected/base/query-deploy.yaml @@ -0,0 +1,69 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + labels: + app: jaeger + chart: jaeger-0.7.0 + component: query + heritage: Tiller + jaeger-infra: query-deployment + release: jaeger + name: jaeger-query +spec: + replicas: 1 + strategy: + type: Recreate + template: + metadata: + labels: + app: jaeger + component: query + jaeger-infra: query-pod + release: jaeger + spec: + containers: + - env: + - name: SPAN_STORAGE_TYPE + valueFrom: + configMapKeyRef: + key: span-storage.type + name: jaeger + - name: CASSANDRA_SERVERS + valueFrom: + configMapKeyRef: + key: cassandra.servers + name: jaeger + - name: CASSANDRA_PORT + valueFrom: + configMapKeyRef: + key: cassandra.port + name: jaeger + - name: CASSANDRA_KEYSPACE + valueFrom: + configMapKeyRef: + key: cassandra.keyspace + name: jaeger + - name: QUERY_PORT + valueFrom: + configMapKeyRef: + key: query.port + name: jaeger + - name: QUERY_HEALTH_CHECK_HTTP_PORT + valueFrom: + configMapKeyRef: + key: query.health-check-http-port + name: jaeger + image: jaegertracing/jaeger-query:1.4.1 + imagePullPolicy: IfNotPresent + name: jaeger-query + ports: + - containerPort: 16686 + protocol: TCP + readinessProbe: + httpGet: + path: / + port: 16687 + resources: {} + dnsPolicy: ClusterFirst + nodeSelector: {} + restartPolicy: Always diff --git a/integration/init/jaeger-helm/expected/base/query-svc.yaml b/integration/init/jaeger-helm/expected/base/query-svc.yaml new file mode 100644 index 000000000..e8926dff3 --- /dev/null +++ b/integration/init/jaeger-helm/expected/base/query-svc.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app: jaeger + chart: jaeger-0.7.0 + component: query + heritage: Tiller + jaeger-infra: query-service + release: jaeger + name: jaeger-query +spec: + ports: + - name: jaeger-query + port: 80 + protocol: TCP + targetPort: 16686 + selector: + app: jaeger + component: query + jaeger-infra: query-pod + release: jaeger + type: ClusterIP diff --git a/integration/init/jaeger-helm/expected/overlays/ship/kustomization.yaml b/integration/init/jaeger-helm/expected/overlays/ship/kustomization.yaml new file mode 100644 index 000000000..c80bb2245 --- /dev/null +++ b/integration/init/jaeger-helm/expected/overlays/ship/kustomization.yaml @@ -0,0 +1,4 @@ +kind: "" +apiversion: "" +bases: +- ../../base diff --git a/integration/init/jaeger-helm/expected/rendered.yaml b/integration/init/jaeger-helm/expected/rendered.yaml new file mode 100644 index 000000000..4c4147a32 --- /dev/null +++ b/integration/init/jaeger-helm/expected/rendered.yaml @@ -0,0 +1,499 @@ +apiVersion: v1 +data: + cassandra.contact-points: jaeger-cassandra:9042 + cassandra.datacenter.name: dc1 + cassandra.keyspace: jaeger_v1_dc1 + cassandra.port: "9042" + cassandra.schema.mode: prod + cassandra.servers: jaeger-cassandra + collector.host-port: jaeger-collector:14267 + collector.http-port: "14268" + collector.port: "14267" + collector.zipkin.http-port: "9411" + es.nodes-wan-only: "false" + es.password: changeme + es.server-urls: http://elasticsearch:9200 + es.username: elastic + hotrod.agent-host-port: jaeger-agent-agent:6831 + query.health-check-http-port: "16687" + query.port: "16686" + span-storage.type: cassandra +kind: ConfigMap +metadata: + labels: + app: jaeger + chart: jaeger-0.7.0 + heritage: Tiller + jaeger-infra: common-configmap + release: jaeger + name: jaeger +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: jaeger + chart: jaeger-0.7.0 + component: agent + heritage: Tiller + jaeger-infra: agent-service + release: jaeger + name: jaeger-agent +spec: + ports: + - name: agent-zipkin-thrift + port: 5775 + protocol: UDP + targetPort: 5775 + - name: agent-compact + port: 6831 + protocol: UDP + targetPort: 6831 + - name: agent-binary + port: 6832 + protocol: UDP + targetPort: 6832 + - name: agent-sampling + port: 5778 + protocol: TCP + targetPort: 5778 + selector: + app: jaeger + component: agent + jaeger-infra: agent-instance + release: jaeger + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: cassandra + chart: cassandra-0.9.3 + heritage: Tiller + release: jaeger + name: jaeger-cassandra +spec: + clusterIP: None + ports: + - name: intra + port: 7000 + targetPort: 7000 + - name: tls + port: 7001 + targetPort: 7001 + - name: jmx + port: 7199 + targetPort: 7199 + - name: cql + port: 9042 + targetPort: 9042 + - name: thrift + port: 9160 + targetPort: 9160 + selector: + app: cassandra + release: jaeger + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: jaeger + chart: jaeger-0.7.0 + component: collector + heritage: Tiller + jaeger-infra: collector-service + release: jaeger + name: jaeger-collector +spec: + ports: + - name: jaeger-collector-tchannel + port: 14267 + protocol: TCP + targetPort: tchannel + - name: jaeger-collector-http + port: 14268 + protocol: TCP + targetPort: http + - name: jaeger-collector-zipkin + port: 9411 + protocol: TCP + targetPort: zipkin + selector: + app: jaeger + component: collector + jaeger-infra: collector-pod + release: jaeger + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: jaeger + chart: jaeger-0.7.0 + component: query + heritage: Tiller + jaeger-infra: query-service + release: jaeger + name: jaeger-query +spec: + ports: + - name: jaeger-query + port: 80 + protocol: TCP + targetPort: 16686 + selector: + app: jaeger + component: query + jaeger-infra: query-pod + release: jaeger + type: ClusterIP +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + labels: + app: cassandra + chart: cassandra-0.9.3 + heritage: Tiller + release: jaeger + name: jaeger-cassandra +spec: + podManagementPolicy: OrderedReady + replicas: 3 + selector: + matchLabels: + app: cassandra + release: jaeger + serviceName: jaeger-cassandra + template: + metadata: + labels: + app: cassandra + release: jaeger + spec: + containers: + - env: + - name: CASSANDRA_SEEDS + value: jaeger-cassandra-0.jaeger-cassandra.default.svc.cluster.local + - name: MAX_HEAP_SIZE + value: 2048M + - name: HEAP_NEWSIZE + value: 512M + - name: CASSANDRA_ENDPOINT_SNITCH + value: GossipingPropertyFileSnitch + - name: CASSANDRA_CLUSTER_NAME + value: jaeger + - name: CASSANDRA_DC + value: dc1 + - name: CASSANDRA_RACK + value: rack1 + - name: CASSANDRA_START_RPC + value: "false" + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + image: cassandra:3.11 + imagePullPolicy: IfNotPresent + lifecycle: + preStop: + exec: + command: + - /bin/sh + - -c + - exec nodetool decommission + livenessProbe: + exec: + command: + - /bin/sh + - -c + - nodetool status + failureThreshold: 3 + initialDelaySeconds: 90 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 5 + name: jaeger-cassandra + ports: + - containerPort: 7000 + name: intra + - containerPort: 7001 + name: tls + - containerPort: 7199 + name: jmx + - containerPort: 9042 + name: cql + - containerPort: 9160 + name: thrift + readinessProbe: + exec: + command: + - /bin/sh + - -c + - nodetool status | grep -E "^UN\s+${POD_IP}" + failureThreshold: 3 + initialDelaySeconds: 90 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 5 + resources: {} + volumeMounts: + - mountPath: /var/lib/cassandra + name: data + terminationGracePeriodSeconds: 30 + volumes: + - emptyDir: {} + name: data + updateStrategy: + type: OnDelete +--- +apiVersion: batch/v1 +kind: Job +metadata: + labels: + app: jaeger + chart: jaeger-0.7.0 + component: cassandra-schema + heritage: Tiller + jaeger-infra: cassandra-schema-job + release: jaeger + name: jaeger-cassandra-schema +spec: + activeDeadlineSeconds: 120 + template: + metadata: + name: jaeger-cassandra-schema + spec: + containers: + - env: + - name: CQLSH_HOST + valueFrom: + configMapKeyRef: + key: cassandra.servers + name: jaeger + - name: MODE + valueFrom: + configMapKeyRef: + key: cassandra.schema.mode + name: jaeger + - name: DATACENTER + valueFrom: + configMapKeyRef: + key: cassandra.datacenter.name + name: jaeger + - name: CASSANDRA_PORT + valueFrom: + configMapKeyRef: + key: cassandra.port + name: jaeger + image: jaegertracing/jaeger-cassandra-schema:1.4.1 + imagePullPolicy: IfNotPresent + name: jaeger-cassandra-schema + resources: {} + restartPolicy: OnFailure +--- +apiVersion: extensions/v1beta1 +kind: DaemonSet +metadata: + labels: + app: jaeger + chart: jaeger-0.7.0 + component: agent + heritage: Tiller + jaeger-infra: agent-daemonset + release: jaeger + name: jaeger-agent +spec: + template: + metadata: + labels: + app: jaeger + component: agent + jaeger-infra: agent-instance + release: jaeger + spec: + containers: + - env: + - name: COLLECTOR_HOST_PORT + valueFrom: + configMapKeyRef: + key: collector.host-port + name: jaeger + image: jaegertracing/jaeger-agent:1.4.1 + imagePullPolicy: IfNotPresent + name: jaeger-agent + ports: + - containerPort: 5775 + protocol: UDP + - containerPort: 6831 + protocol: UDP + - containerPort: 6832 + protocol: UDP + - containerPort: 5778 + protocol: TCP + resources: {} + dnsPolicy: ClusterFirst + nodeSelector: {} +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + labels: + app: jaeger + chart: jaeger-0.7.0 + component: collector + heritage: Tiller + jaeger-infra: collector-deployment + release: jaeger + name: jaeger-collector +spec: + replicas: 1 + strategy: + type: Recreate + template: + metadata: + labels: + app: jaeger + component: collector + jaeger-infra: collector-pod + release: jaeger + spec: + containers: + - env: + - name: SPAN_STORAGE_TYPE + valueFrom: + configMapKeyRef: + key: span-storage.type + name: jaeger + - name: CASSANDRA_SERVERS + valueFrom: + configMapKeyRef: + key: cassandra.servers + name: jaeger + - name: CASSANDRA_PORT + valueFrom: + configMapKeyRef: + key: cassandra.port + name: jaeger + - name: CASSANDRA_KEYSPACE + valueFrom: + configMapKeyRef: + key: cassandra.keyspace + name: jaeger + - name: COLLECTOR_PORT + valueFrom: + configMapKeyRef: + key: collector.port + name: jaeger + - name: COLLECTOR_HTTP_PORT + valueFrom: + configMapKeyRef: + key: collector.http-port + name: jaeger + - name: COLLECTOR_ZIPKIN_HTTP_PORT + valueFrom: + configMapKeyRef: + key: collector.zipkin.http-port + name: jaeger + image: jaegertracing/jaeger-collector:1.4.1 + imagePullPolicy: IfNotPresent + livenessProbe: + httpGet: + port: healthcheck + initialDelaySeconds: 10 + name: jaeger-collector + ports: + - containerPort: 14267 + name: tchannel + protocol: TCP + - containerPort: 14268 + name: http + protocol: TCP + - containerPort: 14269 + name: healthcheck + protocol: TCP + - containerPort: 9411 + name: zipkin + protocol: TCP + readinessProbe: + httpGet: + port: healthcheck + initialDelaySeconds: 10 + resources: {} + dnsPolicy: ClusterFirst + nodeSelector: {} + restartPolicy: Always +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + labels: + app: jaeger + chart: jaeger-0.7.0 + component: query + heritage: Tiller + jaeger-infra: query-deployment + release: jaeger + name: jaeger-query +spec: + replicas: 1 + strategy: + type: Recreate + template: + metadata: + labels: + app: jaeger + component: query + jaeger-infra: query-pod + release: jaeger + spec: + containers: + - env: + - name: SPAN_STORAGE_TYPE + valueFrom: + configMapKeyRef: + key: span-storage.type + name: jaeger + - name: CASSANDRA_SERVERS + valueFrom: + configMapKeyRef: + key: cassandra.servers + name: jaeger + - name: CASSANDRA_PORT + valueFrom: + configMapKeyRef: + key: cassandra.port + name: jaeger + - name: CASSANDRA_KEYSPACE + valueFrom: + configMapKeyRef: + key: cassandra.keyspace + name: jaeger + - name: QUERY_PORT + valueFrom: + configMapKeyRef: + key: query.port + name: jaeger + - name: QUERY_HEALTH_CHECK_HTTP_PORT + valueFrom: + configMapKeyRef: + key: query.health-check-http-port + name: jaeger + image: jaegertracing/jaeger-query:1.4.1 + imagePullPolicy: IfNotPresent + name: jaeger-query + ports: + - containerPort: 16686 + protocol: TCP + readinessProbe: + httpGet: + path: / + port: 16687 + resources: {} + dnsPolicy: ClusterFirst + nodeSelector: {} + restartPolicy: Always diff --git a/integration/init/jaeger-helm/metadata.yaml b/integration/init/jaeger-helm/metadata.yaml new file mode 100644 index 000000000..114fba5e4 --- /dev/null +++ b/integration/init/jaeger-helm/metadata.yaml @@ -0,0 +1,3 @@ +upstream: "https://github.com/helm/charts/tree/f839d88d087511eb163b12a394c05a63f10d5ee4/incubator/jaeger" +args: ["--prefer-git"] +skip_cleanup: false diff --git a/pkg/helm/repo_add.go b/pkg/helm/repo_add.go new file mode 100644 index 000000000..10bc749ec --- /dev/null +++ b/pkg/helm/repo_add.go @@ -0,0 +1,140 @@ +/* +Copyright The Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/*This file was edited by Replicated in 2018 to + - expose `helm repo add` as a function + - silence the error output from the cobra command. +*/ + +package helm + +import ( + "bufio" + "bytes" + "fmt" + "io" + + "github.com/pkg/errors" + + "syscall" + + "golang.org/x/crypto/ssh/terminal" + "k8s.io/helm/pkg/getter" + "k8s.io/helm/pkg/helm/helmpath" + "k8s.io/helm/pkg/repo" +) + +type repoAddCmd struct { + name string + url string + username string + password string + home helmpath.Home + noupdate bool + + certFile string + keyFile string + caFile string + + out io.Writer +} + +func RepoAdd(name, url, home string) (string, error) { + var buf bytes.Buffer + bufWriter := bufio.NewWriter(&buf) + + toRepoAdd := repoAddCmd{ + name: name, + url: url, + + out: bufWriter, + } + + if home != "" { + toRepoAdd.home = helmpath.Home(home) + } else { + path, err := helmHome() + if err != nil { + return "", errors.Wrap(err, "unable to find home directory") + } + toRepoAdd.home = helmpath.Home(path) + } + + err := toRepoAdd.run() + return buf.String(), err +} + +func (a *repoAddCmd) run() error { + if a.username != "" && a.password == "" { + fmt.Fprint(a.out, "Password:") + password, err := readPassword() + fmt.Fprintln(a.out) + if err != nil { + return err + } + a.password = password + } + + if err := addRepository(a.name, a.url, a.username, a.password, a.home, a.certFile, a.keyFile, a.caFile, a.noupdate); err != nil { + return err + } + fmt.Fprintf(a.out, "%q has been added to your repositories\n", a.name) + return nil +} + +func readPassword() (string, error) { + password, err := terminal.ReadPassword(int(syscall.Stdin)) + if err != nil { + return "", err + } + return string(password), nil +} + +func addRepository(name, url, username, password string, home helmpath.Home, certFile, keyFile, caFile string, noUpdate bool) error { + f, err := repo.LoadRepositoriesFile(home.RepositoryFile()) + if err != nil { + return err + } + + if noUpdate && f.Has(name) { + return fmt.Errorf("repository name (%s) already exists, please specify a different name", name) + } + + cif := home.CacheIndex(name) + c := repo.Entry{ + Name: name, + Cache: cif, + URL: url, + Username: username, + Password: password, + CertFile: certFile, + KeyFile: keyFile, + CAFile: caFile, + } + + r, err := repo.NewChartRepository(&c, getter.All(settings)) + if err != nil { + return err + } + + if err := r.DownloadIndexFile(home.Cache()); err != nil { + return fmt.Errorf("Looks like %q is not a valid chart repository or cannot be reached: %s", url, err.Error()) + } + + f.Update(&c) + + return f.WriteFile(home.RepositoryFile(), 0644) +} diff --git a/pkg/helm/shared.go b/pkg/helm/shared.go index 2944988ac..88e38a278 100644 --- a/pkg/helm/shared.go +++ b/pkg/helm/shared.go @@ -203,3 +203,15 @@ func prettyError(err error) error { func helmHome() (string, error) { return filepath.Abs(constants.InternalTempHelmHome) } + +func checkArgsLength(argsReceived int, requiredArgs ...string) error { + expectedNum := len(requiredArgs) + if argsReceived != expectedNum { + arg := "arguments" + if expectedNum == 1 { + arg = "argument" + } + return fmt.Errorf("This command needs %v %s: %s", expectedNum, arg, strings.Join(requiredArgs, ", ")) + } + return nil +} diff --git a/pkg/lifecycle/render/helm/commands.go b/pkg/lifecycle/render/helm/commands.go index 7902a49c7..7276d25d8 100644 --- a/pkg/lifecycle/render/helm/commands.go +++ b/pkg/lifecycle/render/helm/commands.go @@ -3,9 +3,7 @@ package helm import ( "fmt" "os" - "path/filepath" - "github.com/ghodss/yaml" "github.com/go-kit/kit/log" "github.com/go-kit/kit/log/level" "github.com/pkg/errors" @@ -18,9 +16,10 @@ import ( // Commands are Helm commands that are available to the Ship binary. type Commands interface { Init() error - MaybeDependencyUpdate(chartRoot string) error + MaybeDependencyUpdate(chartRoot string, requirements chartutil.Requirements) error Template(chartName string, args []string) error Fetch(chartRef, repoURL, version, dest, home string) error + RepoAdd(name, url, home string) error } type helmCommands struct { @@ -45,28 +44,8 @@ func (h *helmCommands) Init() error { return errors.Wrapf(err, "helm init: %s", output) } -func (h *helmCommands) MaybeDependencyUpdate(chartRoot string) error { +func (h *helmCommands) MaybeDependencyUpdate(chartRoot string, requirements chartutil.Requirements) error { debug := level.Debug(log.With(h.logger, "method", "maybeDependencyUpdate")) - - requirementsExists, err := h.fs.Exists(filepath.Join(chartRoot, "requirements.yaml")) - if err != nil { - return errors.Wrap(err, "check requirements yaml existence") - } - - if !requirementsExists { - return nil - } - - requirementsB, err := h.fs.ReadFile(filepath.Join(chartRoot, "requirements.yaml")) - if err != nil { - return errors.Wrap(err, "read requirements yaml") - } - - requirements := chartutil.Requirements{} - if err := yaml.Unmarshal(requirementsB, &requirements); err != nil { - return errors.Wrap(err, "unmarshal requirements yaml") - } - allEmpty := true for _, dependency := range requirements.Dependencies { if dependency.Repository != "" { @@ -116,3 +95,11 @@ func (h *helmCommands) dependencyUpdate(chartRoot string) error { } return dependencyCommand.Execute() } + +func (h *helmCommands) RepoAdd(name, url, home string) error { + outstring, err := helm.RepoAdd(name, url, home) + if err != nil { + return errors.Wrap(err, fmt.Sprintf("helm repo add failed, output %q", outstring)) + } + return nil +} diff --git a/pkg/lifecycle/render/helm/template.go b/pkg/lifecycle/render/helm/template.go index 08cf0d5a5..e5efe4cb4 100644 --- a/pkg/lifecycle/render/helm/template.go +++ b/pkg/lifecycle/render/helm/template.go @@ -10,6 +10,9 @@ import ( "regexp" "strings" + "k8s.io/helm/pkg/chartutil" + + "github.com/emosbaugh/yaml" "github.com/go-kit/kit/log" "github.com/go-kit/kit/log/level" "github.com/pkg/errors" @@ -25,6 +28,10 @@ import ( "github.com/spf13/viper" ) +const ( + HelmChartIncubatorURL = "https://kubernetes-charts-incubator.storage.googleapis.com/" +) + // Templater is something that can consume and render a helm chart pulled by ship. // the chart should already be present at the specified path. type Templater interface { @@ -128,8 +135,28 @@ func (f *LocalTemplater) Template( return errors.Wrap(err, "init helm client") } + debug.Log("event", "helm.get.requirements") + requirements, err := f.getChartRequirements(chartRoot) + if err != nil { + return errors.Wrap(err, "get chart requirements") + } + + debug.Log("event", "helm.repo.add") + absTempHelmHome, err := filepath.Abs(constants.InternalTempHelmHome) + if err != nil { + return errors.Wrap(err, "make absolute helm temp home") + } + for _, dependency := range requirements.Dependencies { + if dependency.Repository == HelmChartIncubatorURL { + if err := f.Commands.RepoAdd("incubator", HelmChartIncubatorURL, absTempHelmHome); err != nil { + return errors.Wrap(err, "add helm repo") + } + break + } + } + debug.Log("event", "helm.dependency.update") - if err := f.Commands.MaybeDependencyUpdate(chartRoot); err != nil { + if err := f.Commands.MaybeDependencyUpdate(chartRoot, requirements); err != nil { return errors.Wrap(err, "update helm dependencies") } @@ -176,6 +203,30 @@ func (f *LocalTemplater) Template( return f.cleanUpAndOutputRenderedFiles(rootFs, asset, tempRenderedChartDir) } +func (f *LocalTemplater) getChartRequirements(chartRoot string) (chartutil.Requirements, error) { + requirements := chartutil.Requirements{} + + requirementsExists, err := f.FS.Exists(filepath.Join(chartRoot, "requirements.yaml")) + if err != nil { + return requirements, errors.Wrap(err, "check requirements yaml existence") + } + + if !requirementsExists { + return requirements, nil + } + + requirementsB, err := f.FS.ReadFile(filepath.Join(chartRoot, "requirements.yaml")) + if err != nil { + return requirements, errors.Wrap(err, "read requirements yaml") + } + + if err := yaml.Unmarshal(requirementsB, &requirements); err != nil { + return requirements, errors.Wrap(err, "unmarshal requirements yaml") + } + + return requirements, nil +} + // checks to see if the specified arg is present in the list. If it is not, adds it set to the specified value func addArgIfNotPresent(existingArgs []string, newArg string, newDefault string) []string { for _, arg := range existingArgs { diff --git a/pkg/lifecycle/render/helm/template_test.go b/pkg/lifecycle/render/helm/template_test.go index f6eafe61b..1a5eeae41 100644 --- a/pkg/lifecycle/render/helm/template_test.go +++ b/pkg/lifecycle/render/helm/template_test.go @@ -3,8 +3,11 @@ package helm import ( "os" "path" + "path/filepath" "testing" + "k8s.io/helm/pkg/chartutil" + "github.com/golang/mock/gomock" "github.com/replicatedhq/libyaml" "github.com/replicatedhq/ship/pkg/api" @@ -20,6 +23,7 @@ import ( "github.com/spf13/afero" "github.com/spf13/viper" "github.com/stretchr/testify/require" + "gopkg.in/yaml.v2" ) func TestLocalTemplater(t *testing.T) { @@ -36,6 +40,8 @@ func TestLocalTemplater(t *testing.T) { expectHelmOpts *matchers.Is ontemplate func(req *require.Assertions, mockFs afero.Afero) func(chartRoot string, args []string) error state state2.VersionedState + requirements *chartutil.Requirements + repoAdd []string }{ { name: "helm test proper args", @@ -101,6 +107,25 @@ func TestLocalTemplater(t *testing.T) { channelName: "1-2-3---------frobnitz", expectedChannelName: "1-2-3---------frobnitz", }, + { + name: "helm values from asset value with incubator requirement", + describe: "calls helm repo add", + expectError: "", + helmValues: map[string]interface{}{ + "service.clusterIP": "10.3.9.2", + }, + expectedHelmValues: []string{ + "--set", "service.clusterIP=10.3.9.2", + }, + requirements: &chartutil.Requirements{ + Dependencies: []*chartutil.Dependency{ + { + Repository: "https://kubernetes-charts-incubator.storage.googleapis.com/", + }, + }, + }, + repoAdd: []string{"incubator", "https://kubernetes-charts-incubator.storage.googleapis.com/"}, + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { @@ -148,6 +173,13 @@ func TestLocalTemplater(t *testing.T) { test.expectedHelmValues..., ) + if test.requirements != nil { + requirementsB, err := yaml.Marshal(test.requirements) + req.NoError(err) + err = mockFs.WriteFile(path.Join(chartRoot, "requirements.yaml"), requirementsB, 0755) + req.NoError(err) + } + templateArgs := append( []string{ "--output-dir", ".ship/tmp/chartrendered", @@ -159,7 +191,22 @@ func TestLocalTemplater(t *testing.T) { templateArgs = addArgIfNotPresent(templateArgs, "--namespace", "default") mockCommands.EXPECT().Init().Return(nil) - mockCommands.EXPECT().MaybeDependencyUpdate(chartRoot).Return(nil) + if test.requirements != nil { + absTempHelmHome, err := filepath.Abs(constants.InternalTempHelmHome) + req.NoError(err) + mockCommands.EXPECT().RepoAdd(test.repoAdd[0], test.repoAdd[1], absTempHelmHome) + + requirementsB, err := mockFs.ReadFile(filepath.Join(chartRoot, "requirements.yaml")) + req.NoError(err) + chartRequirements := chartutil.Requirements{} + err = yaml.Unmarshal(requirementsB, &chartRequirements) + req.NoError(err) + + mockCommands.EXPECT().MaybeDependencyUpdate(chartRoot, chartRequirements).Return(nil) + } else { + mockCommands.EXPECT().MaybeDependencyUpdate(chartRoot, chartutil.Requirements{}).Return(nil) + } + if test.ontemplate != nil { mockCommands.EXPECT().Template(chartRoot, templateArgs).DoAndReturn(test.ontemplate(req, mockFs)) } else { diff --git a/pkg/test-mocks/helm/commands_mock.go b/pkg/test-mocks/helm/commands_mock.go index c03ffa3ae..92081a151 100644 --- a/pkg/test-mocks/helm/commands_mock.go +++ b/pkg/test-mocks/helm/commands_mock.go @@ -8,6 +8,7 @@ import ( reflect "reflect" gomock "github.com/golang/mock/gomock" + chartutil "k8s.io/helm/pkg/chartutil" ) // MockCommands is a mock of Commands interface @@ -58,15 +59,27 @@ func (mr *MockCommandsMockRecorder) Init() *gomock.Call { } // MaybeDependencyUpdate mocks base method -func (m *MockCommands) MaybeDependencyUpdate(arg0 string) error { - ret := m.ctrl.Call(m, "MaybeDependencyUpdate", arg0) +func (m *MockCommands) MaybeDependencyUpdate(arg0 string, arg1 chartutil.Requirements) error { + ret := m.ctrl.Call(m, "MaybeDependencyUpdate", arg0, arg1) ret0, _ := ret[0].(error) return ret0 } // MaybeDependencyUpdate indicates an expected call of MaybeDependencyUpdate -func (mr *MockCommandsMockRecorder) MaybeDependencyUpdate(arg0 interface{}) *gomock.Call { - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MaybeDependencyUpdate", reflect.TypeOf((*MockCommands)(nil).MaybeDependencyUpdate), arg0) +func (mr *MockCommandsMockRecorder) MaybeDependencyUpdate(arg0, arg1 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MaybeDependencyUpdate", reflect.TypeOf((*MockCommands)(nil).MaybeDependencyUpdate), arg0, arg1) +} + +// RepoAdd mocks base method +func (m *MockCommands) RepoAdd(arg0, arg1, arg2 string) error { + ret := m.ctrl.Call(m, "RepoAdd", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// RepoAdd indicates an expected call of RepoAdd +func (mr *MockCommandsMockRecorder) RepoAdd(arg0, arg1, arg2 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RepoAdd", reflect.TypeOf((*MockCommands)(nil).RepoAdd), arg0, arg1, arg2) } // Template mocks base method