diff --git a/sample/missing-properties.yml b/sample/missing-properties.yml index ebb4d56b..5b854e4c 100644 --- a/sample/missing-properties.yml +++ b/sample/missing-properties.yml @@ -5,6 +5,9 @@ city: New Jersey country: country_us username: SpongeBob password: { 'secret': SquarePants } +my_creds: + identity: username + password: p4ssw0rd app2_persistence_store_type: none # p-mysql # Works, but turned off because this is not deployed in our PCF environments dynamic_service_plans: - name: plan1 diff --git a/sample/tile.yml b/sample/tile.yml index d7ccc914..04f9067a 100644 --- a/sample/tile.yml +++ b/sample/tile.yml @@ -46,6 +46,10 @@ forms: default: true - name: country_elsewhere label: Elsewhere + - name: my_creds + type: simple_credentials + label: Some Credentials + description: Some credentials - name: account-info-1 label: Account Info description: Example Account Information Form diff --git a/tile_generator/template.py b/tile_generator/template.py index 5597a409..048ccd13 100644 --- a/tile_generator/template.py +++ b/tile_generator/template.py @@ -55,6 +55,41 @@ def render_plans_json(input): ' %>\n' ' export ' + input.upper() + '=<%= Shellwords.escape JSON.dump(plans) %>') +def render_property_value(property): + complex_types = ( + 'simple_credentials', + 'rsa_cert_credentials', + 'rsa_pkey_credentials', + 'salted_credentials', + 'selector', + ) + if property['type'] in complex_types: + return 'properties.{}.marshal_dump.to_json'.format(property['name']) + else: + return 'properties.' + property['name'] + +def render_property(property): + """Render a property for bosh manifest, according to its type.""" + # This ain't the prettiest thing, but it should get the job done. + # I don't think we have anything more elegant available at bosh-manifest-generation time. + # See https://docs.pivotal.io/partners/product-template-reference.html for list + property_fields = { + 'simple_credentials': ['identity', 'password'], + 'rsa_cert_credentials': [ 'private_key_pem', 'cert_pem', 'public_key_pem', 'cert_and_private_key_pems' ], + 'rsa_pkey_credentials': [ 'private_key_pem', 'public_key_pem', 'public_key_openssh', 'public_key_fingerprint' ], + 'salted_credentials': [ 'salt', 'identity', 'password' ], + 'selector': [ 'value', 'selected_option', 'nested context' ], + } + if 'type' in property and property['type'] in property_fields: + fields = {} + for field in property_fields[property['type']]: + fields[field] = '(( .properties.{}.{} ))'.format(property['name'], field) + out = { property['name']: fields } + else: + # Other types use 'value'. + out = { property['name']: '(( .properties.{}.value ))'.format(property['name']) } + return out + @contextfilter def render(context, input): template = Template(input) @@ -67,6 +102,8 @@ def render(context, input): TEMPLATE_ENVIRONMENT.filters['yaml'] = render_yaml TEMPLATE_ENVIRONMENT.filters['shell_string'] = render_shell_string TEMPLATE_ENVIRONMENT.filters['plans_json'] = render_plans_json +TEMPLATE_ENVIRONMENT.filters['property'] = render_property +TEMPLATE_ENVIRONMENT.filters['property_value'] = render_property_value TEMPLATE_ENVIRONMENT.filters['render'] = render def render(target_path, template_file, config): diff --git a/tile_generator/template_unittest.py b/tile_generator/template_unittest.py new file mode 100644 index 00000000..b9066ed8 --- /dev/null +++ b/tile_generator/template_unittest.py @@ -0,0 +1,41 @@ +# tile-generator +# +# Copyright (c) 2015-Present Pivotal Software, Inc. All Rights Reserved. +# +# Licensed 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. + +from __future__ import absolute_import, division, print_function +import unittest +from . import template + +class TestPropertyFilter(unittest.TestCase): + def test_property_filter_simple_property(self): + property = { + 'name': 'prop', + 'type': 'string', + } + result = template.render_property(property) + self.assertEqual(result, {'prop': '(( .properties.prop.value ))' }) + + def test_property_filter_complex_property(self): + property = { + 'name': 'prop', + 'type': 'simple_credentials', + } + result = template.render_property(property) + self.assertEqual(result, { + 'prop': { + 'identity': '(( .properties.prop.identity ))', + 'password': '(( .properties.prop.password ))', + } + }) diff --git a/tile_generator/templates/jobs/deploy-all.sh.erb b/tile_generator/templates/jobs/deploy-all.sh.erb index 7039e2c4..2be2a0f3 100644 --- a/tile_generator/templates/jobs/deploy-all.sh.erb +++ b/tile_generator/templates/jobs/deploy-all.sh.erb @@ -45,7 +45,7 @@ function import_opsmgr_variables() { {% endfor %} {% for property in context.all_properties %} - export {{ property.name | upper }}={{ ( 'properties.' + property.name ) | shell_string }} + export {{ property.name | upper }}={{ property | property_value | shell_string }} {% endfor %} {% for package in context.packages if package.type == 'docker-bosh' %} export {{ package.name | upper }}_HOST={{ ( 'properties.' + package.name + '.host' ) | shell_string }} diff --git a/tile_generator/templates/tile/metadata.yml b/tile_generator/templates/tile/metadata.yml index 17e60639..876fc006 100644 --- a/tile_generator/templates/tile/metadata.yml +++ b/tile_generator/templates/tile/metadata.yml @@ -479,7 +479,7 @@ job_types: user: (( .{{ job.name }}.app_credentials.identity )) password: (( .{{ job.name }}.app_credentials.password )) {% for property in all_properties %} - {{ property.name }}: (( .properties.{{ property.name }}.value )) + {{ property | property | yaml | indent }} {% endfor %} {% if dynamic_service_plans %} dynamic_service_plans: (( .properties.dynamic_service_plans.value ))