Skip to content

Commit 0efd123

Browse files
Merge pull request #1434 from exdx/feat/support-configmaps
feat: support configmap creation from the bundle
2 parents e9797bc + e517d03 commit 0efd123

File tree

6 files changed

+265
-0
lines changed

6 files changed

+265
-0
lines changed

pkg/controller/operators/catalog/operator.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ const (
6161
secretKind = "Secret"
6262
clusterRoleKind = "ClusterRole"
6363
clusterRoleBindingKind = "ClusterRoleBinding"
64+
configMapKind = "ConfigMap"
6465
serviceAccountKind = "ServiceAccount"
6566
serviceKind = "Service"
6667
roleKind = "Role"
@@ -1731,6 +1732,28 @@ func (o *Operator) ExecutePlan(plan *v1alpha1.InstallPlan) error {
17311732

17321733
plan.Status.Plan[i].Status = status
17331734

1735+
case configMapKind:
1736+
var cfg corev1.ConfigMap
1737+
err := json.Unmarshal([]byte(step.Resource.Manifest), &cfg)
1738+
if err != nil {
1739+
return errorwrap.Wrapf(err, "error parsing step manifest: %s", step.Resource.Name)
1740+
}
1741+
1742+
// Update UIDs on all CSV OwnerReferences
1743+
updated, err := o.getUpdatedOwnerReferences(cfg.OwnerReferences, plan.Namespace)
1744+
if err != nil {
1745+
return errorwrap.Wrapf(err, "error generating ownerrefs for configmap: %s", cfg.GetName())
1746+
}
1747+
cfg.SetOwnerReferences(updated)
1748+
cfg.SetNamespace(namespace)
1749+
1750+
status, err := ensurer.EnsureConfigMap(plan.Namespace, &cfg)
1751+
if err != nil {
1752+
return err
1753+
}
1754+
1755+
plan.Status.Plan[i].Status = status
1756+
17341757
default:
17351758
if !isSupported(step.Resource.Kind) {
17361759
// Not a supported resource

pkg/controller/operators/catalog/operator_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,27 @@ func TestExecutePlan(t *testing.T) {
413413
want: []runtime.Object{serviceAccount("sa", namespace, "", objectReference("init secret"))},
414414
err: nil,
415415
},
416+
{
417+
testName: "CreateConfigMap",
418+
in: withSteps(installPlan("p", namespace, v1alpha1.InstallPlanPhaseInstalling, "csv"),
419+
[]*v1alpha1.Step{
420+
{
421+
Resource: v1alpha1.StepResource{
422+
CatalogSource: "catalog",
423+
CatalogSourceNamespace: namespace,
424+
Group: "",
425+
Version: "v1",
426+
Kind: "ConfigMap",
427+
Name: "cfg",
428+
Manifest: toManifest(t, configmap("cfg", namespace)),
429+
},
430+
Status: v1alpha1.StepStatusUnknown,
431+
},
432+
},
433+
),
434+
want: []runtime.Object{configmap("cfg", namespace)},
435+
err: nil,
436+
},
416437
{
417438
testName: "UpdateServiceAccountWithSameFields",
418439
in: withSteps(installPlan("p", namespace, v1alpha1.InstallPlanPhaseInstalling, "csv"),
@@ -557,6 +578,8 @@ func TestExecutePlan(t *testing.T) {
557578
fetched, err = op.opClient.GetSecret(namespace, o.GetName())
558579
case *corev1.Service:
559580
fetched, err = op.opClient.GetService(namespace, o.GetName())
581+
case *corev1.ConfigMap:
582+
fetched, err = op.opClient.GetConfigMap(namespace, o.GetName())
560583
case *v1beta1.CustomResourceDefinition:
561584
fetched, err = op.opClient.ApiextensionsV1beta1Interface().ApiextensionsV1beta1().CustomResourceDefinitions().Get(o.GetName(), getOpts)
562585
case *v1alpha1.ClusterServiceVersion:
@@ -1322,6 +1345,13 @@ func serviceAccount(name, namespace, generateName string, secretRef *corev1.Obje
13221345
}
13231346
}
13241347

1348+
func configmap(name, namespace string) *corev1.ConfigMap {
1349+
return &corev1.ConfigMap{
1350+
TypeMeta: metav1.TypeMeta{Kind: configMapKind},
1351+
ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespace},
1352+
}
1353+
}
1354+
13251355
func objectReference(name string) *corev1.ObjectReference {
13261356
if name == "" {
13271357
return &corev1.ObjectReference{}

pkg/controller/operators/catalog/step_ensurer.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,3 +300,26 @@ func (o *StepEnsurer) EnsureUnstructuredObject(client dynamic.ResourceInterface,
300300
status = v1alpha1.StepStatusPresent
301301
return
302302
}
303+
304+
// EnsureConfigMap writes the specified ConfigMap object to the cluster.
305+
func (o *StepEnsurer) EnsureConfigMap(namespace string, configmap *corev1.ConfigMap) (status v1alpha1.StepStatus, err error) {
306+
_, createErr := o.kubeClient.KubernetesInterface().CoreV1().ConfigMaps(namespace).Create(configmap)
307+
if createErr == nil {
308+
status = v1alpha1.StepStatusCreated
309+
return
310+
}
311+
312+
if !k8serrors.IsAlreadyExists(createErr) {
313+
err = errorwrap.Wrapf(createErr, "error updating configmap: %s", configmap.GetName())
314+
return
315+
}
316+
317+
configmap.SetNamespace(namespace)
318+
if _, updateErr := o.kubeClient.UpdateConfigMap(configmap); updateErr != nil {
319+
err = errorwrap.Wrapf(updateErr, "error updating configmap: %s", configmap.GetName())
320+
return
321+
}
322+
323+
status = v1alpha1.StepStatusPresent
324+
return
325+
}

pkg/lib/operatorclient/client.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ type ClientInterface interface {
3131
ClusterRoleBindingClient
3232
ClusterRoleClient
3333
DeploymentClient
34+
ConfigMapClient
3435
}
3536

3637
// CustomResourceClient contains methods for the Custom Resource.
@@ -127,6 +128,14 @@ type DeploymentClient interface {
127128
ListDeploymentsWithLabels(namespace string, labels labels.Set) (*appsv1.DeploymentList, error)
128129
}
129130

131+
// ConfigMapClient contains methods for the ConfigMap resource
132+
type ConfigMapClient interface {
133+
CreateConfigMap(*v1.ConfigMap) (*v1.ConfigMap, error)
134+
GetConfigMap(namespace, name string) (*v1.ConfigMap, error)
135+
UpdateConfigMap(modified *v1.ConfigMap) (*v1.ConfigMap, error)
136+
DeleteConfigMap(namespace, name string, options *metav1.DeleteOptions) error
137+
}
138+
130139
// Interface assertion.
131140
var _ ClientInterface = &Client{}
132141

pkg/lib/operatorclient/configmap.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package operatorclient
2+
3+
import (
4+
"fmt"
5+
6+
corev1 "k8s.io/api/core/v1"
7+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
8+
"k8s.io/apimachinery/pkg/types"
9+
"k8s.io/klog"
10+
)
11+
12+
// CreateConfigMap creates the ConfigMap.
13+
func (c *Client) CreateConfigMap(ig *corev1.ConfigMap) (*corev1.ConfigMap, error) {
14+
return c.CoreV1().ConfigMaps(ig.GetNamespace()).Create(ig)
15+
}
16+
17+
// GetConfigMap returns the existing ConfigMap.
18+
func (c *Client) GetConfigMap(namespace, name string) (*corev1.ConfigMap, error) {
19+
return c.CoreV1().ConfigMaps(namespace).Get(name, metav1.GetOptions{})
20+
}
21+
22+
// DeleteConfigMap deletes the ConfigMap.
23+
func (c *Client) DeleteConfigMap(namespace, name string, options *metav1.DeleteOptions) error {
24+
return c.CoreV1().ConfigMaps(namespace).Delete(name, options)
25+
}
26+
27+
// UpdateConfigMap will update the given ConfigMap resource.
28+
func (c *Client) UpdateConfigMap(configmap *corev1.ConfigMap) (*corev1.ConfigMap, error) {
29+
klog.V(4).Infof("[UPDATE ConfigMap]: %s", configmap.GetName())
30+
oldSa, err := c.GetConfigMap(configmap.GetNamespace(), configmap.GetName())
31+
if err != nil {
32+
return nil, err
33+
}
34+
patchBytes, err := createPatch(oldSa, configmap)
35+
if err != nil {
36+
return nil, fmt.Errorf("error creating patch for ConfigMap: %v", err)
37+
}
38+
return c.CoreV1().ConfigMaps(configmap.GetNamespace()).Patch(configmap.GetName(), types.StrategicMergePatchType, patchBytes)
39+
}

pkg/lib/operatorclient/operatorclientmocks/mock_client.go

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

0 commit comments

Comments
 (0)