Skip to content

Commit 6fed75b

Browse files
authored
Merge pull request #18 from weaveworks/secret-sync-experiment
bootstrapping secrets from management cluster to leaf clusters
2 parents d025467 + d84ded3 commit 6fed75b

14 files changed

+1042
-161
lines changed

README.md

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,14 @@
22

33
This is a controller that tracks [GitopsCluster] objects.
44

5-
It provides a CR for a `ClusterBootstrapConfig` which provides a [Job](https://kubernetes.io/docs/concepts/workloads/controllers/job/) template.
5+
It provides the following CRs:
6+
7+
- [ClusterBootstrapConfig](#clusterBootstrapConfig)
8+
- [SecretSync](#secretsync)
9+
10+
## ClusterBootstrapConfig
11+
12+
`ClusterBootstrapConfig` CR provides a [Job](https://kubernetes.io/docs/concepts/workloads/controllers/job/) template.
613

714
When a GitopsCluster is "Ready" a Job is created from the template, the template can access multiple fields.
815

@@ -36,7 +43,7 @@ spec:
3643
3744
This is using Go [templating](https://pkg.go.dev/text/template) and the `GitopsCluster` object is provided as the context, this means that expressions like `{{ .ObjectMeta.Name }}` will get the _name_ of the GitopsCluster that has transitioned to "Ready".
3845

39-
## Annotations
46+
### Annotations
4047

4148
Go templating doesn't easily support access to strings that have "/" in them,
4249
which is a common annotation [naming strategy](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/#syntax-and-character-set).
@@ -53,6 +60,35 @@ e.g.
5360
5461
```
5562

63+
## SecretSync
64+
65+
`SecretSync` provides a way to sync secrets from management cluster to leaf cluster.
66+
67+
The CR references the secret on management cluster to be synced to matched leaf clusters.
68+
69+
SecretSync has a selector to select group of clusters based on their labels
70+
71+
Secrets will be re-synced to leaf clusters when updated
72+
73+
### Example
74+
75+
```yaml
76+
apiVersion: capi.weave.works/v1alpha2
77+
kind: SecretSync
78+
metadata:
79+
name: my-dev-secret-syncer
80+
namespace: default
81+
spec:
82+
clusterSelector:
83+
matchLabels:
84+
environment: dev
85+
secretRef:
86+
name: my-dev-secret
87+
targetNamespace: my-namespace
88+
```
89+
90+
91+
5692
## Installation
5793

5894
Release files are available https://github.com/weaveworks/cluster-bootstrap-controller/releases

api/v1alpha2/secretsync_types.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package v1alpha2
2+
3+
import (
4+
v1 "k8s.io/api/core/v1"
5+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
6+
)
7+
8+
// SecretSyncSpec
9+
type SecretSyncSpec struct {
10+
// Label selector for Clusters. The Clusters that are
11+
// selected by this will be the ones affected by this SecretSync.
12+
// It must match the Cluster labels. This field is immutable.
13+
// Label selector cannot be empty.
14+
ClusterSelector metav1.LabelSelector `json:"clusterSelector"`
15+
// SecretRef specifies the Secret to be bootstrapped to the matched clusters
16+
// Secret must be in the same namespace of the SecretSync object
17+
SecretRef v1.LocalObjectReference `json:"secretRef"`
18+
// TargetNamespace specifies the namespace which the secret should be bootstrapped in
19+
// The default value is the namespace of the referenced secret
20+
//+optional
21+
TargetNamespace string `json:"targetNamespace,omitempty"`
22+
}
23+
24+
// SecretSyncStatus secretsync object status
25+
type SecretSyncStatus struct {
26+
// SecretVersions a map contains the ResourceVersion of the secret of each cluster
27+
// Cluster name is the key and secret's ResourceVersion is the value
28+
SecretVersions map[string]string `json:"versions"`
29+
}
30+
31+
// SetClusterSecretVersion sets the latest secret version of the given cluster
32+
func (s *SecretSyncStatus) SetClusterSecretVersion(cluster, version string) {
33+
if s.SecretVersions == nil {
34+
s.SecretVersions = make(map[string]string)
35+
}
36+
s.SecretVersions[cluster] = version
37+
}
38+
39+
// GetClusterSecretVersion returns secret's ResourceVersion of the given cluster
40+
func (s *SecretSyncStatus) GetClusterSecretVersion(cluster string) string {
41+
return s.SecretVersions[cluster]
42+
}
43+
44+
//+kubebuilder:object:root=true
45+
//+kubebuilder:subresource:status
46+
//+kubebuilder:storageversion
47+
//+kubebuilder:scope:namespaced
48+
49+
type SecretSync struct {
50+
metav1.TypeMeta `json:",inline"`
51+
metav1.ObjectMeta `json:"metadata,omitempty"`
52+
Spec SecretSyncSpec `json:"spec,omitempty"`
53+
Status SecretSyncStatus `json:"status,omitempty"`
54+
}
55+
56+
//+kubebuilder:object:root=true
57+
58+
type SecretSyncList struct {
59+
metav1.TypeMeta `json:",inline"`
60+
metav1.ListMeta `json:"metadata,omitempty"`
61+
Items []SecretSync `json:"items"`
62+
}
63+
64+
func init() {
65+
SchemeBuilder.Register(&SecretSync{}, &SecretSyncList{})
66+
}

api/v1alpha2/zz_generated.deepcopy.go

Lines changed: 98 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
---
2+
apiVersion: apiextensions.k8s.io/v1
3+
kind: CustomResourceDefinition
4+
metadata:
5+
annotations:
6+
controller-gen.kubebuilder.io/version: v0.9.2
7+
creationTimestamp: null
8+
name: secretsyncs.capi.weave.works
9+
spec:
10+
group: capi.weave.works
11+
names:
12+
kind: SecretSync
13+
listKind: SecretSyncList
14+
plural: secretsyncs
15+
singular: secretsync
16+
scope: Namespaced
17+
versions:
18+
- name: v1alpha2
19+
schema:
20+
openAPIV3Schema:
21+
properties:
22+
apiVersion:
23+
description: 'APIVersion defines the versioned schema of this representation
24+
of an object. Servers should convert recognized schemas to the latest
25+
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
26+
type: string
27+
kind:
28+
description: 'Kind is a string value representing the REST resource this
29+
object represents. Servers may infer this from the endpoint the client
30+
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
31+
type: string
32+
metadata:
33+
type: object
34+
spec:
35+
description: SecretSyncSpec
36+
properties:
37+
clusterSelector:
38+
description: ClusterSelector specifies the label selector to match
39+
clusters with
40+
properties:
41+
matchExpressions:
42+
description: matchExpressions is a list of label selector requirements.
43+
The requirements are ANDed.
44+
items:
45+
description: A label selector requirement is a selector that
46+
contains values, a key, and an operator that relates the key
47+
and values.
48+
properties:
49+
key:
50+
description: key is the label key that the selector applies
51+
to.
52+
type: string
53+
operator:
54+
description: operator represents a key's relationship to
55+
a set of values. Valid operators are In, NotIn, Exists
56+
and DoesNotExist.
57+
type: string
58+
values:
59+
description: values is an array of string values. If the
60+
operator is In or NotIn, the values array must be non-empty.
61+
If the operator is Exists or DoesNotExist, the values
62+
array must be empty. This array is replaced during a strategic
63+
merge patch.
64+
items:
65+
type: string
66+
type: array
67+
required:
68+
- key
69+
- operator
70+
type: object
71+
type: array
72+
matchLabels:
73+
additionalProperties:
74+
type: string
75+
description: matchLabels is a map of {key,value} pairs. A single
76+
{key,value} in the matchLabels map is equivalent to an element
77+
of matchExpressions, whose key field is "key", the operator
78+
is "In", and the values array contains only "value". The requirements
79+
are ANDed.
80+
type: object
81+
type: object
82+
x-kubernetes-map-type: atomic
83+
secretRef:
84+
description: SecretRef specifies the Secret to be bootstrapped to
85+
the matched clusters Secret must be in the same namespace of the
86+
SecretSync object
87+
properties:
88+
name:
89+
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
90+
TODO: Add other useful fields. apiVersion, kind, uid?'
91+
type: string
92+
type: object
93+
x-kubernetes-map-type: atomic
94+
targetNamespace:
95+
description: TargetNamespace specifies the namespace which the secret
96+
should be bootstrapped in The default value is the namespace of
97+
the referenced secret
98+
type: string
99+
required:
100+
- clusterSelector
101+
- secretRef
102+
type: object
103+
status:
104+
description: SecretSyncStatus secretsync object status
105+
properties:
106+
versions:
107+
additionalProperties:
108+
type: string
109+
description: SecretVersions a map contains the ResourceVersion of
110+
the secret of each cluster Cluster name is the key and secret's
111+
ResourceVersion is the value
112+
type: object
113+
required:
114+
- versions
115+
type: object
116+
type: object
117+
served: true
118+
storage: true
119+
subresources:
120+
status: {}

config/rbac/role.yaml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,32 @@ rules:
5151
- get
5252
- patch
5353
- update
54+
- apiGroups:
55+
- capi.weave.works
56+
resources:
57+
- secretsyncs
58+
verbs:
59+
- create
60+
- delete
61+
- get
62+
- list
63+
- patch
64+
- update
65+
- watch
66+
- apiGroups:
67+
- capi.weave.works
68+
resources:
69+
- secretsyncs/finalizers
70+
verbs:
71+
- update
72+
- apiGroups:
73+
- capi.weave.works
74+
resources:
75+
- secretsyncs/status
76+
verbs:
77+
- get
78+
- patch
79+
- update
5480
- apiGroups:
5581
- cluster.x-k8s.io
5682
resources:

0 commit comments

Comments
 (0)