This is an automated email from the ASF dual-hosted git repository. nferraro pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel-k.git
commit a000ec5c18b0e504ccd2e424a3ca417e0d50b11a Author: John Poth <[email protected]> AuthorDate: Fri Sep 25 14:31:30 2020 +0200 feat: Add ServiceBinding trait (#1445) --- deploy/operator-role-binding-service-binding.yaml | 30 +++ deploy/operator-role-service-binding.yaml | 37 +++ go.mod | 7 +- pkg/apis/addtoscheme_service_binding.go | 25 ++ pkg/apis/camel/v1/integration_types.go | 4 + pkg/cmd/run.go | 9 +- .../integration/integration_controller.go | 10 + pkg/controller/integration/platform_setup.go | 3 +- pkg/trait/deployer.go | 3 +- pkg/trait/service_binding.go | 266 +++++++++++++++++++++ pkg/trait/trait_register.go | 1 + pkg/trait/trait_types.go | 33 ++- 12 files changed, 418 insertions(+), 10 deletions(-) diff --git a/deploy/operator-role-binding-service-binding.yaml b/deploy/operator-role-binding-service-binding.yaml new file mode 100644 index 0000000..9a2621a --- /dev/null +++ b/deploy/operator-role-binding-service-binding.yaml @@ -0,0 +1,30 @@ +# --------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# --------------------------------------------------------------------------- + +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: camel-k-operator-service-binding + labels: + app: "camel-k" +subjects: +- kind: ServiceAccount + name: camel-k-operator +roleRef: + kind: Role + name: camel-k-operator-service-binding + apiGroup: rbac.authorization.k8s.io diff --git a/deploy/operator-role-service-binding.yaml b/deploy/operator-role-service-binding.yaml new file mode 100644 index 0000000..68a2774 --- /dev/null +++ b/deploy/operator-role-service-binding.yaml @@ -0,0 +1,37 @@ +# --------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# --------------------------------------------------------------------------- + +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: camel-k-operator-service-binding + labels: + app: "camel-k" +rules: +- apiGroups: + - operators.coreos.com + resources: + - servicebindings + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch diff --git a/go.mod b/go.mod index e744805..603cb68 100644 --- a/go.mod +++ b/go.mod @@ -28,6 +28,7 @@ require ( github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.42.1 github.com/prometheus/client_golang v1.7.1 github.com/radovskyb/watcher v1.0.6 + github.com/redhat-developer/service-binding-operator v0.4.0 github.com/rs/xid v1.2.1 github.com/scylladb/go-set v1.0.2 github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 @@ -37,7 +38,7 @@ require ( github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.6.2 github.com/stoewer/go-strcase v1.0.2 - github.com/stretchr/testify v1.5.1 + github.com/stretchr/testify v1.6.1 go.uber.org/multierr v1.5.0 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d gopkg.in/inf.v0 v0.9.1 @@ -57,6 +58,10 @@ replace ( github.com/Azure/go-autorest => github.com/Azure/go-autorest v13.3.2+incompatible // Required by OLM k8s.io/client-go => k8s.io/client-go v0.18.9 k8s.io/code-generator => k8s.io/code-generator v0.18.9 + // Required by Service Binding Operator dependency, see https://github.com/redhat-developer/service-binding-operator/pull/798 + github.com/operator-framework/operator-lifecycle-manager => github.com/operator-framework/operator-lifecycle-manager v0.0.0-20200321030439-57b580e57e88 + github.com/operator-framework/operator-sdk => github.com/operator-framework/operator-sdk v0.17.1 + k8s.io/api => k8s.io/api v0.18.9 ) replace github.com/docker/docker => github.com/moby/moby v0.7.3-0.20190826074503-38ab9da00309 // Required by Helm diff --git a/pkg/apis/addtoscheme_service_binding.go b/pkg/apis/addtoscheme_service_binding.go new file mode 100644 index 0000000..9fc4a7b --- /dev/null +++ b/pkg/apis/addtoscheme_service_binding.go @@ -0,0 +1,25 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package apis + +import "github.com/redhat-developer/service-binding-operator/pkg/apis/operators/v1alpha1" + +func init() { + // Register the types with the Scheme so the components can map objects to GroupVersionKinds and back + AddToSchemes = append(AddToSchemes, v1alpha1.SchemeBuilder.AddToScheme) +} diff --git a/pkg/apis/camel/v1/integration_types.go b/pkg/apis/camel/v1/integration_types.go index 3d103d5..5a9e631 100644 --- a/pkg/apis/camel/v1/integration_types.go +++ b/pkg/apis/camel/v1/integration_types.go @@ -112,6 +112,8 @@ const ( IntegrationPhaseBuildingKit IntegrationPhase = "Building Kit" // IntegrationPhaseResolvingKit -- IntegrationPhaseResolvingKit IntegrationPhase = "Resolving Kit" + // IntegrationPhaseWaitingForServiceBindingCollectionReady -- + IntegrationPhaseWaitingForServiceBindingCollectionReady IntegrationPhase = "Waiting For Service binding Collection Ready Status" // IntegrationPhaseDeploying -- IntegrationPhaseDeploying IntegrationPhase = "Deploying" // IntegrationPhaseRunning -- @@ -133,6 +135,8 @@ const ( IntegrationConditionKnativeServiceAvailable IntegrationConditionType = "KnativeServiceAvailable" // IntegrationConditionCronJobAvailable -- IntegrationConditionCronJobAvailable IntegrationConditionType = "CronJobAvailable" + // IntegrationConditionServiceBindingCollectionReady -- + IntegrationConditionServiceBindingCollectionReady IntegrationConditionType = "ServiceBindingCollectionReady" // IntegrationConditionExposureAvailable -- IntegrationConditionExposureAvailable IntegrationConditionType = "ExposureAvailable" // IntegrationConditionPrometheusAvailable -- diff --git a/pkg/cmd/run.go b/pkg/cmd/run.go index 874c443..6f5f4ce 100644 --- a/pkg/cmd/run.go +++ b/pkg/cmd/run.go @@ -72,6 +72,7 @@ func newCmdRun(rootCmdOptions *RootCmdOptions) (*cobra.Command, *runCmdOptions) } cmd.Flags().String("name", "", "The integration name") + cmd.Flags().StringArrayP("connect", "c", nil, "A ServiceBinding or Provisioned Service that the integration should bind to specified as KIND.VERSION.GROUP/NAME[/NAMESPACE]") cmd.Flags().StringArrayP("dependency", "d", nil, "An external library that should be included. E.g. for Maven dependencies \"mvn:org.my/app:1.0\"") cmd.Flags().BoolP("wait", "w", false, "Wait for the integration to be running") cmd.Flags().StringP("kit", "k", "", "The kit used to run the integration") @@ -117,6 +118,7 @@ type runCmdOptions struct { IntegrationName string `mapstructure:"name" yaml:",omitempty"` Profile string `mapstructure:"profile" yaml:",omitempty"` OutputFormat string `mapstructure:"output" yaml:",omitempty"` + Connects []string `mapstructure:"connects" yaml:",omitempty"` Resources []string `mapstructure:"resources" yaml:",omitempty"` OpenAPIs []string `mapstructure:"open-apis" yaml:",omitempty"` Dependencies []string `mapstructure:"dependencies" yaml:",omitempty"` @@ -658,7 +660,12 @@ func (o *runCmdOptions) GetIntegrationName(sources []string) string { return name } -func (*runCmdOptions) configureTraits(integration *v1.Integration, options []string, catalog *trait.Catalog) error { +func (o *runCmdOptions) configureTraits(integration *v1.Integration, options []string, catalog *trait.Catalog) error { + // configure ServiceBinding trait + for _, sb := range o.Connects { + bindings := fmt.Sprintf("service-binding.service-bindings=%s", sb) + options = append(options, bindings) + } traits, err := configureTraits(options, catalog) if err != nil { return err diff --git a/pkg/controller/integration/integration_controller.go b/pkg/controller/integration/integration_controller.go index 5a1b5fe..012a20c 100644 --- a/pkg/controller/integration/integration_controller.go +++ b/pkg/controller/integration/integration_controller.go @@ -44,6 +44,7 @@ import ( "github.com/apache/camel-k/pkg/util/digest" "github.com/apache/camel-k/pkg/util/log" "github.com/apache/camel-k/pkg/util/monitoring" + sb "github.com/redhat-developer/service-binding-operator/pkg/apis/operators/v1alpha1" ) // Add creates a new Integration Controller and adds it to the Manager. The Manager will set fields on the Controller @@ -217,6 +218,15 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error { return err } + // Watch ServiceBindings created + err = c.Watch(&source.Kind{Type: &sb.ServiceBinding{}}, &handler.EnqueueRequestForOwner{ + OwnerType: &v1.Integration{}, + IsController: true, + }) + if err != nil { + return err + } + return nil } diff --git a/pkg/controller/integration/platform_setup.go b/pkg/controller/integration/platform_setup.go index 51c5a5b..0bf4127 100644 --- a/pkg/controller/integration/platform_setup.go +++ b/pkg/controller/integration/platform_setup.go @@ -46,7 +46,8 @@ func (action *platformSetupAction) Name() string { // CanHandle tells whether this action can handle the integration func (action *platformSetupAction) CanHandle(integration *v1.Integration) bool { return integration.Status.Phase == v1.IntegrationPhaseNone || - integration.Status.Phase == v1.IntegrationPhaseWaitingForPlatform + integration.Status.Phase == v1.IntegrationPhaseWaitingForPlatform || + integration.Status.Phase == v1.IntegrationPhaseWaitingForServiceBindingCollectionReady } // Handle handles the integrations diff --git a/pkg/trait/deployer.go b/pkg/trait/deployer.go index 81aaee8..ed11cf4 100644 --- a/pkg/trait/deployer.go +++ b/pkg/trait/deployer.go @@ -49,6 +49,7 @@ func newDeployerTrait() Trait { func (t *deployerTrait) Configure(e *Environment) (bool, error) { return e.IntegrationInPhase( v1.IntegrationPhaseNone, + v1.IntegrationPhaseWaitingForServiceBindingCollectionReady, v1.IntegrationPhaseWaitingForPlatform, v1.IntegrationPhaseInitialization, v1.IntegrationPhaseBuildingKit, @@ -79,7 +80,7 @@ func (t *deployerTrait) Apply(e *Environment) error { }) } - case v1.IntegrationPhaseRunning: + case v1.IntegrationPhaseRunning, v1.IntegrationPhaseWaitingForServiceBindingCollectionReady: // Register a post action that patches the resources generated by the traits e.PostActions = append(e.PostActions, func(env *Environment) error { for _, resource := range env.Resources.Items() { diff --git a/pkg/trait/service_binding.go b/pkg/trait/service_binding.go new file mode 100644 index 0000000..131d2c5 --- /dev/null +++ b/pkg/trait/service_binding.go @@ -0,0 +1,266 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package trait + +import ( + "fmt" + "strings" + + v1 "github.com/apache/camel-k/pkg/apis/camel/v1" + sb "github.com/redhat-developer/service-binding-operator/pkg/apis/operators/v1alpha1" + corev1 "k8s.io/api/core/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + k8sclient "sigs.k8s.io/controller-runtime/pkg/client" +) + +// The Service Binding trait allows users to connect to Provisioned Services and ServiceBindings in Kubernetes: +// https://github.com/k8s-service-bindings/spec#service-binding +// As the specification is still evolving this is subject to change +// +camel-k:trait=service-binding +type serviceBindingTrait struct { + BaseTrait `property:",squash"` + // List of Provisioned Services and ServiceBindings in the form KIND.VERSION.GROUP/NAME[/NAMESPACE] + ServiceBindings []string `property:"service-bindings" json:"serviceBindings,omitempty"` +} + +func newServiceBindingTrait() Trait { + return &serviceBindingTrait{ + BaseTrait: NewBaseTrait("service-binding", 250), + } +} + +// IsAllowedInProfile overrides default +func (t *serviceBindingTrait) IsAllowedInProfile(profile v1.TraitProfile) bool { + return profile == v1.TraitProfileKubernetes || + profile == v1.TraitProfileOpenShift +} + +func (t *serviceBindingTrait) Configure(e *Environment) (bool, error) { + if t.Enabled != nil && !*t.Enabled { + return false, nil + } + + if len(t.ServiceBindings) == 0 { + return false, nil + } + + return e.IntegrationInPhase( + v1.IntegrationPhaseInitialization, + v1.IntegrationPhaseWaitingForServiceBindingCollectionReady, + v1.IntegrationPhaseDeploying, + v1.IntegrationPhaseRunning, + ), nil +} + +func (t *serviceBindingTrait) Apply(e *Environment) error { + integrationServiceBindingName := e.Integration.Name + "-service-binding-request" + services, err := t.parseProvisionedServices(e) + if err != nil { + return err + } + serviceBindings, err := t.parseServiceBindings(e) + if err != nil { + return err + } + if len(services) > 0 { + serviceBindings = append(serviceBindings, integrationServiceBindingName) + } + if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) { + serviceBindingsCollectionReady := true + for _, name := range serviceBindings { + isIntSB := name == integrationServiceBindingName + serviceBinding, err := t.getServiceBinding(e, name) + // Do not throw an error if the ServiceBinding is not found and if we are managing it: we will create it + if (err != nil && !k8serrors.IsNotFound(err)) || (err != nil && !isIntSB) { + return err + } + if isIntSB { + request := createServiceBinding(e, services, integrationServiceBindingName) + e.Resources.Add(&request) + } + if isCollectionReady(serviceBinding) { + setCollectionReady(e, name, corev1.ConditionTrue) + } else { + setCollectionReady(e, name, corev1.ConditionFalse) + serviceBindingsCollectionReady = false + } + } + if !serviceBindingsCollectionReady { + e.PostProcessors = append(e.PostProcessors, func(environment *Environment) error { + e.Integration.Status.Phase = v1.IntegrationPhaseWaitingForServiceBindingCollectionReady + return nil + }) + } + return nil + } else if e.IntegrationInPhase(v1.IntegrationPhaseWaitingForServiceBindingCollectionReady) { + for _, name := range serviceBindings { + serviceBinding, err := t.getServiceBinding(e, name) + if err != nil { + return err + } + if isCollectionReady(serviceBinding) { + setCollectionReady(e, name, corev1.ConditionTrue) + } else { + setCollectionReady(e, name, corev1.ConditionFalse) + return nil + } + } + e.PostActions = append(e.PostActions, func(environment *Environment) error { + e.Integration.Status.Phase = v1.IntegrationPhaseInitialization + return nil + }) + } else if e.IntegrationInPhase(v1.IntegrationPhaseDeploying, v1.IntegrationPhaseRunning) { + e.ServiceBindings = make(map[string]string) + for _, name := range serviceBindings { + sb, err := t.getServiceBinding(e, name) + if err != nil { + return err + } + if !isCollectionReady(sb) { + setCollectionReady(e, name, corev1.ConditionFalse) + e.PostProcessors = append(e.PostProcessors, func(environment *Environment) error { + e.Integration.Status.Phase = v1.IntegrationPhaseWaitingForServiceBindingCollectionReady + return nil + }) + return nil + } + e.ServiceBindings[name] = sb.Status.Secret + if name == integrationServiceBindingName { + request := createServiceBinding(e, services, integrationServiceBindingName) + e.Resources.Add(&request) + } + } + e.ApplicationProperties["quarkus.kubernetes-service-binding.enabled"] = "true" + e.ApplicationProperties["SERVICE_BINDING_ROOT"] = ServiceBindingsMountPath + } + return nil +} + +func setCollectionReady(e *Environment, serviceBinding string, status corev1.ConditionStatus) { + e.Integration.Status.SetCondition( + v1.IntegrationConditionServiceBindingCollectionReady, + status, + "", + fmt.Sprintf("Name=%s", serviceBinding), + ) +} + +func isCollectionReady(sb sb.ServiceBinding) bool { + for _, condition := range sb.Status.Conditions { + if condition.Type == "CollectionReady" { + return condition.Status == corev1.ConditionTrue && sb.Status.Secret != "" + } + } + return false +} + +func (t *serviceBindingTrait) getServiceBinding(e *Environment, name string) (sb.ServiceBinding, error) { + serviceBinding := sb.ServiceBinding{} + key := k8sclient.ObjectKey{ + Namespace: e.Integration.Namespace, + Name: name, + } + return serviceBinding, t.Client.Get(t.Ctx, key, &serviceBinding) +} + +func (t *serviceBindingTrait) parseProvisionedServices(e *Environment) ([]sb.Service, error) { + services := make([]sb.Service, 0) + for _, s := range t.ServiceBindings { + seg := strings.Split(s, "/") + if !(len(seg) == 3 || len(seg) == 2) { + return nil, fmt.Errorf("ServiceBinding: %s should be specified in the form KIND.VERSION.GROUP/NAME[/NAMESPACE]", s) + } + gvk := seg[0] + index := strings.Index(gvk, ".") + kind := seg[0][0:index] + if kind == "ServiceBinding" { + continue + } + vg := seg[0][index+1 : len(gvk)] + index = strings.Index(vg, ".") + version := vg[0:index] + group := vg[index+1 : len(vg)] + name := seg[1] + namespace := e.Integration.Namespace + if len(seg) == 3 { + namespace = seg[2] + } + namePrefix := "" + service := sb.Service{ + GroupVersionKind: metav1.GroupVersionKind{ + Group: group, + Version: version, + Kind: kind, + }, + EnvVarPrefix: &namePrefix, + LocalObjectReference: corev1.LocalObjectReference{ + Name: name, + }, + Namespace: &namespace, + } + services = append(services, service) + } + return services, nil +} + +func (t *serviceBindingTrait) parseServiceBindings(e *Environment) ([]string, error) { + serviceBindings := make([]string, 0) + for _, s := range t.ServiceBindings { + seg := strings.Split(s, "/") + if !(len(seg) == 3 || len(seg) == 2) { + return nil, fmt.Errorf("ServiceBinding: %s should be specified in the form KIND.VERSION.GROUP/NAME[/NAMESPACE]", s) + } + gvk := seg[0] + index := strings.Index(gvk, ".") + kind := seg[0][0:index] + if kind == "ServiceBinding" { + vg := seg[0][index+1 : len(gvk)] + if vg != "v1alpha1.operators.coreos.com" { + return nil, fmt.Errorf("ServiceBinding: %s VERSION.GROUP should be v1alpha1.operators.coreos.com", s) + } + if len(seg) == 3 && seg[2] != e.Integration.Namespace { + return nil, fmt.Errorf("ServiceBinding: %s should be in the same namespace %s as the integration", s, e.Integration.Namespace) + } + serviceBindings = append(serviceBindings, seg[1]) + } + } + return serviceBindings, nil +} + +func createServiceBinding(e *Environment, services []sb.Service, name string) sb.ServiceBinding { + spec := sb.ServiceBindingSpec{ + Services: services, + } + labels := map[string]string{ + v1.IntegrationLabel: e.Integration.Name, + } + serviceBinding := sb.ServiceBinding{ + TypeMeta: metav1.TypeMeta{ + Kind: "ServiceBinding", + APIVersion: "operators.coreos.com/v1alpha1", + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: e.Integration.Namespace, + Name: name, + Labels: labels, + }, + Spec: spec, + } + return serviceBinding +} diff --git a/pkg/trait/trait_register.go b/pkg/trait/trait_register.go index ef171c7..1ec4e31 100644 --- a/pkg/trait/trait_register.go +++ b/pkg/trait/trait_register.go @@ -45,6 +45,7 @@ func init() { AddToTraits(newRouteTrait) AddToTraits(newIstioTrait) AddToTraits(newIngressTrait) + AddToTraits(newServiceBindingTrait) AddToTraits(newOwnerTrait) AddToTraits(newPdbTrait) } diff --git a/pkg/trait/trait_types.go b/pkg/trait/trait_types.go index 7b60392..ed893e0 100644 --- a/pkg/trait/trait_types.go +++ b/pkg/trait/trait_types.go @@ -42,12 +42,13 @@ import ( const True = "true" var ( - basePath = "/etc/camel" - confDPath = path.Join(basePath, "conf.d") - sourcesMountPath = path.Join(basePath, "sources") - resourcesMountPath = path.Join(basePath, "resources") - configMapsMountPath = path.Join(confDPath, "_configmaps") - secretsMountPath = path.Join(confDPath, "_secrets") + basePath = "/etc/camel" + confDPath = path.Join(basePath, "conf.d") + sourcesMountPath = path.Join(basePath, "sources") + resourcesMountPath = path.Join(basePath, "resources") + configMapsMountPath = path.Join(confDPath, "_configmaps") + secretsMountPath = path.Join(confDPath, "_secrets") + serviceBindingsMountPath = path.Join(ConfdPath, "_servicebindings") ) // Identifiable represent an identifiable type @@ -196,6 +197,7 @@ type Environment struct { EnvVars []corev1.EnvVar ApplicationProperties map[string]string Interceptors []string + ServiceBindings map[string]string } // ControllerStrategy is used to determine the kind of controller that needs to be created for the integration @@ -671,6 +673,25 @@ func (e *Environment) configureVolumesAndMounts(vols *[]corev1.Volume, mnts *[]c // // Volumes :: Additional Secrets // + // append Service Binding secrets + for _, name := range e.ServiceBindings { + refName := kubernetes.SanitizeLabel(name) + + *vols = append(*vols, corev1.Volume{ + Name: refName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: name, + }, + }, + }) + + *mnts = append(*mnts, corev1.VolumeMount{ + Name: refName, + MountPath: path.Join(serviceBindingsMountPath, strings.ToLower(name)), + }) + } + secrets := e.CollectConfigurationValues("secret") for _, secretName := range e.collectConfigurationValues("secret") { refName := kubernetes.SanitizeLabel(secretName)
