Skip to content

Commit 6b36677

Browse files
authored
Merge pull request #203 from alexander-demicev/injectmanifests
✨Inject additional manifests on provider installation/upgrade
2 parents 4d54900 + 44aa3a1 commit 6b36677

14 files changed

+292
-15
lines changed

Tiltfile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ def build_image():
1818
"OWNERS_ALIASES",
1919
"PROJECT",
2020
"SECURITY_CONTACTS"
21-
]
21+
],
22+
build_args = {
23+
"builder_image": "docker.io/library/golang:1.20.4",
24+
}
2225
)
2326

2427
def deploy():

api/v1alpha1/provider_types.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,23 @@ type ProviderSpec struct {
6363
// https://github.com/kubernetes-sigs/cluster-api-provider-aws/releases.
6464
// +optional
6565
FetchConfig *FetchConfiguration `json:"fetchConfig,omitempty"`
66+
67+
// AdditionalManifests is reference to configmap that contains additional manifests that will be applied
68+
// together with the provider components. The key for storing these manifests has to be `manifests`.
69+
// The manifests are applied only once when a certain release is installed/upgraded. If namespace is not specified, the
70+
// namespace of the provider will be used. There is no validation of the yaml content inside the configmap.
71+
// +optional
72+
AdditionalManifestsRef *ConfigmapReference `json:"additionalManifests,omitempty"`
73+
}
74+
75+
// ConfigmapReference contains enough information to locate the configmap.
76+
type ConfigmapReference struct {
77+
// Name defines the name of the configmap.
78+
Name string `json:"name"`
79+
80+
// Namespace defines the namespace of the configmap.
81+
// +optional
82+
Namespace string `json:"namespace,omitempty"`
6683
}
6784

6885
// ManagerSpec defines the properties that can be enabled on the controller manager for the provider.

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/operator.cluster.x-k8s.io_bootstrapproviders.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,23 @@ spec:
4141
spec:
4242
description: BootstrapProviderSpec defines the desired state of BootstrapProvider.
4343
properties:
44+
additionalManifests:
45+
description: AdditionalManifests is reference to configmap that contains
46+
additional manifests that will be applied together with the provider
47+
components. The key for storing these manifests has to be `manifests`.
48+
The manifests are applied only once when a certain release is installed/upgraded.
49+
If namespace is not specified, the namespace of the provider will
50+
be used. There is no validation of the yaml content inside the configmap.
51+
properties:
52+
name:
53+
description: Name defines the name of the configmap.
54+
type: string
55+
namespace:
56+
description: Namespace defines the namespace of the configmap.
57+
type: string
58+
required:
59+
- name
60+
type: object
4461
deployment:
4562
description: Deployment defines the properties that can be enabled
4663
on the deployment for the provider.

config/crd/bases/operator.cluster.x-k8s.io_controlplaneproviders.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,23 @@ spec:
4242
spec:
4343
description: ControlPlaneProviderSpec defines the desired state of ControlPlaneProvider.
4444
properties:
45+
additionalManifests:
46+
description: AdditionalManifests is reference to configmap that contains
47+
additional manifests that will be applied together with the provider
48+
components. The key for storing these manifests has to be `manifests`.
49+
The manifests are applied only once when a certain release is installed/upgraded.
50+
If namespace is not specified, the namespace of the provider will
51+
be used. There is no validation of the yaml content inside the configmap.
52+
properties:
53+
name:
54+
description: Name defines the name of the configmap.
55+
type: string
56+
namespace:
57+
description: Namespace defines the namespace of the configmap.
58+
type: string
59+
required:
60+
- name
61+
type: object
4562
deployment:
4663
description: Deployment defines the properties that can be enabled
4764
on the deployment for the provider.

config/crd/bases/operator.cluster.x-k8s.io_coreproviders.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,23 @@ spec:
4141
spec:
4242
description: CoreProviderSpec defines the desired state of CoreProvider.
4343
properties:
44+
additionalManifests:
45+
description: AdditionalManifests is reference to configmap that contains
46+
additional manifests that will be applied together with the provider
47+
components. The key for storing these manifests has to be `manifests`.
48+
The manifests are applied only once when a certain release is installed/upgraded.
49+
If namespace is not specified, the namespace of the provider will
50+
be used. There is no validation of the yaml content inside the configmap.
51+
properties:
52+
name:
53+
description: Name defines the name of the configmap.
54+
type: string
55+
namespace:
56+
description: Namespace defines the namespace of the configmap.
57+
type: string
58+
required:
59+
- name
60+
type: object
4461
deployment:
4562
description: Deployment defines the properties that can be enabled
4663
on the deployment for the provider.

config/crd/bases/operator.cluster.x-k8s.io_infrastructureproviders.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,23 @@ spec:
4242
spec:
4343
description: InfrastructureProviderSpec defines the desired state of InfrastructureProvider.
4444
properties:
45+
additionalManifests:
46+
description: AdditionalManifests is reference to configmap that contains
47+
additional manifests that will be applied together with the provider
48+
components. The key for storing these manifests has to be `manifests`.
49+
The manifests are applied only once when a certain release is installed/upgraded.
50+
If namespace is not specified, the namespace of the provider will
51+
be used. There is no validation of the yaml content inside the configmap.
52+
properties:
53+
name:
54+
description: Name defines the name of the configmap.
55+
type: string
56+
namespace:
57+
description: Namespace defines the namespace of the configmap.
58+
type: string
59+
required:
60+
- name
61+
type: object
4562
deployment:
4663
description: Deployment defines the properties that can be enabled
4764
on the deployment for the provider.

docs/README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
* [Modifying a Provider](#modifying-a-provider)
2727
* [Deleting a Provider](#deleting-a-provider)
2828
- [Air-gapped Environment](#air-gapped-environment)
29+
- [Injecting additional manifests](#injecting-additional-manifests)
2930

3031
# Introduction
3132

@@ -717,3 +718,30 @@ yq eval -i '.metadata.labels += {"my-label": "label-value"}' configmap.yaml
717718
```sh
718719
kubectl create -f configmap.yaml
719720
```
721+
722+
## Injecting additional manifests
723+
724+
It is possible to inject additional manifests when installing/upgrading a provider. This can be useful when you need to add extra RBAC resources to the provider controller, for example.
725+
The field `AdditionalManifests` is a reference to a ConfigMap that contains additional manifests, which will be applied together with the provider components. The key for storing these manifests has to be `manifests`.
726+
The manifests are applied only once when a certain release is installed/upgraded. If the namespace is not specified, the namespace of the provider will be used. There is no validation of the YAML content inside the ConfigMap.
727+
728+
```yaml
729+
---
730+
apiVersion: v1
731+
kind: ConfigMap
732+
metadata:
733+
name: additional-manifests
734+
namespace: capi-system
735+
data:
736+
manifests: |
737+
# Additional manifests go here
738+
---
739+
apiVersion: operator.cluster.x-k8s.io/v1alpha1
740+
kind: CoreProvider
741+
metadata:
742+
name: cluster-api
743+
namespace: capi-system
744+
spec:
745+
additionalManifests:
746+
name: additional-manifests
747+
```

internal/controller/manifests_downloader.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,9 @@ const (
4040

4141
compressedAnnotation = "provider.cluster.x-k8s.io/compressed"
4242

43-
metadataConfigMapKey = "metadata"
44-
componentsConfigMapKey = "components"
43+
metadataConfigMapKey = "metadata"
44+
componentsConfigMapKey = "components"
45+
additionalManifestsConfigMapKey = "manifests"
4546

4647
maxConfigMapSize = 1 * 1024 * 1024
4748
)

internal/controller/phases.go

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,12 @@ func (p *phaseReconciler) load(ctx context.Context) (reconcile.Result, error) {
155155
labelSelector = p.provider.GetSpec().FetchConfig.Selector
156156
}
157157

158-
p.repo, err = p.configmapRepository(ctx, labelSelector)
158+
additionalManifests, err := p.fetchAddionalManifests(ctx)
159+
if err != nil {
160+
return reconcile.Result{}, wrapPhaseError(err, "failed to load additional manifests")
161+
}
162+
163+
p.repo, err = p.configmapRepository(ctx, labelSelector, additionalManifests)
159164
if err != nil {
160165
return reconcile.Result{}, wrapPhaseError(err, "failed to load the repository")
161166
}
@@ -242,7 +247,7 @@ func (p *phaseReconciler) secretReader(ctx context.Context) (configclient.Reader
242247

243248
// configmapRepository use clusterctl NewMemoryRepository structure to store the manifests
244249
// and metadata from a given configmap.
245-
func (p *phaseReconciler) configmapRepository(ctx context.Context, labelSelector *metav1.LabelSelector) (repository.Repository, error) {
250+
func (p *phaseReconciler) configmapRepository(ctx context.Context, labelSelector *metav1.LabelSelector, additionalManifests string) (repository.Repository, error) {
246251
mr := repository.NewMemoryRepository()
247252
mr.WithPaths("", "components.yaml")
248253

@@ -289,12 +294,30 @@ func (p *phaseReconciler) configmapRepository(ctx context.Context, labelSelector
289294
return nil, err
290295
}
291296

297+
if additionalManifests != "" {
298+
components = components + "\n---\n" + additionalManifests
299+
}
300+
292301
mr.WithFile(version, mr.ComponentsPath(), []byte(components))
293302
}
294303

295304
return mr, nil
296305
}
297306

307+
func (p *phaseReconciler) fetchAddionalManifests(ctx context.Context) (string, error) {
308+
cm := &corev1.ConfigMap{}
309+
310+
if p.provider.GetSpec().AdditionalManifestsRef != nil {
311+
key := types.NamespacedName{Namespace: p.provider.GetSpec().AdditionalManifestsRef.Namespace, Name: p.provider.GetSpec().AdditionalManifestsRef.Name}
312+
313+
if err := p.ctrlClient.Get(ctx, key, cm); err != nil {
314+
return "", fmt.Errorf("failed to get ConfigMap %s/%s: %w", key.Namespace, key.Name, err)
315+
}
316+
}
317+
318+
return cm.Data[additionalManifestsConfigMapKey], nil
319+
}
320+
298321
// getComponentsData returns components data based on if it's compressed or not.
299322
func getComponentsData(cm corev1.ConfigMap) (string, error) {
300323
// Data is not compressed, return it immediately.

0 commit comments

Comments
 (0)