Skip to content

Commit

Permalink
Support extra parameters in the templates
Browse files Browse the repository at this point in the history
  • Loading branch information
zoetrope committed May 20, 2024
1 parent b4b552c commit 2fee070
Show file tree
Hide file tree
Showing 11 changed files with 104 additions and 24 deletions.
4 changes: 4 additions & 0 deletions api/v1beta1/tenant_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ type TenantSpec struct {
// If not specified, the default controller is used.
// +optional
ControllerName string `json:"controllerName,omitempty"`

// ExtraParams is a map of extra parameters that can be used in the templates.
// +optional
ExtraParams map[string]string `json:"extraParams,omitempty"`
}

// RootNamespaceSpec defines the desired state of Namespace.
Expand Down
7 changes: 7 additions & 0 deletions api/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions charts/cattage/crds/tenant.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ spec:
- roles
type: object
type: array
extraParams:
additionalProperties:
type: string
description: ExtraParams is a map of extra parameters that can be used in the templates.
type: object
rootNamespaces:
description: RootNamespaces are the list of root namespaces that belong to this tenant.
items:
Expand Down
6 changes: 6 additions & 0 deletions config/crd/bases/cattage.cybozu.io_tenants.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ spec:
- roles
type: object
type: array
extraParams:
additionalProperties:
type: string
description: ExtraParams is a map of extra parameters that can be
used in the templates.
type: object
rootNamespaces:
description: RootNamespaces are the list of root namespaces that belong
to this tenant.
Expand Down
8 changes: 4 additions & 4 deletions config/manager/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ data:
{{- range .Roles.admin }}
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: {{ . }}
name: {{ .Name }}
- kind: ServiceAccount
name: node-{{ . }}
name: node-{{ .Name }}
namespace: teleport
{{- end }}
argocd:
Expand All @@ -48,9 +48,9 @@ data:
kind: LimitRange
roles:
- groups:
- cybozu-go:{{ .Name }}
- cybozu-go:{{with .Extras.GitHubTeam}}{{ . }}{{else}}{{ .Name }}{{end}}
{{- range .Roles.admin }}
- cybozu-go:{{ . }}
- cybozu-go:{{with .Extras.GitHubTeam}}{{ . }}{{else}}{{ .Name }}{{end}}
{{- end }}
name: admin
policies:
Expand Down
4 changes: 4 additions & 0 deletions config/samples/tenant.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ spec:
rootNamespaces:
- name: app-a
controllerName: second
extraParams:
GitHubTeam: a-team-gh
---
apiVersion: cattage.cybozu.io/v1beta1
kind: Tenant
Expand All @@ -21,3 +23,5 @@ spec:
- name: a-team
roles:
- admin
extraParams:
GitHubTeam: b-team-gh
48 changes: 38 additions & 10 deletions controllers/tenant_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -354,15 +354,23 @@ func (r *TenantReconciler) patchRoleBinding(ctx context.Context, rb *acrbacv1.Ro
})
}

func rolesMap(delegates []cattagev1beta1.DelegateSpec) map[string][]string {
result := make(map[string][]string)
func (r *TenantReconciler) rolesMap(ctx context.Context, delegates []cattagev1beta1.DelegateSpec) (map[string][]Role, error) {
result := make(map[string][]Role)

for _, d := range delegates {
for _, role := range d.Roles {
result[role] = append(result[role], d.Name)
delegatedTenant := &cattagev1beta1.Tenant{}
err := r.client.Get(ctx, client.ObjectKey{Name: d.Name}, delegatedTenant)
if err != nil {
return nil, err
}
result[role] = append(result[role], Role{
Name: delegatedTenant.Name,
Extras: delegatedTenant.Spec.ExtraParams,
})
}
}
return result
return result, nil
}

func (r *TenantReconciler) reconcileNamespaces(ctx context.Context, tenant *cattagev1beta1.Tenant) error {
Expand Down Expand Up @@ -395,13 +403,20 @@ func (r *TenantReconciler) reconcileNamespaces(ctx context.Context, tenant *catt
if err != nil {
return err
}
roles, err := r.rolesMap(ctx, tenant.Spec.Delegates)
if err != nil {
return err
}

var buf bytes.Buffer
err = tpl.Execute(&buf, struct {
Name string
Roles map[string][]string
Name string
Roles map[string][]Role
Extras map[string]string
}{
Name: tenant.Name,
Roles: rolesMap(tenant.Spec.Delegates),
Name: tenant.Name,
Roles: roles,
Extras: tenant.Spec.ExtraParams,
})
if err != nil {
return err
Expand Down Expand Up @@ -445,6 +460,11 @@ func (r *TenantReconciler) reconcileNamespaces(ctx context.Context, tenant *catt
return nil
}

type Role struct {
Name string
Extras map[string]string
}

func (r *TenantReconciler) reconcileArgoCD(ctx context.Context, tenant *cattagev1beta1.Tenant) error {
logger := log.FromContext(ctx)

Expand All @@ -469,17 +489,24 @@ func (r *TenantReconciler) reconcileArgoCD(ctx context.Context, tenant *cattagev
return err
}

roles, err := r.rolesMap(ctx, tenant.Spec.Delegates)
if err != nil {
return err
}

var buf bytes.Buffer
err = tpl.Execute(&buf, struct {
Name string
Namespaces []string
Roles map[string][]string
Roles map[string][]Role
Repositories []string
Extras map[string]string
}{
Name: tenant.Name,
Namespaces: namespaces,
Roles: rolesMap(tenant.Spec.Delegates),
Roles: roles,
Repositories: tenant.Spec.ArgoCD.Repositories,
Extras: tenant.Spec.ExtraParams,
})
if err != nil {
return err
Expand All @@ -489,6 +516,7 @@ func (r *TenantReconciler) reconcileArgoCD(ctx context.Context, tenant *cattagev
dec := yaml.NewDecodingSerializer(unstructured.UnstructuredJSONScheme)
_, _, err = dec.Decode(buf.Bytes(), nil, proj)
if err != nil {
logger.Error(err, "failed to decode", "yaml", buf.String())
return err
}

Expand Down
39 changes: 32 additions & 7 deletions controllers/tenant_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,29 @@ var _ = Describe("Tenant controller", Ordered, func() {
})

It("should create root namespaces, rolebindings and an appproject", func() {
tenant := &cattagev1beta1.Tenant{
cTeam := &cattagev1beta1.Tenant{
ObjectMeta: metav1.ObjectMeta{
Name: "c-team",
},
Spec: cattagev1beta1.TenantSpec{
RootNamespaces: []cattagev1beta1.RootNamespaceSpec{
{
Name: "app-c",
},
},
ArgoCD: cattagev1beta1.ArgoCDSpec{
Repositories: []string{
"https://github.com/cybozu-go/*",
},
},
ExtraParams: map[string]string{
"GitHubTeam": "c-team-gh",
},
},
}
err := k8sClient.Create(ctx, cTeam)
Expect(err).ToNot(HaveOccurred())
xTeam := &cattagev1beta1.Tenant{
ObjectMeta: metav1.ObjectMeta{
Name: "x-team",
},
Expand Down Expand Up @@ -119,9 +141,12 @@ var _ = Describe("Tenant controller", Ordered, func() {
},
},
},
ExtraParams: map[string]string{
"GitHubTeam": "x-team-gh",
},
},
}
err := k8sClient.Create(ctx, tenant)
err = k8sClient.Create(ctx, xTeam)
Expect(err).ToNot(HaveOccurred())

ns := &corev1.Namespace{}
Expand Down Expand Up @@ -198,7 +223,7 @@ var _ = Describe("Tenant controller", Ordered, func() {
}),
"roles": ConsistOf(
MatchAllKeys(Keys{
"groups": ConsistOf("cybozu-go:x-team", "cybozu-go:c-team"),
"groups": ConsistOf("cybozu-go:x-team-gh", "cybozu-go:c-team-gh"),
"name": Equal("admin"),
"policies": ConsistOf("p, proj:x-team:admin, applications, *, x-team/*, allow"),
}),
Expand All @@ -214,14 +239,14 @@ var _ = Describe("Tenant controller", Ordered, func() {
err := k8sClient.Get(ctx, client.ObjectKey{Namespace: "argocd", Name: "all-tenant-namespaces-cm"}, allNsCm)
g.Expect(err).NotTo(HaveOccurred())
allNs := strings.Split(allNsCm.Data["application.namespaces"], ",")
g.Expect(allNs).Should(ConsistOf("app-x", "sub-4"))
g.Expect(allNs).Should(ConsistOf("app-x", "sub-4", "app-c"))
}).Should(Succeed())

Eventually(func(g Gomega) {
err := k8sClient.Get(ctx, client.ObjectKey{Namespace: "argocd", Name: "default-application-controller-cm"}, defaultCm)
g.Expect(err).NotTo(HaveOccurred())
defaultNs := strings.Split(defaultCm.Data["application.namespaces"], ",")
g.Expect(defaultNs).Should(ConsistOf("app-x", "sub-4"))
g.Expect(defaultNs).Should(ConsistOf("app-x", "sub-4", "app-c"))
}).Should(Succeed())

tenantS := &cattagev1beta1.Tenant{
Expand All @@ -245,13 +270,13 @@ var _ = Describe("Tenant controller", Ordered, func() {
err := k8sClient.Get(ctx, client.ObjectKey{Namespace: "argocd", Name: "all-tenant-namespaces-cm"}, allNsCm)
g.Expect(err).NotTo(HaveOccurred())
allNs := strings.Split(allNsCm.Data["application.namespaces"], ",")
g.Expect(allNs).Should(ConsistOf("app-x", "sub-4", "app-a", "sub-1", "sub-2", "sub-3"))
g.Expect(allNs).Should(ConsistOf("app-x", "sub-4", "app-a", "sub-1", "sub-2", "sub-3", "app-c"))
}).Should(Succeed())
Eventually(func(g Gomega) {
err := k8sClient.Get(ctx, client.ObjectKey{Namespace: "argocd", Name: "default-application-controller-cm"}, defaultCm)
g.Expect(err).NotTo(HaveOccurred())
defaultNs := strings.Split(defaultCm.Data["application.namespaces"], ",")
g.Expect(defaultNs).Should(ConsistOf("app-x", "sub-4"))
g.Expect(defaultNs).Should(ConsistOf("app-x", "sub-4", "app-c"))
}).Should(Succeed())
Eventually(func(g Gomega) {
err := k8sClient.Get(ctx, client.ObjectKey{Namespace: "argocd", Name: "second-application-controller-cm"}, secondCm)
Expand Down
4 changes: 2 additions & 2 deletions controllers/testdata/appprojecttemplate.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ spec:
warn: false
roles:
- groups:
- cybozu-go:{{ .Name }}
- cybozu-go:{{with .Extras.GitHubTeam}}{{ . }}{{else}}{{ .Name }}{{end}}
{{- range .Roles.admin }}
- cybozu-go:{{ . }}
- cybozu-go:{{with .Extras.GitHubTeam}}{{ . }}{{else}}{{ .Name }}{{end}}
{{- end }}
name: admin
policies:
Expand Down
2 changes: 1 addition & 1 deletion controllers/testdata/rolebindingtemplate.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ subjects:
{{- range .Roles.admin }}
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: {{ . }}
name: {{ .Name }}
{{- end }}
1 change: 1 addition & 0 deletions docs/crd_tenant.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ TenantSpec defines the desired state of Tenant.
| argocd | ArgoCD is the settings of Argo CD for this tenant. | [ArgoCDSpec](#argocdspec) | false |
| delegates | Delegates is a list of other tenants that are delegated access to this tenant. | [][DelegateSpec](#delegatespec) | false |
| controllerName | ControllerName is the name of the application-controller that manages this tenant's applications. If not specified, the default controller is used. | string | false |
| extraParams | ExtraParams is a map of extra parameters that can be used in the templates. | map[string]string | false |

[Back to Custom Resources](#custom-resources)

Expand Down

0 comments on commit 2fee070

Please sign in to comment.