diff --git a/dist/origin-web-common-services.js b/dist/origin-web-common-services.js index a438cbd..23a7071 100644 --- a/dist/origin-web-common-services.js +++ b/dist/origin-web-common-services.js @@ -1031,6 +1031,9 @@ angular.module("openshiftCommonServices") AuthService, DataService, DNS1123_SUBDOMAIN_VALIDATION) { + // The secret key this service uses for the parameters JSON blob when binding. + var PARAMETERS_SECRET_KEY = 'parameters'; + var bindingResource = { group: 'servicecatalog.k8s.io', resource: 'bindings' @@ -1046,23 +1049,49 @@ angular.module("openshiftCommonServices") return _.find(serviceClass.plans, { name: planName }); }; - var getBindParameters = function(serviceInstance, serviceClass) { - var plan = getPlanForInstance(serviceInstance, serviceClass); - if (_.has(plan, ['alphaBindingCreateParameterSchema', 'properties', 'template.openshift.io/requester-username'])) { - return AuthService.withUser().then(function(user) { - return { - 'template.openshift.io/requester-username': user.metadata.name - }; - }); - } + var generateName = $filter('generateName'); + var generateSecretName = function(prefix) { + var generateNameLength = 5; + // Truncate the class name if it's too long to append the generated name suffix. + var secretNamePrefix = _.truncate(prefix, { + // `generateNameLength - 1` because we append a '-' and then a 5 char generated suffix + length: DNS1123_SUBDOMAIN_VALIDATION.maxlength - generateNameLength - 1, + omission: '' + }); - return $q.when({}); + return generateName(secretNamePrefix, generateNameLength); }; - var generateName = $filter('generateName'); - var makeBinding = function (serviceInstance, application, parameters) { + var makeParametersSecret = function(secretName, parameters, binding) { + var secret = { + apiVersion: 'v1', + kind: 'Secret', + metadata: { + name: secretName, + ownerReferences: [{ + apiVersion: binding.apiVersion, + kind: binding.kind, + name: binding.metadata.name, + uid: binding.metadata.uid, + controller: false, + // TODO: Change to true when garbage collection works with service + // catalog resources. Setting to true now results in a 403 Forbidden + // error creating the secret. + blockOwnerDeletion: false + }] + }, + type: 'Opaque', + stringData: {} + }; + + secret.stringData[PARAMETERS_SECRET_KEY] = JSON.stringify(parameters); + return secret; + }; + + var makeBinding = function(serviceInstance, application, parametersSecretName) { + var parametersSecretName; var instanceName = serviceInstance.metadata.name; - var relatedObjName = generateName(_.truncate(instanceName, DNS1123_SUBDOMAIN_VALIDATION.maxlength - 6) + '-'); + var binding = { kind: 'Binding', apiVersion: 'servicecatalog.k8s.io/v1alpha1', @@ -1073,12 +1102,17 @@ angular.module("openshiftCommonServices") instanceRef: { name: instanceName }, - secretName: relatedObjName + secretName: generateSecretName(serviceInstance.metadata.name + '-credentials-') } }; - if (!_.isEmpty(parameters)) { - binding.spec.parameters = parameters; + if (parametersSecretName) { + binding.spec.parametersFrom = [{ + secretKeyRef: { + name: parametersSecretName, + key: PARAMETERS_SECRET_KEY + } + }]; } var appSelector = _.get(application, 'spec.selector'); @@ -1190,18 +1224,34 @@ angular.module("openshiftCommonServices") return { bindingResource: bindingResource, getServiceClassForInstance: getServiceClassForInstance, + getPlanForInstance: getPlanForInstance, // Create a binding for `serviceInstance`. If an `application` API object // is specified, also create a pod preset for that application using its // `spec.selector`. `serviceClass` is required to determine if any // parameters need to be set when creating the binding. - bindService: function(serviceInstance, application, serviceClass) { - return getBindParameters(serviceInstance, serviceClass).then(function (parameters) { - var newBinding = makeBinding(serviceInstance, application, parameters); - var context = { - namespace: serviceInstance.metadata.namespace - }; - return DataService.create(bindingResource, null, newBinding, context); + bindService: function(serviceInstance, application, serviceClass, parameters) { + var parametersSecretName; + if (!_.isEmpty(parameters)) { + parametersSecretName = generateSecretName(serviceInstance.metadata.name + '-bind-parameters-'); + } + + var newBinding = makeBinding(serviceInstance, application, parametersSecretName); + var context = { + namespace: serviceInstance.metadata.namespace + }; + + var promise = DataService.create(bindingResource, null, newBinding, context); + if (!parametersSecretName) { + return promise; + } + + // Create the secret as well if the binding has parameters. + return promise.then(function(binding) { + var parametersSecret = makeParametersSecret(parametersSecretName, parameters, binding); + return DataService.create("secrets", null, parametersSecret, context).then(function() { + return binding; + }); }); }, diff --git a/dist/origin-web-common.js b/dist/origin-web-common.js index 3a3799b..417b64e 100644 --- a/dist/origin-web-common.js +++ b/dist/origin-web-common.js @@ -2911,6 +2911,9 @@ angular.module("openshiftCommonServices") AuthService, DataService, DNS1123_SUBDOMAIN_VALIDATION) { + // The secret key this service uses for the parameters JSON blob when binding. + var PARAMETERS_SECRET_KEY = 'parameters'; + var bindingResource = { group: 'servicecatalog.k8s.io', resource: 'bindings' @@ -2926,23 +2929,49 @@ angular.module("openshiftCommonServices") return _.find(serviceClass.plans, { name: planName }); }; - var getBindParameters = function(serviceInstance, serviceClass) { - var plan = getPlanForInstance(serviceInstance, serviceClass); - if (_.has(plan, ['alphaBindingCreateParameterSchema', 'properties', 'template.openshift.io/requester-username'])) { - return AuthService.withUser().then(function(user) { - return { - 'template.openshift.io/requester-username': user.metadata.name - }; - }); - } + var generateName = $filter('generateName'); + var generateSecretName = function(prefix) { + var generateNameLength = 5; + // Truncate the class name if it's too long to append the generated name suffix. + var secretNamePrefix = _.truncate(prefix, { + // `generateNameLength - 1` because we append a '-' and then a 5 char generated suffix + length: DNS1123_SUBDOMAIN_VALIDATION.maxlength - generateNameLength - 1, + omission: '' + }); - return $q.when({}); + return generateName(secretNamePrefix, generateNameLength); }; - var generateName = $filter('generateName'); - var makeBinding = function (serviceInstance, application, parameters) { + var makeParametersSecret = function(secretName, parameters, binding) { + var secret = { + apiVersion: 'v1', + kind: 'Secret', + metadata: { + name: secretName, + ownerReferences: [{ + apiVersion: binding.apiVersion, + kind: binding.kind, + name: binding.metadata.name, + uid: binding.metadata.uid, + controller: false, + // TODO: Change to true when garbage collection works with service + // catalog resources. Setting to true now results in a 403 Forbidden + // error creating the secret. + blockOwnerDeletion: false + }] + }, + type: 'Opaque', + stringData: {} + }; + + secret.stringData[PARAMETERS_SECRET_KEY] = JSON.stringify(parameters); + return secret; + }; + + var makeBinding = function(serviceInstance, application, parametersSecretName) { + var parametersSecretName; var instanceName = serviceInstance.metadata.name; - var relatedObjName = generateName(_.truncate(instanceName, DNS1123_SUBDOMAIN_VALIDATION.maxlength - 6) + '-'); + var binding = { kind: 'Binding', apiVersion: 'servicecatalog.k8s.io/v1alpha1', @@ -2953,12 +2982,17 @@ angular.module("openshiftCommonServices") instanceRef: { name: instanceName }, - secretName: relatedObjName + secretName: generateSecretName(serviceInstance.metadata.name + '-credentials-') } }; - if (!_.isEmpty(parameters)) { - binding.spec.parameters = parameters; + if (parametersSecretName) { + binding.spec.parametersFrom = [{ + secretKeyRef: { + name: parametersSecretName, + key: PARAMETERS_SECRET_KEY + } + }]; } var appSelector = _.get(application, 'spec.selector'); @@ -3070,18 +3104,34 @@ angular.module("openshiftCommonServices") return { bindingResource: bindingResource, getServiceClassForInstance: getServiceClassForInstance, + getPlanForInstance: getPlanForInstance, // Create a binding for `serviceInstance`. If an `application` API object // is specified, also create a pod preset for that application using its // `spec.selector`. `serviceClass` is required to determine if any // parameters need to be set when creating the binding. - bindService: function(serviceInstance, application, serviceClass) { - return getBindParameters(serviceInstance, serviceClass).then(function (parameters) { - var newBinding = makeBinding(serviceInstance, application, parameters); - var context = { - namespace: serviceInstance.metadata.namespace - }; - return DataService.create(bindingResource, null, newBinding, context); + bindService: function(serviceInstance, application, serviceClass, parameters) { + var parametersSecretName; + if (!_.isEmpty(parameters)) { + parametersSecretName = generateSecretName(serviceInstance.metadata.name + '-bind-parameters-'); + } + + var newBinding = makeBinding(serviceInstance, application, parametersSecretName); + var context = { + namespace: serviceInstance.metadata.namespace + }; + + var promise = DataService.create(bindingResource, null, newBinding, context); + if (!parametersSecretName) { + return promise; + } + + // Create the secret as well if the binding has parameters. + return promise.then(function(binding) { + var parametersSecret = makeParametersSecret(parametersSecretName, parameters, binding); + return DataService.create("secrets", null, parametersSecret, context).then(function() { + return binding; + }); }); }, diff --git a/dist/origin-web-common.min.js b/dist/origin-web-common.min.js index f968a9e..1346dfc 100644 --- a/dist/origin-web-common.min.js +++ b/dist/origin-web-common.min.js @@ -1158,7 +1158,7 @@ return data; } }; }), angular.module("openshiftCommonServices").service("BindingService", [ "$filter", "$q", "AuthService", "DataService", "DNS1123_SUBDOMAIN_VALIDATION", function($filter, $q, AuthService, DataService, DNS1123_SUBDOMAIN_VALIDATION) { -var bindingResource = { +var PARAMETERS_SECRET_KEY = "parameters", bindingResource = { group:"servicecatalog.k8s.io", resource:"bindings" }, getServiceClassForInstance = function(serviceInstance, serviceClasses) { @@ -1169,15 +1169,33 @@ var planName = _.get(serviceInstance, "spec.planName"); return _.find(serviceClass.plans, { name:planName }); -}, getBindParameters = function(serviceInstance, serviceClass) { -var plan = getPlanForInstance(serviceInstance, serviceClass); -return _.has(plan, [ "alphaBindingCreateParameterSchema", "properties", "template.openshift.io/requester-username" ]) ? AuthService.withUser().then(function(user) { -return { -"template.openshift.io/requester-username":user.metadata.name +}, generateName = $filter("generateName"), generateSecretName = function(prefix) { +var generateNameLength = 5, secretNamePrefix = _.truncate(prefix, { +length:DNS1123_SUBDOMAIN_VALIDATION.maxlength - generateNameLength - 1, +omission:"" +}); +return generateName(secretNamePrefix, generateNameLength); +}, makeParametersSecret = function(secretName, parameters, binding) { +var secret = { +apiVersion:"v1", +kind:"Secret", +metadata:{ +name:secretName, +ownerReferences:[ { +apiVersion:binding.apiVersion, +kind:binding.kind, +name:binding.metadata.name, +uid:binding.metadata.uid, +controller:!1, +blockOwnerDeletion:!1 +} ] +}, +type:"Opaque", +stringData:{} }; -}) :$q.when({}); -}, generateName = $filter("generateName"), makeBinding = function(serviceInstance, application, parameters) { -var instanceName = serviceInstance.metadata.name, relatedObjName = generateName(_.truncate(instanceName, DNS1123_SUBDOMAIN_VALIDATION.maxlength - 6) + "-"), binding = { +return secret.stringData[PARAMETERS_SECRET_KEY] = JSON.stringify(parameters), secret; +}, makeBinding = function(serviceInstance, application, parametersSecretName) { +var parametersSecretName, instanceName = serviceInstance.metadata.name, binding = { kind:"Binding", apiVersion:"servicecatalog.k8s.io/v1alpha1", metadata:{ @@ -1187,10 +1205,15 @@ spec:{ instanceRef:{ name:instanceName }, -secretName:relatedObjName +secretName:generateSecretName(serviceInstance.metadata.name + "-credentials-") } }; -_.isEmpty(parameters) || (binding.spec.parameters = parameters); +parametersSecretName && (binding.spec.parametersFrom = [ { +secretKeyRef:{ +name:parametersSecretName, +key:PARAMETERS_SECRET_KEY +} +} ]); var appSelector = _.get(application, "spec.selector"); return appSelector && (appSelector.matchLabels || appSelector.matchExpressions || (appSelector = { matchLabels:appSelector @@ -1230,13 +1253,19 @@ return _.get(item, "metadata.name", ""); return { bindingResource:bindingResource, getServiceClassForInstance:getServiceClassForInstance, -bindService:function(serviceInstance, application, serviceClass) { -return getBindParameters(serviceInstance, serviceClass).then(function(parameters) { -var newBinding = makeBinding(serviceInstance, application, parameters), context = { +getPlanForInstance:getPlanForInstance, +bindService:function(serviceInstance, application, serviceClass, parameters) { +var parametersSecretName; +_.isEmpty(parameters) || (parametersSecretName = generateSecretName(serviceInstance.metadata.name + "-bind-parameters-")); +var newBinding = makeBinding(serviceInstance, application, parametersSecretName), context = { namespace:serviceInstance.metadata.namespace -}; -return DataService.create(bindingResource, null, newBinding, context); +}, promise = DataService.create(bindingResource, null, newBinding, context); +return parametersSecretName ? promise.then(function(binding) { +var parametersSecret = makeParametersSecret(parametersSecretName, parameters, binding); +return DataService.create("secrets", null, parametersSecret, context).then(function() { +return binding; }); +}) :promise; }, isServiceBindable:isServiceBindable, getPodPresetSelectorsForBindings:getPodPresetSelectorsForBindings, diff --git a/src/services/bindService.js b/src/services/bindService.js index 5617985..85ae2b0 100644 --- a/src/services/bindService.js +++ b/src/services/bindService.js @@ -7,6 +7,9 @@ angular.module("openshiftCommonServices") AuthService, DataService, DNS1123_SUBDOMAIN_VALIDATION) { + // The secret key this service uses for the parameters JSON blob when binding. + var PARAMETERS_SECRET_KEY = 'parameters'; + var bindingResource = { group: 'servicecatalog.k8s.io', resource: 'bindings' @@ -22,23 +25,49 @@ angular.module("openshiftCommonServices") return _.find(serviceClass.plans, { name: planName }); }; - var getBindParameters = function(serviceInstance, serviceClass) { - var plan = getPlanForInstance(serviceInstance, serviceClass); - if (_.has(plan, ['alphaBindingCreateParameterSchema', 'properties', 'template.openshift.io/requester-username'])) { - return AuthService.withUser().then(function(user) { - return { - 'template.openshift.io/requester-username': user.metadata.name - }; - }); - } + var generateName = $filter('generateName'); + var generateSecretName = function(prefix) { + var generateNameLength = 5; + // Truncate the class name if it's too long to append the generated name suffix. + var secretNamePrefix = _.truncate(prefix, { + // `generateNameLength - 1` because we append a '-' and then a 5 char generated suffix + length: DNS1123_SUBDOMAIN_VALIDATION.maxlength - generateNameLength - 1, + omission: '' + }); - return $q.when({}); + return generateName(secretNamePrefix, generateNameLength); }; - var generateName = $filter('generateName'); - var makeBinding = function (serviceInstance, application, parameters) { + var makeParametersSecret = function(secretName, parameters, binding) { + var secret = { + apiVersion: 'v1', + kind: 'Secret', + metadata: { + name: secretName, + ownerReferences: [{ + apiVersion: binding.apiVersion, + kind: binding.kind, + name: binding.metadata.name, + uid: binding.metadata.uid, + controller: false, + // TODO: Change to true when garbage collection works with service + // catalog resources. Setting to true now results in a 403 Forbidden + // error creating the secret. + blockOwnerDeletion: false + }] + }, + type: 'Opaque', + stringData: {} + }; + + secret.stringData[PARAMETERS_SECRET_KEY] = JSON.stringify(parameters); + return secret; + }; + + var makeBinding = function(serviceInstance, application, parametersSecretName) { + var parametersSecretName; var instanceName = serviceInstance.metadata.name; - var relatedObjName = generateName(_.truncate(instanceName, DNS1123_SUBDOMAIN_VALIDATION.maxlength - 6) + '-'); + var binding = { kind: 'Binding', apiVersion: 'servicecatalog.k8s.io/v1alpha1', @@ -49,12 +78,17 @@ angular.module("openshiftCommonServices") instanceRef: { name: instanceName }, - secretName: relatedObjName + secretName: generateSecretName(serviceInstance.metadata.name + '-credentials-') } }; - if (!_.isEmpty(parameters)) { - binding.spec.parameters = parameters; + if (parametersSecretName) { + binding.spec.parametersFrom = [{ + secretKeyRef: { + name: parametersSecretName, + key: PARAMETERS_SECRET_KEY + } + }]; } var appSelector = _.get(application, 'spec.selector'); @@ -166,18 +200,34 @@ angular.module("openshiftCommonServices") return { bindingResource: bindingResource, getServiceClassForInstance: getServiceClassForInstance, + getPlanForInstance: getPlanForInstance, // Create a binding for `serviceInstance`. If an `application` API object // is specified, also create a pod preset for that application using its // `spec.selector`. `serviceClass` is required to determine if any // parameters need to be set when creating the binding. - bindService: function(serviceInstance, application, serviceClass) { - return getBindParameters(serviceInstance, serviceClass).then(function (parameters) { - var newBinding = makeBinding(serviceInstance, application, parameters); - var context = { - namespace: serviceInstance.metadata.namespace - }; - return DataService.create(bindingResource, null, newBinding, context); + bindService: function(serviceInstance, application, serviceClass, parameters) { + var parametersSecretName; + if (!_.isEmpty(parameters)) { + parametersSecretName = generateSecretName(serviceInstance.metadata.name + '-bind-parameters-'); + } + + var newBinding = makeBinding(serviceInstance, application, parametersSecretName); + var context = { + namespace: serviceInstance.metadata.namespace + }; + + var promise = DataService.create(bindingResource, null, newBinding, context); + if (!parametersSecretName) { + return promise; + } + + // Create the secret as well if the binding has parameters. + return promise.then(function(binding) { + var parametersSecret = makeParametersSecret(parametersSecretName, parameters, binding); + return DataService.create("secrets", null, parametersSecret, context).then(function() { + return binding; + }); }); },