Skip to content

Commit

Permalink
feat: support configmap creation from the bundle
Browse files Browse the repository at this point in the history
  • Loading branch information
exdx committed Apr 8, 2020
1 parent 3ba5db8 commit 503887d
Show file tree
Hide file tree
Showing 6 changed files with 265 additions and 0 deletions.
23 changes: 23 additions & 0 deletions pkg/controller/operators/catalog/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ const (
secretKind = "Secret"
clusterRoleKind = "ClusterRole"
clusterRoleBindingKind = "ClusterRoleBinding"
configMapKind = "ConfigMap"
serviceAccountKind = "ServiceAccount"
serviceKind = "Service"
roleKind = "Role"
Expand Down Expand Up @@ -1731,6 +1732,28 @@ func (o *Operator) ExecutePlan(plan *v1alpha1.InstallPlan) error {

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

case configMapKind:
var cfg corev1.ConfigMap
err := json.Unmarshal([]byte(step.Resource.Manifest), &cfg)
if err != nil {
return errorwrap.Wrapf(err, "error parsing step manifest: %s", step.Resource.Name)
}

// Update UIDs on all CSV OwnerReferences
updated, err := o.getUpdatedOwnerReferences(cfg.OwnerReferences, plan.Namespace)
if err != nil {
return errorwrap.Wrapf(err, "error generating ownerrefs for service: %s", cfg.GetName())
}
cfg.SetOwnerReferences(updated)
cfg.SetNamespace(namespace)

status, err := ensurer.EnsureConfigMap(plan.Namespace, &cfg)
if err != nil {
return err
}

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

default:
if !isSupported(step.Resource.Kind) {
// Not a supported resource
Expand Down
30 changes: 30 additions & 0 deletions pkg/controller/operators/catalog/operator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,27 @@ func TestExecutePlan(t *testing.T) {
want: []runtime.Object{serviceAccount("sa", namespace, "", objectReference("init secret"))},
err: nil,
},
{
testName: "CreateConfigMap",
in: withSteps(installPlan("p", namespace, v1alpha1.InstallPlanPhaseInstalling, "csv"),
[]*v1alpha1.Step{
{
Resource: v1alpha1.StepResource{
CatalogSource: "catalog",
CatalogSourceNamespace: namespace,
Group: "",
Version: "v1",
Kind: "ConfigMap",
Name: "cfg",
Manifest: toManifest(t, configmap("cfg", namespace)),
},
Status: v1alpha1.StepStatusUnknown,
},
},
),
want: []runtime.Object{configmap("cfg", namespace)},
err: nil,
},
{
testName: "UpdateServiceAccountWithSameFields",
in: withSteps(installPlan("p", namespace, v1alpha1.InstallPlanPhaseInstalling, "csv"),
Expand Down Expand Up @@ -557,6 +578,8 @@ func TestExecutePlan(t *testing.T) {
fetched, err = op.opClient.GetSecret(namespace, o.GetName())
case *corev1.Service:
fetched, err = op.opClient.GetService(namespace, o.GetName())
case *corev1.ConfigMap:
fetched, err = op.opClient.GetConfigMap(namespace, o.GetName())
case *v1beta1.CustomResourceDefinition:
fetched, err = op.opClient.ApiextensionsV1beta1Interface().ApiextensionsV1beta1().CustomResourceDefinitions().Get(o.GetName(), getOpts)
case *v1alpha1.ClusterServiceVersion:
Expand Down Expand Up @@ -1322,6 +1345,13 @@ func serviceAccount(name, namespace, generateName string, secretRef *corev1.Obje
}
}

func configmap(name, namespace string) *corev1.ConfigMap {
return &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{Kind: configMapKind},
ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespace},
}
}

func objectReference(name string) *corev1.ObjectReference {
if name == "" {
return &corev1.ObjectReference{}
Expand Down
23 changes: 23 additions & 0 deletions pkg/controller/operators/catalog/step_ensurer.go
Original file line number Diff line number Diff line change
Expand Up @@ -300,3 +300,26 @@ func (o *StepEnsurer) EnsureUnstructuredObject(client dynamic.ResourceInterface,
status = v1alpha1.StepStatusPresent
return
}

// EnsureConfigMap writes the specified ConfigMap object to the cluster.
func (o *StepEnsurer) EnsureConfigMap(namespace string, configmap *corev1.ConfigMap) (status v1alpha1.StepStatus, err error) {
_, createErr := o.kubeClient.KubernetesInterface().CoreV1().ConfigMaps(namespace).Create(configmap)
if createErr == nil {
status = v1alpha1.StepStatusCreated
return
}

if !k8serrors.IsAlreadyExists(createErr) {
err = errorwrap.Wrapf(createErr, "error updating configmap: %s", configmap.GetName())
return
}

configmap.SetNamespace(namespace)
if _, updateErr := o.kubeClient.UpdateConfigMap(configmap); updateErr != nil {
err = errorwrap.Wrapf(updateErr, "error updating service: %s", configmap.GetName())
return
}

status = v1alpha1.StepStatusPresent
return
}
9 changes: 9 additions & 0 deletions pkg/lib/operatorclient/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type ClientInterface interface {
ClusterRoleBindingClient
ClusterRoleClient
DeploymentClient
ConfigMapClient
}

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

// ConfigMapClient contains methods for the ConfigMap resource
type ConfigMapClient interface {
CreateConfigMap(*v1.ConfigMap) (*v1.ConfigMap, error)
GetConfigMap(namespace, name string) (*v1.ConfigMap, error)
UpdateConfigMap(modified *v1.ConfigMap) (*v1.ConfigMap, error)
DeleteConfigMap(namespace, name string, options *metav1.DeleteOptions) error
}

// Interface assertion.
var _ ClientInterface = &Client{}

Expand Down
39 changes: 39 additions & 0 deletions pkg/lib/operatorclient/configmap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package operatorclient

import (
"fmt"

corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/klog"
)

// CreateConfigMap creates the ConfigMap.
func (c *Client) CreateConfigMap(ig *corev1.ConfigMap) (*corev1.ConfigMap, error) {
return c.CoreV1().ConfigMaps(ig.GetNamespace()).Create(ig)
}

// GetConfigMap returns the existing ConfigMap.
func (c *Client) GetConfigMap(namespace, name string) (*corev1.ConfigMap, error) {
return c.CoreV1().ConfigMaps(namespace).Get(name, metav1.GetOptions{})
}

// DeleteConfigMap deletes the ConfigMap.
func (c *Client) DeleteConfigMap(namespace, name string, options *metav1.DeleteOptions) error {
return c.CoreV1().ConfigMaps(namespace).Delete(name, options)
}

// UpdateConfigMap will update the given ConfigMap resource.
func (c *Client) UpdateConfigMap(configmap *corev1.ConfigMap) (*corev1.ConfigMap, error) {
klog.V(4).Infof("[UPDATE ConfigMap]: %s", configmap.GetName())
oldSa, err := c.GetConfigMap(configmap.GetNamespace(), configmap.GetName())
if err != nil {
return nil, err
}
patchBytes, err := createPatch(oldSa, configmap)
if err != nil {
return nil, fmt.Errorf("error creating patch for ConfigMap: %v", err)
}
return c.CoreV1().ConfigMaps(configmap.GetNamespace()).Patch(configmap.GetName(), types.StrategicMergePatchType, patchBytes)
}
141 changes: 141 additions & 0 deletions pkg/lib/operatorclient/operatorclientmocks/mock_client.go

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

0 comments on commit 503887d

Please sign in to comment.