Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Helm chart #11

Merged
merged 28 commits into from
Sep 22, 2021
Merged

Add Helm chart #11

merged 28 commits into from
Sep 22, 2021

Conversation

d-kuro
Copy link
Contributor

@d-kuro d-kuro commented Aug 9, 2021

refs: #10

  • Add accurate Helm Chart
  • Update documentation to use Helm Chart
  • Changed e2e tests to use Helm instead of kustomzie

Review Points

TODOs

  • Release the Chart after merging this pull request

Diffs

=== RUN   TestChart
=== RUN   TestChart/namespace/accurate
    chart_test.go:54: object was not found: not found [namespace/accurate]
=== RUN   TestChart/customresourcedefinition.apiextensions.k8s.io/subnamespaces.accurate.cybozu.com
=== RUN   TestChart/serviceaccount/accurate/accurate-controller-manager
=== RUN   TestChart/role.rbac.authorization.k8s.io/accurate/accurate-leader-election-role
=== RUN   TestChart/clusterrole.rbac.authorization.k8s.io/accurate-manager-role
=== RUN   TestChart/clusterrole.rbac.authorization.k8s.io/accurate-subnamespace-editor-role
=== RUN   TestChart/clusterrole.rbac.authorization.k8s.io/accurate-subnamespace-viewer-role
=== RUN   TestChart/rolebinding.rbac.authorization.k8s.io/accurate/accurate-leader-election-rolebinding
=== RUN   TestChart/clusterrolebinding.rbac.authorization.k8s.io/accurate-manager-admin
=== RUN   TestChart/clusterrolebinding.rbac.authorization.k8s.io/accurate-manager-rolebinding
=== RUN   TestChart/configmap/accurate/accurate-config-6tkg9g6bm6
    chart_test.go:54: configmap/accurate/accurate-config mismatch (-want +got):
          &v1.ConfigMap{
          	TypeMeta:   {Kind: "ConfigMap", APIVersion: "v1"},
          	ObjectMeta: {Name: "accurate-config", Namespace: "accurate"},
          	Immutable:  nil,
        - 	Data: map[string]string{
        - 		"config.yaml": (
        - 			"""
        - 			# Labels to be propagated to sub-namespaces.
        - 			# It is also possible to specify a glob pattern that can be interpreted by Go's "path.Match" func.
        - 			# https://pkg.go.dev/path#Match
        - 			labelKeys:
        - 			- team
        - 			
        - 			# Annotations to be propagated to sub-namespaces.
        - 			# It is also possible to specify a glob pattern that can be interpreted by Go's "path.Match" func.
        - 			# https://pkg.go.dev/path#Match
        - 			annotationKeys:
        - 			# An example to propagate an annotation for MetalLB
        - 			# https://metallb.universe.tf/usage/#requesting-specific-ips
        - 			- metallb.universe.tf/address-pool
        - 			
        - 			# List of GVK for namespace-scoped resources that can be propagated.
        - 			# Any namespace-scoped resource is allowed.
        - 			watches:
        - 			- group: rbac.authorization.k8s.io
        - 			  version: v1
        - 			  kind: Role
        - 			- group: rbac.authorization.k8s.io
        - 			  version: v1
        - 			  kind: RoleBinding
        - 			- version: v1
        - 			  kind: Secret
        - 			"""
        - 		),
        - 	},
        + 	Data: map[string]string{
        + 		"config.yaml": (
        + 			"""
        + 			watches: 
        + 			  - group: rbac.authorization.k8s.io
        + 			    kind: Role
        + 			    version: v1
        + 			  - group: rbac.authorization.k8s.io
        + 			    kind: RoleBinding
        + 			    version: v1
        + 			  - kind: Secret
        + 			    version: v1
        + 			"""
        + 		),
        + 	},
          	BinaryData: nil,
          }
=== RUN   TestChart/service/accurate/accurate-webhook-service
=== RUN   TestChart/deployment.apps/accurate/accurate-controller-manager
    chart_test.go:54: deployment.apps/accurate/accurate-controller-manager mismatch (-want +got):
          &v1.Deployment{
          	TypeMeta:   {Kind: "Deployment", APIVersion: "apps/v1"},
          	ObjectMeta: {Name: "accurate-controller-manager", Namespace: "accurate"},
          	Spec: v1.DeploymentSpec{
          		Replicas: &2,
          		Selector: &{MatchLabels: {"app.kubernetes.io/component": "controller", "app.kubernetes.io/name": "accurate"}},
          		Template: v1.PodTemplateSpec{
          			ObjectMeta: v1.ObjectMeta{
          				... // 9 identical fields
          				DeletionGracePeriodSeconds: nil,
          				Labels:                     {"app.kubernetes.io/component": "controller", "app.kubernetes.io/name": "accurate"},
        - 				Annotations:                nil,
        + 				Annotations: map[string]string{
        + 					"checksum/config": "c63a34726123e77a197a658c7d16af9ef6428654dc5fad90326d3a1c07091e5d",
        + 				},
          				OwnerReferences: nil,
          				Finalizers:      nil,
          				... // 2 identical fields
          			},
          			Spec: v1.PodSpec{
          				Volumes: []v1.Volume{
          					{Name: "cert", VolumeSource: {Secret: &{SecretName: "webhook-server-cert", DefaultMode: &420}}},
          					{
          						Name: "config",
          						VolumeSource: v1.VolumeSource{
          							... // 16 identical fields
          							FC:        nil,
          							AzureFile: nil,
          							ConfigMap: &v1.ConfigMapVolumeSource{
        - 								LocalObjectReference: v1.LocalObjectReference{Name: "accurate-config-6tkg9g6bm6"},
        + 								LocalObjectReference: v1.LocalObjectReference{Name: "accurate-config"},
          								Items:                nil,
          								DefaultMode:          nil,
          								Optional:             nil,
          							},
          							VsphereVolume: nil,
          							Quobyte:       nil,
          							... // 8 identical fields
          						},
          					},
          				},
          				InitContainers: nil,
          				Containers:     {{Name: "manager", Image: "ghcr.io/cybozu-go/accurate:0.1.0", Ports: {{Name: "webhook-server", ContainerPort: 9443, Protocol: "TCP"}, {Name: "health", ContainerPort: 8081, Protocol: "TCP"}, {Name: "metrics", ContainerPort: 8080, Protocol: "TCP"}}, Env: {{Name: "POD_NAMESPACE", ValueFrom: &{FieldRef: &{FieldPath: "metadata.namespace"}}}}, ...}},
          				... // 32 identical fields
          			},
          		},
          		Strategy:        {},
          		MinReadySeconds: 0,
          		... // 3 identical fields
          	},
          	Status: {},
          }
=== RUN   TestChart/certificate.cert-manager.io/accurate/accurate-serving-cert
=== RUN   TestChart/issuer.cert-manager.io/accurate/accurate-selfsigned-issuer
=== RUN   TestChart/mutatingwebhookconfiguration.admissionregistration.k8s.io/accurate-mutating-webhook-configuration
=== RUN   TestChart/validatingwebhookconfiguration.admissionregistration.k8s.io/accurate-validating-webhook-configuration
--- FAIL: TestChart (0.02s)
    --- FAIL: TestChart/namespace/accurate (0.00s)
    --- PASS: TestChart/customresourcedefinition.apiextensions.k8s.io/subnamespaces.accurate.cybozu.com (0.00s)
    --- PASS: TestChart/serviceaccount/accurate/accurate-controller-manager (0.00s)
    --- PASS: TestChart/role.rbac.authorization.k8s.io/accurate/accurate-leader-election-role (0.00s)
    --- PASS: TestChart/clusterrole.rbac.authorization.k8s.io/accurate-manager-role (0.00s)
    --- PASS: TestChart/clusterrole.rbac.authorization.k8s.io/accurate-subnamespace-editor-role (0.00s)
    --- PASS: TestChart/clusterrole.rbac.authorization.k8s.io/accurate-subnamespace-viewer-role (0.00s)
    --- PASS: TestChart/rolebinding.rbac.authorization.k8s.io/accurate/accurate-leader-election-rolebinding (0.00s)
    --- PASS: TestChart/clusterrolebinding.rbac.authorization.k8s.io/accurate-manager-admin (0.00s)
    --- PASS: TestChart/clusterrolebinding.rbac.authorization.k8s.io/accurate-manager-rolebinding (0.00s)
    --- FAIL: TestChart/configmap/accurate/accurate-config-6tkg9g6bm6 (0.00s)
    --- PASS: TestChart/service/accurate/accurate-webhook-service (0.00s)
    --- FAIL: TestChart/deployment.apps/accurate/accurate-controller-manager (0.00s)
    --- PASS: TestChart/certificate.cert-manager.io/accurate/accurate-serving-cert (0.00s)
    --- PASS: TestChart/issuer.cert-manager.io/accurate/accurate-selfsigned-issuer (0.00s)
    --- PASS: TestChart/mutatingwebhookconfiguration.admissionregistration.k8s.io/accurate-mutating-webhook-configuration (0.00s)
    --- PASS: TestChart/validatingwebhookconfiguration.admissionregistration.k8s.io/accurate-validating-webhook-configuration (0.00s)
FAIL
FAIL	tests	0.467s
FAIL

@d-kuro d-kuro self-assigned this Aug 9, 2021
Signed-off-by: d-kuro <[email protected]>
@d-kuro d-kuro force-pushed the d-kuro/helm branch 13 times, most recently from f6350f5 to 849dfbf Compare August 18, 2021 03:28
Signed-off-by: d-kuro <[email protected]>
Signed-off-by: d-kuro <[email protected]>
@d-kuro d-kuro marked this pull request as ready for review August 20, 2021 14:42
@d-kuro d-kuro requested a review from ymmt2005 August 20, 2021 14:43
.github/workflows/helm-release.yaml Outdated Show resolved Hide resolved
.github/workflows/helm-release.yaml Outdated Show resolved Hide resolved
.github/workflows/helm-release.yaml Outdated Show resolved Hide resolved
.cr.yaml Show resolved Hide resolved
.github/workflows/helm.yaml Show resolved Hide resolved
containers:
- name: manager
image: "{{ .Values.image.repository }}:{{ default .Chart.AppVersion .Values.image.tag }}"
{{- with .Values.image.pullPolicy }}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens when pullPolicy is not set? Is it always set?
If so, can we simplify this as below?

          imagePullPolicy: {{ .Values.image.pullPolicy }}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default is undefined and the imagePullPolicy field is not added if not specified.

pullPolicy: # Always

I will explicitly set IfNotPresent.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, if pullPolicy is not set, this would render as follows, right?

spec:
  containers:
  - name: manager
    image: ...
    imagePullPolicy:   # empty

I don't like this. Could you omit imagePullPolicy: altogether when pullPolicy is not set?

charts/accurate/templates/deployment.yaml Show resolved Hide resolved
charts/accurate/templates/rolebinding.yaml Outdated Show resolved Hide resolved
charts/accurate/README.md Outdated Show resolved Hide resolved
@d-kuro d-kuro force-pushed the d-kuro/helm branch 2 times, most recently from e6c44a4 to f7890ab Compare September 15, 2021 01:21
@d-kuro
Copy link
Contributor Author

d-kuro commented Sep 15, 2021

@ymmt2005 @zoetrope

I fixed the pull request.

Review Poinsts:

  • Chart release by merging into the main branch
  • Remove helm-docs deps
  • Generate RBAC, CRDs, Webhook manifests from controller-gen manifests
    • 3acf5a9
    • Use kustomize to convert the manifests file generated by controller-gen into a Helm template

.github/workflows/helm-release.yaml Show resolved Hide resolved
charts/accurate/README.md Outdated Show resolved Hide resolved
name: {{ template "accurate.fullname" . }}-additional-resources
subjects:
- kind: ServiceAccount
name: {{ template "accurate.fullname" . }}-controller-manager
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then, users cannot stop creating a ServiceAccount, right?

containers:
- name: manager
image: "{{ .Values.image.repository }}:{{ default .Chart.AppVersion .Values.image.tag }}"
{{- with .Values.image.pullPolicy }}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, if pullPolicy is not set, this would render as follows, right?

spec:
  containers:
  - name: manager
    image: ...
    imagePullPolicy:   # empty

I don't like this. Could you omit imagePullPolicy: altogether when pullPolicy is not set?

{{- with .Values.image.pullPolicy }}
imagePullPolicy: {{ . }}
{{- end }}
{{- with .Values.controller.extraArgs }}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, it renders as follows, right?

    args:  # empty

Same above. Please fix.

Makefile Show resolved Hide resolved
@d-kuro
Copy link
Contributor Author

d-kuro commented Sep 22, 2021

@ymmt2005

Then, users cannot stop creating a ServiceAccount, right?

Is there a case where a User wants to stop creating a ServiceAccount?
I didn't understand why it was a problem to have to create a ServiceAccount.

So, if pullPolicy is not set, this would render as follows, right?

No, if the field is empty the with block will not be rendered.

Rendering with the default values will result in the following YAML:

helm template -n accurate accurate ./charts/accurate
<snip>
# Source: accurate/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: accurate-controller-manager
  namespace: accurate
  labels:
    app.kubernetes.io/component: controller
    helm.sh/chart: accurate-0.1.0
    app.kubernetes.io/name: accurate
    app.kubernetes.io/version: "0.1.0"
    app.kubernetes.io/managed-by: Helm
spec:
  replicas: 2
  selector:
    matchLabels:
      app.kubernetes.io/component: controller
  template:
    metadata:
      annotations:
        checksum/config: 856d9f37889d4ef4ad9a5bbec38b558ab0e1c5db0dac189d4e9aceadf52be133
      labels:
        app.kubernetes.io/component: controller
    spec:
      containers:
        - name: manager
          image: "ghcr.io/cybozu-go/accurate:0.1.0"
          ports:
            - containerPort: 9443
              name: webhook-server
              protocol: TCP
            - containerPort: 8081
              name: health
              protocol: TCP
            - containerPort: 8080
              name: metrics
              protocol: TCP
          resources:
            requests:
              cpu: 100m
              memory: 20Mi
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
          env:
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          livenessProbe:
            httpGet:
              path: /healthz
              port: health
            initialDelaySeconds: 15
            periodSeconds: 20
          readinessProbe:
            httpGet:
              path: /readyz
              port: health
            initialDelaySeconds: 5
            periodSeconds: 10
          volumeMounts:
            - mountPath: /tmp/k8s-webhook-server/serving-certs
              name: cert
              readOnly: true
            - mountPath: /etc/accurate
              name: config
      securityContext:
        runAsNonRoot: true
      serviceAccountName: accurate-controller-manager
      terminationGracePeriodSeconds: 10
      volumes:
        - name: cert
          secret:
            defaultMode: 420
            secretName: webhook-server-cert
        - configMap:
            name: accurate-config
          name: config
<snip>

@d-kuro d-kuro requested review from zoetrope and ymmt2005 September 22, 2021 00:16
@ymmt2005
Copy link
Member

@d-kuro

Is there a case where a user wants to stop creating a ServiceAccount?
I didn't understand why it was a problem to have to create a ServiceAccount.

I don't think users want to avoid creating a ServiceAccount, but my point is that
even when a user chooses not to create a ServiceAccount, the Helm template should
generate a valid manifest. Currently, it does not seem so.

I'd like either one of the following:

  • Users cannot avoid creating a ServiceAccount, or
  • Helm can generate a valid manifest if a user chooses not to create a ServiceAccount

No, if the field is empty the with block will not be rendered.

I see. Thank you.

@d-kuro
Copy link
Contributor Author

d-kuro commented Sep 22, 2021

@ymmt2005

I see, thank you for comments.

I don't think users want to avoid creating a ServiceAccount, but my point is that
even when a user chooses not to create a ServiceAccount, the Helm template should
generate a valid manifest. Currently, it does not seem so.

I'd like either one of the following:

  • Users cannot avoid creating a ServiceAccount, or
  • Helm can generate a valid manifest if a user chooses not to create a ServiceAccount

In the _helpers.tpl file, there was a flag whether or not to create a ServiceAccount, which was automatically created by the helm init command.

{{- if .Values.serviceAccount.create }}

This is no longer in use and has been removed in the following commit:

ded4522

So a ServiceAccount is always created.

@ymmt2005
Copy link
Member

Great!

@d-kuro
Copy link
Contributor Author

d-kuro commented Sep 22, 2021

Difference from kustomize

    --- FAIL: TestHelmCharts/namespace/accurate (0.00s)
        chart_test.go:51: object was not found: not found [namespace/accurate]
    --- FAIL: TestHelmCharts/serviceaccount/accurate/accurate-controller-manager (0.00s)
        chart_test.go:51: serviceaccount/accurate/accurate-controller-manager mismatch (-want +got):
              &v1.ServiceAccount{
              	TypeMeta: {Kind: "ServiceAccount", APIVersion: "v1"},
              	ObjectMeta: v1.ObjectMeta{
              		... // 8 identical fields
              		DeletionTimestamp:          nil,
              		DeletionGracePeriodSeconds: nil,
              		Labels: map[string]string{
            + 			"app.kubernetes.io/managed-by": "Helm",
              			"app.kubernetes.io/name":       "accurate",
            + 			"app.kubernetes.io/version":    "0.1.0",
            + 			"helm.sh/chart":                "accurate-0.1.0",
              		},
              		Annotations:     nil,
              		OwnerReferences: nil,
              		... // 3 identical fields
              	},
              	Secrets:                      nil,
              	ImagePullSecrets:             nil,
              	AutomountServiceAccountToken: nil,
              }
    --- FAIL: TestHelmCharts/role.rbac.authorization.k8s.io/accurate/accurate-leader-election-role (0.00s)
        chart_test.go:51: role.rbac.authorization.k8s.io/accurate/accurate-leader-election-role mismatch (-want +got):
              &v1.Role{
              	TypeMeta: {Kind: "Role", APIVersion: "rbac.authorization.k8s.io/v1"},
              	ObjectMeta: v1.ObjectMeta{
              		... // 8 identical fields
              		DeletionTimestamp:          nil,
              		DeletionGracePeriodSeconds: nil,
              		Labels: map[string]string{
            + 			"app.kubernetes.io/managed-by": "Helm",
              			"app.kubernetes.io/name":       "accurate",
            + 			"app.kubernetes.io/version":    "0.1.0",
            + 			"helm.sh/chart":                "accurate-0.1.0",
              		},
              		Annotations:     nil,
              		OwnerReferences: nil,
              		... // 3 identical fields
              	},
              	Rules: {{Verbs: {"get", "list", "watch", "create", ...}, APIGroups: {""}, Resources: {"configmaps"}}, {Verbs: {"get", "list", "watch", "create", ...}, APIGroups: {"coordination.k8s.io"}, Resources: {"leases"}}, {Verbs: {"create", "patch"}, APIGroups: {""}, Resources: {"events"}}},
              }
    --- FAIL: TestHelmCharts/clusterrole.rbac.authorization.k8s.io/accurate-manager-role (0.00s)
        chart_test.go:51: clusterrole.rbac.authorization.k8s.io/accurate-manager-role mismatch (-want +got):
              &v1.ClusterRole{
              	TypeMeta: {Kind: "ClusterRole", APIVersion: "rbac.authorization.k8s.io/v1"},
              	ObjectMeta: v1.ObjectMeta{
              		... // 8 identical fields
              		DeletionTimestamp:          nil,
              		DeletionGracePeriodSeconds: nil,
              		Labels: map[string]string{
            + 			"app.kubernetes.io/managed-by": "Helm",
              			"app.kubernetes.io/name":       "accurate",
            + 			"app.kubernetes.io/version":    "0.1.0",
            + 			"helm.sh/chart":                "accurate-0.1.0",
              		},
              		Annotations:     nil,
              		OwnerReferences: nil,
              		... // 3 identical fields
              	},
              	Rules:           {{Verbs: {"create", "delete", "get", "list", ...}, APIGroups: {""}, Resources: {"namespaces"}}, {Verbs: {"create", "delete", "get", "list", ...}, APIGroups: {"accurate.cybozu.com"}, Resources: {"subnamespaces"}}, {Verbs: {"update"}, APIGroups: {"accurate.cybozu.com"}, Resources: {"subnamespaces/finalizers"}}, {Verbs: {"get", "patch", "update"}, APIGroups: {"accurate.cybozu.com"}, Resources: {"subnamespaces/status"}}},
              	AggregationRule: nil,
              }
    --- FAIL: TestHelmCharts/clusterrole.rbac.authorization.k8s.io/accurate-subnamespace-editor-role (0.00s)
        chart_test.go:51: clusterrole.rbac.authorization.k8s.io/accurate-subnamespace-editor-role mismatch (-want +got):
              &v1.ClusterRole{
              	TypeMeta: {Kind: "ClusterRole", APIVersion: "rbac.authorization.k8s.io/v1"},
              	ObjectMeta: v1.ObjectMeta{
              		... // 8 identical fields
              		DeletionTimestamp:          nil,
              		DeletionGracePeriodSeconds: nil,
              		Labels: map[string]string{
            + 			"app.kubernetes.io/managed-by":                 "Helm",
              			"app.kubernetes.io/name":                       "accurate",
            + 			"app.kubernetes.io/version":                    "0.1.0",
            + 			"helm.sh/chart":                                "accurate-0.1.0",
              			"rbac.authorization.k8s.io/aggregate-to-admin": "true",
              			"rbac.authorization.k8s.io/aggregate-to-edit":  "true",
              		},
              		Annotations:     nil,
              		OwnerReferences: nil,
              		... // 3 identical fields
              	},
              	Rules:           {{Verbs: {"create", "delete", "get", "list", ...}, APIGroups: {"accurate.cybozu.com"}, Resources: {"subnamespaces"}}, {Verbs: {"get"}, APIGroups: {"accurate.cybozu.com"}, Resources: {"subnamespaces/status"}}},
              	AggregationRule: nil,
              }
    --- FAIL: TestHelmCharts/clusterrole.rbac.authorization.k8s.io/accurate-subnamespace-viewer-role (0.00s)
        chart_test.go:51: clusterrole.rbac.authorization.k8s.io/accurate-subnamespace-viewer-role mismatch (-want +got):
              &v1.ClusterRole{
              	TypeMeta: {Kind: "ClusterRole", APIVersion: "rbac.authorization.k8s.io/v1"},
              	ObjectMeta: v1.ObjectMeta{
              		... // 8 identical fields
              		DeletionTimestamp:          nil,
              		DeletionGracePeriodSeconds: nil,
              		Labels: map[string]string{
            + 			"app.kubernetes.io/managed-by":                "Helm",
              			"app.kubernetes.io/name":                      "accurate",
            + 			"app.kubernetes.io/version":                   "0.1.0",
            + 			"helm.sh/chart":                               "accurate-0.1.0",
              			"rbac.authorization.k8s.io/aggregate-to-view": "true",
              		},
              		Annotations:     nil,
              		OwnerReferences: nil,
              		... // 3 identical fields
              	},
              	Rules:           {{Verbs: {"get", "list", "watch"}, APIGroups: {"accurate.cybozu.com"}, Resources: {"subnamespaces"}}, {Verbs: {"get"}, APIGroups: {"accurate.cybozu.com"}, Resources: {"subnamespaces/status"}}},
              	AggregationRule: nil,
              }
    --- FAIL: TestHelmCharts/rolebinding.rbac.authorization.k8s.io/accurate/accurate-leader-election-rolebinding (0.00s)
        chart_test.go:51: rolebinding.rbac.authorization.k8s.io/accurate/accurate-leader-election-rolebinding mismatch (-want +got):
              &v1.RoleBinding{
              	TypeMeta: {Kind: "RoleBinding", APIVersion: "rbac.authorization.k8s.io/v1"},
              	ObjectMeta: v1.ObjectMeta{
              		... // 8 identical fields
              		DeletionTimestamp:          nil,
              		DeletionGracePeriodSeconds: nil,
              		Labels: map[string]string{
            + 			"app.kubernetes.io/managed-by": "Helm",
              			"app.kubernetes.io/name":       "accurate",
            + 			"app.kubernetes.io/version":    "0.1.0",
            + 			"helm.sh/chart":                "accurate-0.1.0",
              		},
              		Annotations:     nil,
              		OwnerReferences: nil,
              		... // 3 identical fields
              	},
              	Subjects: {{Kind: "ServiceAccount", Name: "accurate-controller-manager", Namespace: "accurate"}},
              	RoleRef:  {APIGroup: "rbac.authorization.k8s.io", Kind: "Role", Name: "accurate-leader-election-role"},
              }
    --- FAIL: TestHelmCharts/clusterrolebinding.rbac.authorization.k8s.io/accurate-manager-admin (0.00s)
        chart_test.go:51: clusterrolebinding.rbac.authorization.k8s.io/accurate-manager-admin mismatch (-want +got):
              &v1.ClusterRoleBinding{
              	TypeMeta: {Kind: "ClusterRoleBinding", APIVersion: "rbac.authorization.k8s.io/v1"},
              	ObjectMeta: v1.ObjectMeta{
              		... // 8 identical fields
              		DeletionTimestamp:          nil,
              		DeletionGracePeriodSeconds: nil,
              		Labels: map[string]string{
            + 			"app.kubernetes.io/managed-by": "Helm",
              			"app.kubernetes.io/name":       "accurate",
            + 			"app.kubernetes.io/version":    "0.1.0",
            + 			"helm.sh/chart":                "accurate-0.1.0",
              		},
              		Annotations:     nil,
              		OwnerReferences: nil,
              		... // 3 identical fields
              	},
              	Subjects: {{Kind: "ServiceAccount", Name: "accurate-controller-manager", Namespace: "accurate"}},
              	RoleRef:  {APIGroup: "rbac.authorization.k8s.io", Kind: "ClusterRole", Name: "admin"},
              }
    --- FAIL: TestHelmCharts/clusterrolebinding.rbac.authorization.k8s.io/accurate-manager-rolebinding (0.00s)
        chart_test.go:51: clusterrolebinding.rbac.authorization.k8s.io/accurate-manager-rolebinding mismatch (-want +got):
              &v1.ClusterRoleBinding{
              	TypeMeta: {Kind: "ClusterRoleBinding", APIVersion: "rbac.authorization.k8s.io/v1"},
              	ObjectMeta: v1.ObjectMeta{
              		... // 8 identical fields
              		DeletionTimestamp:          nil,
              		DeletionGracePeriodSeconds: nil,
              		Labels: map[string]string{
            + 			"app.kubernetes.io/managed-by": "Helm",
              			"app.kubernetes.io/name":       "accurate",
            + 			"app.kubernetes.io/version":    "0.1.0",
            + 			"helm.sh/chart":                "accurate-0.1.0",
              		},
              		Annotations:     nil,
              		OwnerReferences: nil,
              		... // 3 identical fields
              	},
              	Subjects: {{Kind: "ServiceAccount", Name: "accurate-controller-manager", Namespace: "accurate"}},
              	RoleRef:  {APIGroup: "rbac.authorization.k8s.io", Kind: "ClusterRole", Name: "accurate-manager-role"},
              }
    --- FAIL: TestHelmCharts/configmap/accurate/accurate-config-6tkg9g6bm6 (0.00s)
        chart_test.go:51: configmap/accurate/accurate-config mismatch (-want +got):
              &v1.ConfigMap{
              	TypeMeta: {Kind: "ConfigMap", APIVersion: "v1"},
              	ObjectMeta: v1.ObjectMeta{
              		... // 8 identical fields
              		DeletionTimestamp:          nil,
              		DeletionGracePeriodSeconds: nil,
            - 		Labels:                     nil,
            + 		Labels: map[string]string{
            + 			"app.kubernetes.io/managed-by": "Helm",
            + 			"app.kubernetes.io/name":       "accurate",
            + 			"app.kubernetes.io/version":    "0.1.0",
            + 			"helm.sh/chart":                "accurate-0.1.0",
            + 		},
              		Annotations:     nil,
              		OwnerReferences: nil,
              		... // 3 identical fields
              	},
              	Immutable: nil,
            - 	Data: map[string]string{
            - 		"config.yaml": (
            - 			"""
            - 			# Labels to be propagated to sub-namespaces.
            - 			# It is also possible to specify a glob pattern that can be interpreted by Go's "path.Match" func.
            - 			# https://pkg.go.dev/path#Match
            - 			labelKeys:
            - 			- team
            - 			
            - 			# Annotations to be propagated to sub-namespaces.
            - 			# It is also possible to specify a glob pattern that can be interpreted by Go's "path.Match" func.
            - 			# https://pkg.go.dev/path#Match
            - 			annotationKeys:
            - 			# An example to propagate an annotation for MetalLB
            - 			# https://metallb.universe.tf/usage/#requesting-specific-ips
            - 			- metallb.universe.tf/address-pool
            - 			
            - 			# List of GVK for namespace-scoped resources that can be propagated.
            - 			# Any namespace-scoped resource is allowed.
            - 			watches:
            - 			- group: rbac.authorization.k8s.io
            - 			  version: v1
            - 			  kind: Role
            - 			- group: rbac.authorization.k8s.io
            - 			  version: v1
            - 			  kind: RoleBinding
            - 			- version: v1
            - 			  kind: Secret
            - 			"""
            - 		),
            - 	},
            + 	Data: map[string]string{
            + 		"config.yaml": (
            + 			"""
            + 			watches: 
            + 			  - group: rbac.authorization.k8s.io
            + 			    kind: Role
            + 			    version: v1
            + 			  - group: rbac.authorization.k8s.io
            + 			    kind: RoleBinding
            + 			    version: v1
            + 			  - kind: Secret
            + 			    version: v1
            + 			"""
            + 		),
            + 	},
              	BinaryData: nil,
              }
    --- FAIL: TestHelmCharts/service/accurate/accurate-webhook-service (0.00s)
        chart_test.go:51: service/accurate/accurate-webhook-service mismatch (-want +got):
              &v1.Service{
              	TypeMeta: {Kind: "Service", APIVersion: "v1"},
              	ObjectMeta: v1.ObjectMeta{
              		... // 8 identical fields
              		DeletionTimestamp:          nil,
              		DeletionGracePeriodSeconds: nil,
              		Labels: map[string]string{
            + 			"app.kubernetes.io/managed-by": "Helm",
              			"app.kubernetes.io/name":       "accurate",
            + 			"app.kubernetes.io/version":    "0.1.0",
            + 			"helm.sh/chart":                "accurate-0.1.0",
              		},
              		Annotations:     nil,
              		OwnerReferences: nil,
              		... // 3 identical fields
              	},
              	Spec:   {Ports: {{Port: 443, TargetPort: {Type: 1, StrVal: "webhook-server"}}}, Selector: {"app.kubernetes.io/component": "controller", "app.kubernetes.io/name": "accurate"}},
              	Status: {},
              }
    --- FAIL: TestHelmCharts/deployment.apps/accurate/accurate-controller-manager (0.00s)
        chart_test.go:51: deployment.apps/accurate/accurate-controller-manager mismatch (-want +got):
              &v1.Deployment{
              	TypeMeta: {Kind: "Deployment", APIVersion: "apps/v1"},
              	ObjectMeta: v1.ObjectMeta{
              		... // 8 identical fields
              		DeletionTimestamp:          nil,
              		DeletionGracePeriodSeconds: nil,
              		Labels: map[string]string{
              			"app.kubernetes.io/component":  "controller",
            + 			"app.kubernetes.io/managed-by": "Helm",
              			"app.kubernetes.io/name":       "accurate",
            + 			"app.kubernetes.io/version":    "0.1.0",
            + 			"helm.sh/chart":                "accurate-0.1.0",
              		},
              		Annotations:     nil,
              		OwnerReferences: nil,
              		... // 3 identical fields
              	},
              	Spec: v1.DeploymentSpec{
              		Replicas: &2,
              		Selector: &{MatchLabels: {"app.kubernetes.io/component": "controller", "app.kubernetes.io/name": "accurate"}},
              		Template: v1.PodTemplateSpec{
              			ObjectMeta: v1.ObjectMeta{
              				... // 9 identical fields
              				DeletionGracePeriodSeconds: nil,
              				Labels:                     {"app.kubernetes.io/component": "controller", "app.kubernetes.io/name": "accurate"},
            - 				Annotations:                nil,
            + 				Annotations: map[string]string{
            + 					"checksum/config": "856d9f37889d4ef4ad9a5bbec38b558ab0e1c5db0dac189d4e9aceadf52be133",
            + 				},
              				OwnerReferences: nil,
              				Finalizers:      nil,
              				... // 2 identical fields
              			},
              			Spec: v1.PodSpec{
              				Volumes: []v1.Volume{
              					{Name: "cert", VolumeSource: {Secret: &{SecretName: "webhook-server-cert", DefaultMode: &420}}},
              					{
              						Name: "config",
              						VolumeSource: v1.VolumeSource{
              							... // 16 identical fields
              							FC:        nil,
              							AzureFile: nil,
              							ConfigMap: &v1.ConfigMapVolumeSource{
            - 								LocalObjectReference: v1.LocalObjectReference{Name: "accurate-config-6tkg9g6bm6"},
            + 								LocalObjectReference: v1.LocalObjectReference{Name: "accurate-config"},
              								Items:                nil,
              								DefaultMode:          nil,
              								Optional:             nil,
              							},
              							VsphereVolume: nil,
              							Quobyte:       nil,
              							... // 8 identical fields
              						},
              					},
              				},
              				InitContainers: nil,
              				Containers:     {{Name: "manager", Image: "ghcr.io/cybozu-go/accurate:0.1.0", Ports: {{Name: "webhook-server", ContainerPort: 9443, Protocol: "TCP"}, {Name: "health", ContainerPort: 8081, Protocol: "TCP"}, {Name: "metrics", ContainerPort: 8080, Protocol: "TCP"}}, Env: {{Name: "POD_NAMESPACE", ValueFrom: &{FieldRef: &{FieldPath: "metadata.namespace"}}}}, ...}},
              				... // 32 identical fields
              			},
              		},
              		Strategy:        {},
              		MinReadySeconds: 0,
              		... // 3 identical fields
              	},
              	Status: {},
              }
    --- FAIL: TestHelmCharts/certificate.cert-manager.io/accurate/accurate-serving-cert (0.00s)
        chart_test.go:51: certificate.cert-manager.io/accurate/accurate-serving-cert mismatch (-want +got):
              &unstructured.Unstructured{
              	Object: map[string]interface{}{
              		"apiVersion": string("cert-manager.io/v1"),
              		"kind":       string("Certificate"),
              		"metadata": map[string]interface{}{
              			"labels": map[string]interface{}{
            + 				"app.kubernetes.io/managed-by": string("Helm"),
              				"app.kubernetes.io/name":       string("accurate"),
            + 				"app.kubernetes.io/version":    string("0.1.0"),
            + 				"helm.sh/chart":                string("accurate-0.1.0"),
              			},
              			"name":      string("accurate-serving-cert"),
              			"namespace": string("accurate"),
              		},
              		"spec": map[string]interface{}{"dnsNames": []interface{}{string("accurate-webhook-service.accurate.svc"), string("accurate-webhook-service.accurate.svc.cluster.local")}, "issuerRef": map[string]interface{}{"kind": string("Issuer"), "name": string("accurate-selfsigned-issuer")}, "secretName": string("webhook-server-cert")},
              	},
              }
    --- FAIL: TestHelmCharts/issuer.cert-manager.io/accurate/accurate-selfsigned-issuer (0.00s)
        chart_test.go:51: issuer.cert-manager.io/accurate/accurate-selfsigned-issuer mismatch (-want +got):
              &unstructured.Unstructured{
              	Object: map[string]interface{}{
              		"apiVersion": string("cert-manager.io/v1"),
              		"kind":       string("Issuer"),
              		"metadata": map[string]interface{}{
              			"labels": map[string]interface{}{
            + 				"app.kubernetes.io/managed-by": string("Helm"),
              				"app.kubernetes.io/name":       string("accurate"),
            + 				"app.kubernetes.io/version":    string("0.1.0"),
            + 				"helm.sh/chart":                string("accurate-0.1.0"),
              			},
              			"name":      string("accurate-selfsigned-issuer"),
              			"namespace": string("accurate"),
              		},
              		"spec": map[string]interface{}{"selfSigned": map[string]interface{}{}},
              	},
              }
    --- FAIL: TestHelmCharts/mutatingwebhookconfiguration.admissionregistration.k8s.io/accurate-mutating-webhook-configuration (0.00s)
        chart_test.go:51: mutatingwebhookconfiguration.admissionregistration.k8s.io/accurate-mutating-webhook-configuration mismatch (-want +got):
              &v1.MutatingWebhookConfiguration{
              	TypeMeta: {Kind: "MutatingWebhookConfiguration", APIVersion: "admissionregistration.k8s.io/v1"},
              	ObjectMeta: v1.ObjectMeta{
              		... // 8 identical fields
              		DeletionTimestamp:          nil,
              		DeletionGracePeriodSeconds: nil,
              		Labels: map[string]string{
            + 			"app.kubernetes.io/managed-by": "Helm",
              			"app.kubernetes.io/name":       "accurate",
            + 			"app.kubernetes.io/version":    "0.1.0",
            + 			"helm.sh/chart":                "accurate-0.1.0",
              		},
              		Annotations:     {"cert-manager.io/inject-ca-from": "accurate/accurate-serving-cert"},
              		OwnerReferences: nil,
              		... // 3 identical fields
              	},
              	Webhooks: {{Name: "msubnamespace.kb.io", ClientConfig: {Service: &{Namespace: "accurate", Name: "accurate-webhook-service", Path: &"/mutate-accurate-cybozu-com-v1-subnamespace"}}, Rules: {{Operations: {"CREATE", "UPDATE"}, Rule: {APIGroups: {"accurate.cybozu.com"}, APIVersions: {"v1"}, Resources: {"subnamespaces"}}}}, FailurePolicy: &"Fail", ...}},
              }
    --- FAIL: TestHelmCharts/validatingwebhookconfiguration.admissionregistration.k8s.io/accurate-validating-webhook-configuration (0.00s)
        chart_test.go:51: validatingwebhookconfiguration.admissionregistration.k8s.io/accurate-validating-webhook-configuration mismatch (-want +got):
              &v1.ValidatingWebhookConfiguration{
              	TypeMeta: {Kind: "ValidatingWebhookConfiguration", APIVersion: "admissionregistration.k8s.io/v1"},
              	ObjectMeta: v1.ObjectMeta{
              		... // 8 identical fields
              		DeletionTimestamp:          nil,
              		DeletionGracePeriodSeconds: nil,
              		Labels: map[string]string{
            + 			"app.kubernetes.io/managed-by": "Helm",
              			"app.kubernetes.io/name":       "accurate",
            + 			"app.kubernetes.io/version":    "0.1.0",
            + 			"helm.sh/chart":                "accurate-0.1.0",
              		},
              		Annotations:     {"cert-manager.io/inject-ca-from": "accurate/accurate-serving-cert"},
              		OwnerReferences: nil,
              		... // 3 identical fields
              	},
              	Webhooks: {{Name: "vnamespace.kb.io", ClientConfig: {Service: &{Namespace: "accurate", Name: "accurate-webhook-service", Path: &"/validate-v1-namespace"}}, Rules: {{Operations: {"CREATE", "UPDATE", "DELETE"}, Rule: {APIGroups: {""}, APIVersions: {"v1"}, Resources: {"namespaces"}}}}, FailurePolicy: &"Fail", ...}, {Name: "vsubnamespace.kb.io", ClientConfig: {Service: &{Namespace: "accurate", Name: "accurate-webhook-service", Path: &"/validate-accurate-cybozu-com-v1-subnamespace"}}, Rules: {{Operations: {"CREATE", "UPDATE"}, Rule: {APIGroups: {"accurate.cybozu.com"}, APIVersions: {"v1"}, Resources: {"subnamespaces"}}}}, FailurePolicy: &"Fail", ...}},
              }
FAIL
FAIL	tests	0.745s
FAIL

Test codes

$ pwd
/path/to/dir/github.com/cybozu-go/accurate

$ kustomize build . > ./charts/tests/testdata/kustomize.yaml
package tests

import (
	"os"
	"path/filepath"
	"strings"
	"testing"

	"github.com/d-kuro/helmut"
	"github.com/d-kuro/helmut/assert"
	"github.com/d-kuro/helmut/util"
	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
)

func TestHelmCharts(t *testing.T) {
	bytes, err := os.ReadFile(filepath.Join("testdata", "kustomize.yaml"))
	if err != nil {
		t.Fatal(err)
	}

	const releaseName = "accurate"

	r := helmut.New()
	manifests, err := r.RenderTemplates(releaseName, filepath.Join("..", "accurate"), helmut.WithNamespace("accurate"), helmut.WithIncludeCRDs())
	if err != nil {
		t.Fatal(err)
	}

	splitManifests, err := util.SplitManifests(bytes)
	if err != nil {
		t.Fatal(err)
	}

	removeSiffux := func(key helmut.ObjectKey) helmut.ObjectKey {
		if strings.HasPrefix(key.Name, "accurate-config") {
			key.Name = "accurate-config"
			return key
		}

		return key
	}

	for _, manifest := range splitManifests {
		obj, _ := util.MustRawManifestToObject(clientgoscheme.Scheme, manifest)
		key, err := helmut.NewObjectKeyFromObject(obj)
		if err != nil {
			t.Fatal(err)
		}

		t.Run(key.String(), func(t *testing.T) {
			assert.Contains(t, manifests, obj, assert.WithAdditionalKeys(removeSiffux))
		})
	}
}

Copy link
Member

@ymmt2005 ymmt2005 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Member

@zoetrope zoetrope left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@zoetrope zoetrope merged commit 69a4b24 into main Sep 22, 2021
@zoetrope zoetrope deleted the d-kuro/helm branch September 22, 2021 06:41
@bells17 bells17 mentioned this pull request Sep 23, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants