diff --git a/jobs/cloud_controller_clock/spec b/jobs/cloud_controller_clock/spec index 1f2f88ed63..d476c06397 100644 --- a/jobs/cloud_controller_clock/spec +++ b/jobs/cloud_controller_clock/spec @@ -14,6 +14,7 @@ templates: cloud_controller_ng.yml.erb: config/cloud_controller_ng.yml newrelic.yml.erb: config/newrelic.yml stacks.yml.erb: config/stacks.yml + blobstore_configs.json.erb: config/blobstore_configs.json drain.sh.erb: bin/drain ruby_version.sh.erb: bin/ruby_version.sh console.erb: bin/console @@ -172,6 +173,8 @@ properties: cc.staging_upload_password: description: "User's password used to access internal endpoints of Cloud Controller to upload files when staging" + cc.resource_pool.blobstore_provider: + description: "The provider of blobstore storage cli to use. Valid values: ['AzureRM']" cc.resource_pool.blobstore_type: description: "The type of blobstore backing to use. Valid values: ['fog', 'webdav']" default: "fog" @@ -217,7 +220,11 @@ properties: cc.resource_pool.cdn.key_pair_id: description: "Key pair name for signed download URIs" default: "" + cc.resource_pool.connection_config: + description: "Azure Storage Cli connection hash" + cc.packages.blobstore_provider: + description: "The provider of blobstore storage cli to use. Valid values: ['AzureRM']" cc.packages.blobstore_type: description: "The type of blobstore backing to use. Valid values: ['fog', 'webdav']" default: "fog" @@ -260,7 +267,11 @@ properties: cc.packages.cdn.key_pair_id: description: "Key pair name for signed download URIs" default: "" + cc.packages.connection_config: + description: "Azure Storage Cli connection hash" + cc.droplets.blobstore_provider: + description: "The provider of blobstore storage cli to use. Valid values: ['AzureRM']" cc.droplets.blobstore_type: description: "The type of blobstore backing to use. Valid values: ['fog', 'webdav']" default: "fog" @@ -300,7 +311,11 @@ properties: cc.droplets.cdn.key_pair_id: description: "Key pair name for signed download URIs" default: "" + cc.droplets.connection_config: + description: "Azure Storage Cli connection hash" + cc.buildpacks.blobstore_provider: + description: "The provider of blobstore storage cli to use. Valid values: ['AzureRM']" cc.buildpacks.blobstore_type: description: "The type of blobstore backing to use. Valid values: ['fog', 'webdav']" default: "fog" @@ -340,6 +355,8 @@ properties: cc.buildpacks.cdn.key_pair_id: description: "Key pair name for signed download URIs" default: "" + cc.buildpacks.connection_config: + description: "Azure Storage Cli connection hash" ccdb.databases: description: "Contains the name of the database on the database server" diff --git a/jobs/cloud_controller_clock/templates/blobstore_configs.json.erb b/jobs/cloud_controller_clock/templates/blobstore_configs.json.erb new file mode 100644 index 0000000000..f4e3a36370 --- /dev/null +++ b/jobs/cloud_controller_clock/templates/blobstore_configs.json.erb @@ -0,0 +1,52 @@ +<% +require "json" + +def cli_cfg_with_default_timeout(connection_cfg, blobstore_type, default_seconds: 41) + cfg = (connection_cfg || {}).dup + if blobstore_type == 'storage_cli' + if !cfg.key?('put_timeout_in_seconds') || cfg['put_timeout_in_seconds'].to_s.empty? + cfg['put_timeout_in_seconds'] = default_seconds.to_s + end + end + cfg +end + +def add(h, key, val) + return if val.nil? + return if val.respond_to?(:empty?) && val.empty? + h[key] = val +end + +def options_for(scope_prefix, provider_prop) + provider = p(provider_prop, nil) + return {} unless provider == "AzureRM" + + h = {} + h["provider"] = provider + h["account_name"] = p("#{scope_prefix}.azure_storage_account_name") + h["container_name"] = p("#{scope_prefix}.container_name") + add(h, "account_key", p("#{scope_prefix}.azure_storage_access_key")) + add(h, "environment", p("#{scope_prefix}.environment", "AzureCloud")) + add(h, "put_timeout_in_seconds", p("#{scope_prefix}.put_timeout_in_seconds", nil)) + + # optional passthrough for extra storage-cli flags + begin + custom = p("#{scope_prefix}.custom", {}) + if custom.respond_to?(:each) + custom.each { |k, v| add(h, k.to_s, v) } + end + rescue + # property might not exist; ignore + end + + cli_cfg_with_default_timeout(h, 'storage_cli') +end + +all = { + "buildpacks" => options_for("cc.buildpacks.connection_config", "cc.buildpacks.blobstore_provider"), + "droplets" => options_for("cc.droplets.connection_config", "cc.droplets.blobstore_provider"), + "packages" => options_for("cc.packages.connection_config", "cc.packages.blobstore_provider"), + "resource_pool" => options_for("cc.resource_pool.connection_config", "cc.resource_pool.blobstore_provider"), +} +-%> +<%= JSON.pretty_generate(all) %> diff --git a/jobs/cloud_controller_clock/templates/cloud_controller_ng.yml.erb b/jobs/cloud_controller_clock/templates/cloud_controller_ng.yml.erb index 71bcb24cc4..ad3e416281 100644 --- a/jobs/cloud_controller_clock/templates/cloud_controller_ng.yml.erb +++ b/jobs/cloud_controller_clock/templates/cloud_controller_ng.yml.erb @@ -38,6 +38,12 @@ readiness_port: clock: <%= p("cc.readiness_port.clock") %> pid_filename: /var/vcap/sys/run/cloud_controller_clock/cloud_controller_clock.pid + +storage_cli_config_file_droplets: /var/vcap/jobs/cloud_controller_clock/config/storage_cli_config_droplets.json +storage_cli_config_file_buildpacks: /var/vcap/jobs/cloud_controller_clock/config/storage_cli_config_buildpacks.json +storage_cli_config_file_packages: /var/vcap/jobs/cloud_controller_clock/config/storage_cli_config_packages.json +storage_cli_config_file_resource_pool: /var/vcap/jobs/cloud_controller_clock/config/storage_cli_config_resource_pool.json + newrelic_enabled: false development_mode: false diff --git a/jobs/cloud_controller_clock/templates/pre-start.sh.erb b/jobs/cloud_controller_clock/templates/pre-start.sh.erb index ff5912e8a8..a1287a685e 100644 --- a/jobs/cloud_controller_clock/templates/pre-start.sh.erb +++ b/jobs/cloud_controller_clock/templates/pre-start.sh.erb @@ -23,8 +23,30 @@ function setup_directories { chown -R vcap:vcap "$LOG_DIR" } +write_blobstore_scope_configs() { + local cfg_json="${CONFIG_DIR}/blobstore_configs.json" + if [[ ! -f "$cfg_json" ]]; then + echo "blobstore_configs.json not found at $cfg_json; skipping fan-out" + return 0 + fi + + # Use the packaged Ruby if you prefer; system Ruby is usually fine on CF VMs. + CFG="$cfg_json" DEST="$BUNDLER_DIR" ruby <<'RUBY' + require "json" + cfg_path = ENV.fetch("CFG") + dest = ENV.fetch("DEST") + data = JSON.parse(File.read(cfg_path)) + + %w[buildpacks droplets packages resource_pool].each do |k| + out = File.join(dest, "storage_cli_config_#{k}.json") + File.write(out, JSON.pretty_generate(data[k] || {})) + end +RUBY +} + function main { setup_directories + write_blobstore_scope_configs } main diff --git a/jobs/cloud_controller_ng/spec b/jobs/cloud_controller_ng/spec index de1ec2bbbd..3a1c4d9131 100644 --- a/jobs/cloud_controller_ng/spec +++ b/jobs/cloud_controller_ng/spec @@ -53,6 +53,7 @@ templates: restart_drain.sh.erb: bin/restart_drain resource_pool_ca_cert.pem.erb: config/certs/resource_pool_ca_cert.pem shutdown_drain.rb.erb: bin/shutdown_drain + blobstore_configs.json.erb: config/blobstore_configs.json ruby_version.sh.erb: bin/ruby_version.sh seed_db.sh.erb: bin/seed_db stack_check.sh.erb: bin/stack_check @@ -115,6 +116,7 @@ provides: - name: cloud_controller_internal type: cloud_controller_internal properties: + - cc.buildpacks.blobstore_provider - cc.buildpacks.blobstore_type - cc.buildpacks.buildpack_directory_key - cc.buildpacks.cdn.key_pair_id @@ -143,6 +145,7 @@ provides: - cc.default_stack - cc.default_app_lifecycle - cc.disable_private_domain_cross_space_context_path_route_sharing + - cc.droplets.blobstore_provider - cc.droplets.blobstore_type - cc.droplets.cdn.key_pair_id - cc.droplets.cdn.private_key @@ -172,6 +175,7 @@ provides: - cc.max_annotations_per_resource - cc.maximum_health_check_timeout - cc.packages.app_package_directory_key + - cc.packages.blobstore_provider - cc.packages.blobstore_type - cc.packages.cdn.key_pair_id - cc.packages.cdn.private_key @@ -187,6 +191,7 @@ provides: - cc.packages.webdav_config.private_endpoint - cc.packages.webdav_config.public_endpoint - cc.packages.webdav_config.username + - cc.resource_pool.blobstore_provider - cc.resource_pool.blobstore_type - cc.resource_pool.cdn.key_pair_id - cc.resource_pool.cdn.private_key @@ -231,6 +236,10 @@ provides: - cc.temporary_enable_deprecated_thin_webserver - cc.custom_root_links - cc.feature_flag_overrides + - cc.resource_pool.connection_config + - cc.packages.connection_config + - cc.droplets.connection_config + - cc.buildpacks.connection_config consumes: - name: database @@ -512,6 +521,8 @@ properties: default: default description: "The name of the quota definition CC will fallback on for org and space limits from the list of quota definitions." + cc.resource_pool.blobstore_provider: + description: "The provider of blobstore storage cli to use. Valid values: ['AzureRM']" cc.resource_pool.blobstore_type: description: "The type of blobstore backing to use. Valid values: ['fog', 'webdav']" default: "fog" @@ -559,7 +570,11 @@ properties: cc.resource_pool.cdn.key_pair_id: description: "Key pair name for signed download URIs" default: "" + cc.resource_pool.connection_config: + description: "Azure Storage Cli connection hash" + cc.packages.blobstore_provider: + description: "The provider of blobstore storage cli to use. Valid values: ['AzureRM']" cc.packages.blobstore_type: description: "The type of blobstore backing to use. Valid values: ['fog', 'webdav']" default: "fog" @@ -607,7 +622,11 @@ properties: cc.packages.cdn.key_pair_id: description: "Key pair name for signed download URIs" default: "" + cc.packages.connection_config: + description: "Azure Storage Cli connection hash" + cc.droplets.blobstore_provider: + description: "The provider of blobstore storage cli to use. Valid values: ['AzureRM']" cc.droplets.blobstore_type: description: "The type of blobstore backing to use. Valid values: ['fog', 'webdav']" default: "fog" @@ -652,7 +671,11 @@ properties: cc.droplets.cdn.key_pair_id: description: "Key pair name for signed download URIs" default: "" + cc.droplets.connection_config: + description: "Azure Storage Cli connection hash" + cc.buildpacks.blobstore_provider: + description: "The provider of blobstore storage cli to use. Valid values: ['AzureRM']" cc.buildpacks.blobstore_type: description: "The type of blobstore backing to use. Valid values: ['fog', 'webdav']" default: "fog" @@ -694,6 +717,8 @@ properties: cc.buildpacks.cdn.key_pair_id: description: "Key pair name for signed download URIs" default: "" + cc.buildpacks.connection_config: + description: "Azure Storage Cli connection hash" ccdb.databases: description: "Contains the name of the database on the database server" diff --git a/jobs/cloud_controller_ng/templates/blobstore_configs.json.erb b/jobs/cloud_controller_ng/templates/blobstore_configs.json.erb new file mode 100644 index 0000000000..f4e3a36370 --- /dev/null +++ b/jobs/cloud_controller_ng/templates/blobstore_configs.json.erb @@ -0,0 +1,52 @@ +<% +require "json" + +def cli_cfg_with_default_timeout(connection_cfg, blobstore_type, default_seconds: 41) + cfg = (connection_cfg || {}).dup + if blobstore_type == 'storage_cli' + if !cfg.key?('put_timeout_in_seconds') || cfg['put_timeout_in_seconds'].to_s.empty? + cfg['put_timeout_in_seconds'] = default_seconds.to_s + end + end + cfg +end + +def add(h, key, val) + return if val.nil? + return if val.respond_to?(:empty?) && val.empty? + h[key] = val +end + +def options_for(scope_prefix, provider_prop) + provider = p(provider_prop, nil) + return {} unless provider == "AzureRM" + + h = {} + h["provider"] = provider + h["account_name"] = p("#{scope_prefix}.azure_storage_account_name") + h["container_name"] = p("#{scope_prefix}.container_name") + add(h, "account_key", p("#{scope_prefix}.azure_storage_access_key")) + add(h, "environment", p("#{scope_prefix}.environment", "AzureCloud")) + add(h, "put_timeout_in_seconds", p("#{scope_prefix}.put_timeout_in_seconds", nil)) + + # optional passthrough for extra storage-cli flags + begin + custom = p("#{scope_prefix}.custom", {}) + if custom.respond_to?(:each) + custom.each { |k, v| add(h, k.to_s, v) } + end + rescue + # property might not exist; ignore + end + + cli_cfg_with_default_timeout(h, 'storage_cli') +end + +all = { + "buildpacks" => options_for("cc.buildpacks.connection_config", "cc.buildpacks.blobstore_provider"), + "droplets" => options_for("cc.droplets.connection_config", "cc.droplets.blobstore_provider"), + "packages" => options_for("cc.packages.connection_config", "cc.packages.blobstore_provider"), + "resource_pool" => options_for("cc.resource_pool.connection_config", "cc.resource_pool.blobstore_provider"), +} +-%> +<%= JSON.pretty_generate(all) %> diff --git a/jobs/cloud_controller_ng/templates/cloud_controller_ng.yml.erb b/jobs/cloud_controller_ng/templates/cloud_controller_ng.yml.erb index ebd6ac7719..ef4864eeb9 100644 --- a/jobs/cloud_controller_ng/templates/cloud_controller_ng.yml.erb +++ b/jobs/cloud_controller_ng/templates/cloud_controller_ng.yml.erb @@ -312,6 +312,11 @@ default_health_check_timeout: <%= p("cc.default_health_check_timeout") %> maximum_health_check_timeout: <%= p("cc.maximum_health_check_timeout") %> stacks_file: /var/vcap/jobs/cloud_controller_ng/config/stacks.yml +storage_cli_config_file_droplets: /var/vcap/jobs/cloud_controller_ng/config/storage_cli_config_droplets.json +storage_cli_config_file_buildpacks: /var/vcap/jobs/cloud_controller_ng/config/storage_cli_config_buildpacks.json +storage_cli_config_file_packages: /var/vcap/jobs/cloud_controller_ng/config/storage_cli_config_packages.json +storage_cli_config_file_resource_pool: /var/vcap/jobs/cloud_controller_ng/config/storage_cli_config_resource_pool.json + shared_isolation_segment_name: <%= p("cc.shared_isolation_segment_name") %> diff --git a/jobs/cloud_controller_ng/templates/pre-start.sh.erb b/jobs/cloud_controller_ng/templates/pre-start.sh.erb index 9e1c91a2a7..d0c453df70 100644 --- a/jobs/cloud_controller_ng/templates/pre-start.sh.erb +++ b/jobs/cloud_controller_ng/templates/pre-start.sh.erb @@ -18,6 +18,28 @@ source ${CC_JOB_DIR}/bin/setup_local_blobstore.sh source "${SCRIPT_DIR}/ruby_version.sh" +write_blobstore_scope_configs() { + local cfg_json="${CONFIG_DIR}/blobstore_configs.json" + if [[ ! -f "$cfg_json" ]]; then + echo "blobstore_configs.json not found at $cfg_json; skipping fan-out" + return 0 + fi + + # Use the packaged Ruby if you prefer; system Ruby is usually fine on CF VMs. + CFG="$cfg_json" DEST="$BUNDLER_DIR" ruby <<'RUBY' + require "json" + cfg_path = ENV.fetch("CFG") + dest = ENV.fetch("DEST") + data = JSON.parse(File.read(cfg_path)) + + %w[buildpacks droplets packages resource_pool].each do |k| + out = File.join(dest, "storage_cli_config_#{k}.json") + File.write(out, JSON.pretty_generate(data[k] || {})) + end +RUBY +} + + function setup_nginx_directories { mkdir -p "/var/vcap/sys/run/nginx_cc" chown -R vcap:vcap "/var/vcap/sys/run/nginx_cc" @@ -141,6 +163,7 @@ function start_consul_agent { function main { start_bosh_dns_or_consul setup_directories + write_blobstore_scope_configs <% if spec.bootstrap && p('cc.run_prestart_migrations') %> stack_check perform_migration diff --git a/jobs/cloud_controller_worker/spec b/jobs/cloud_controller_worker/spec index e6997d43b7..63a3038aa6 100644 --- a/jobs/cloud_controller_worker/spec +++ b/jobs/cloud_controller_worker/spec @@ -16,6 +16,7 @@ templates: newrelic.yml.erb: config/newrelic.yml drain.sh.erb: bin/drain stacks.yml.erb: config/stacks.yml + blobstore_configs.json.erb: config/blobstore_configs.json ruby_version.sh.erb: bin/ruby_version.sh console.erb: bin/console blobstore_waiter.sh.erb: bin/blobstore_waiter.sh @@ -139,6 +140,8 @@ properties: cc.staging_upload_password: description: "User's password used to access internal endpoints of Cloud Controller to upload files when staging" + cc.resource_pool.blobstore_provider: + description: "The provider of blobstore storage cli to use. Valid values: ['AzureRM']" cc.resource_pool.blobstore_type: description: "The type of blobstore backing to use. Valid values: ['fog', 'webdav']" default: "fog" @@ -184,7 +187,11 @@ properties: cc.resource_pool.cdn.key_pair_id: description: "Key pair name for signed download URIs" default: "" + cc.resource_pool.connection_config: + description: "Azure Storage Cli connection hash" + cc.packages.blobstore_provider: + description: "The provider of blobstore storage cli to use. Valid values: ['AzureRM']" cc.packages.blobstore_type: description: "The type of blobstore backing to use. Valid values: ['fog', 'webdav']" default: "fog" @@ -227,7 +234,11 @@ properties: cc.packages.cdn.key_pair_id: description: "Key pair name for signed download URIs" default: "" + cc.packages.connection_config: + description: "Azure Storage Cli connection hash" + cc.droplets.blobstore_provider: + description: "The provider of blobstore storage cli to use. Valid values: ['AzureRM']" cc.droplets.blobstore_type: description: "The type of blobstore backing to use. Valid values: ['fog', 'webdav']" default: "fog" @@ -267,7 +278,11 @@ properties: cc.droplets.cdn.key_pair_id: description: "Key pair name for signed download URIs" default: "" + cc.droplets.connection_config: + description: "Azure Storage Cli connection hash" + cc.buildpacks.blobstore_provider: + description: "The provider of blobstore storage cli to use. Valid values: ['AzureRM']" cc.buildpacks.blobstore_type: description: "The type of blobstore backing to use. Valid values: ['fog', 'webdav']" default: "fog" @@ -307,6 +322,8 @@ properties: cc.buildpacks.cdn.key_pair_id: description: "Key pair name for signed download URIs" default: "" + cc.buildpacks.connection_config: + description: "Azure Storage Cli connection hash" ccdb.databases: description: "Contains the name of the database on the database server" diff --git a/jobs/cloud_controller_worker/templates/blobstore_configs.json.erb b/jobs/cloud_controller_worker/templates/blobstore_configs.json.erb new file mode 100644 index 0000000000..f4e3a36370 --- /dev/null +++ b/jobs/cloud_controller_worker/templates/blobstore_configs.json.erb @@ -0,0 +1,52 @@ +<% +require "json" + +def cli_cfg_with_default_timeout(connection_cfg, blobstore_type, default_seconds: 41) + cfg = (connection_cfg || {}).dup + if blobstore_type == 'storage_cli' + if !cfg.key?('put_timeout_in_seconds') || cfg['put_timeout_in_seconds'].to_s.empty? + cfg['put_timeout_in_seconds'] = default_seconds.to_s + end + end + cfg +end + +def add(h, key, val) + return if val.nil? + return if val.respond_to?(:empty?) && val.empty? + h[key] = val +end + +def options_for(scope_prefix, provider_prop) + provider = p(provider_prop, nil) + return {} unless provider == "AzureRM" + + h = {} + h["provider"] = provider + h["account_name"] = p("#{scope_prefix}.azure_storage_account_name") + h["container_name"] = p("#{scope_prefix}.container_name") + add(h, "account_key", p("#{scope_prefix}.azure_storage_access_key")) + add(h, "environment", p("#{scope_prefix}.environment", "AzureCloud")) + add(h, "put_timeout_in_seconds", p("#{scope_prefix}.put_timeout_in_seconds", nil)) + + # optional passthrough for extra storage-cli flags + begin + custom = p("#{scope_prefix}.custom", {}) + if custom.respond_to?(:each) + custom.each { |k, v| add(h, k.to_s, v) } + end + rescue + # property might not exist; ignore + end + + cli_cfg_with_default_timeout(h, 'storage_cli') +end + +all = { + "buildpacks" => options_for("cc.buildpacks.connection_config", "cc.buildpacks.blobstore_provider"), + "droplets" => options_for("cc.droplets.connection_config", "cc.droplets.blobstore_provider"), + "packages" => options_for("cc.packages.connection_config", "cc.packages.blobstore_provider"), + "resource_pool" => options_for("cc.resource_pool.connection_config", "cc.resource_pool.blobstore_provider"), +} +-%> +<%= JSON.pretty_generate(all) %> diff --git a/jobs/cloud_controller_worker/templates/cloud_controller_ng.yml.erb b/jobs/cloud_controller_worker/templates/cloud_controller_ng.yml.erb index 6ff07aae79..7f375dd652 100644 --- a/jobs/cloud_controller_worker/templates/cloud_controller_ng.yml.erb +++ b/jobs/cloud_controller_worker/templates/cloud_controller_ng.yml.erb @@ -154,6 +154,10 @@ default_health_check_timeout: <%= p("cc.default_health_check_timeout") %> maximum_health_check_timeout: <%= p("cc.maximum_health_check_timeout") %> stacks_file: /var/vcap/jobs/cloud_controller_worker/config/stacks.yml +storage_cli_config_file_droplets: /var/vcap/jobs/cloud_controller_worker/config/storage_cli_config_droplets.json +storage_cli_config_file_buildpacks: /var/vcap/jobs/cloud_controller_worker/config/storage_cli_config_buildpacks.json +storage_cli_config_file_packages: /var/vcap/jobs/cloud_controller_worker/config/storage_cli_config_packages.json +storage_cli_config_file_resource_pool: /var/vcap/jobs/cloud_controller_worker/config/storage_cli_config_resource_pool.json resource_pool: blobstore_type: <%= p("cc.resource_pool.blobstore_type") %> diff --git a/jobs/cloud_controller_worker/templates/pre-start.sh.erb b/jobs/cloud_controller_worker/templates/pre-start.sh.erb index dca9855e2d..508aef279e 100644 --- a/jobs/cloud_controller_worker/templates/pre-start.sh.erb +++ b/jobs/cloud_controller_worker/templates/pre-start.sh.erb @@ -26,8 +26,30 @@ function setup_directories { chpst -u vcap:vcap chmod -R go-w $BUNDLER_DIR } +write_blobstore_scope_configs() { + local cfg_json="${CONFIG_DIR}/blobstore_configs.json" + if [[ ! -f "$cfg_json" ]]; then + echo "blobstore_configs.json not found at $cfg_json; skipping fan-out" + return 0 + fi + + # Use the packaged Ruby if you prefer; system Ruby is usually fine on CF VMs. + CFG="$cfg_json" DEST="$BUNDLER_DIR" ruby <<'RUBY' + require "json" + cfg_path = ENV.fetch("CFG") + dest = ENV.fetch("DEST") + data = JSON.parse(File.read(cfg_path)) + + %w[buildpacks droplets packages resource_pool].each do |k| + out = File.join(dest, "storage_cli_config_#{k}.json") + File.write(out, JSON.pretty_generate(data[k] || {})) + end +RUBY +} + function main { setup_directories + write_blobstore_scope_configs } main diff --git a/spec/cloud_controller_ng/cloud_controller_ng_spec.rb b/spec/cloud_controller_ng/cloud_controller_ng_spec.rb index c81045a003..42f431d4b2 100644 --- a/spec/cloud_controller_ng/cloud_controller_ng_spec.rb +++ b/spec/cloud_controller_ng/cloud_controller_ng_spec.rb @@ -942,14 +942,14 @@ module Test end end - context 'when it is set to buidpack' do + context 'when it is set to buildpack' do before do - merged_manifest_properties['cc']['default_app_lifecycle'] = 'buidpack' + merged_manifest_properties['cc']['default_app_lifecycle'] = 'buildpack' end - it 'renders it as buidpack' do + it 'renders it as buildpack' do template_hash = YAML.safe_load(template.render(merged_manifest_properties, consumes: links)) - expect(template_hash['default_app_lifecycle']).to eq('buidpack') + expect(template_hash['default_app_lifecycle']).to eq('buildpack') end end @@ -963,23 +963,35 @@ module Test expect(template_hash['default_app_lifecycle']).to eq('cnb') end end - end - context 'with max_service_credential_bindings_per_app_service_instance parameter' do - it 'defaults to 1' do - template_hash = YAML.safe_load(template.render(merged_manifest_properties, consumes: links)) - expect(template_hash['max_service_credential_bindings_per_app_service_instance']).to eq(1) - end + context 'with max_service_credential_bindings_per_app_service_instance parameter' do + it 'defaults to 1' do + template_hash = YAML.safe_load(template.render(merged_manifest_properties, consumes: links)) + expect(template_hash['max_service_credential_bindings_per_app_service_instance']).to eq(1) + end - context 'when set in the manifest' do - before { merged_manifest_properties['cc']['max_service_credential_bindings_per_app_service_instance'] = 5 } + context 'when set in the manifest' do + before { merged_manifest_properties['cc']['max_service_credential_bindings_per_app_service_instance'] = 5 } - it 'renders the value from the manifest' do - template_hash = YAML.safe_load(template.render(merged_manifest_properties, consumes: links)) - expect(template_hash['max_service_credential_bindings_per_app_service_instance']).to eq(5) + it 'renders the value from the manifest' do + template_hash = YAML.safe_load(template.render(merged_manifest_properties, consumes: links)) + expect(template_hash['max_service_credential_bindings_per_app_service_instance']).to eq(5) + end end end end + + describe 'storage_cli_config_file_* paths' do + let(:template) { job.template('config/cloud_controller_ng.yml') } + + it 'renders absolute paths for all four scope files' do + yaml = YAML.safe_load(template.render(merged_manifest_properties, consumes: links)) + expect(yaml['storage_cli_config_file_droplets']).to eq('/var/vcap/jobs/cloud_controller_ng/config/storage_cli_config_droplets.json') + expect(yaml['storage_cli_config_file_packages']).to eq('/var/vcap/jobs/cloud_controller_ng/config/storage_cli_config_packages.json') + expect(yaml['storage_cli_config_file_buildpacks']).to eq('/var/vcap/jobs/cloud_controller_ng/config/storage_cli_config_buildpacks.json') + expect(yaml['storage_cli_config_file_resource_pool']).to eq('/var/vcap/jobs/cloud_controller_ng/config/storage_cli_config_resource_pool.json') + end + end end end end diff --git a/spec/cloud_controller_ng/storage_cli_config_jsons_spec.rb b/spec/cloud_controller_ng/storage_cli_config_jsons_spec.rb new file mode 100644 index 0000000000..f16a292b0a --- /dev/null +++ b/spec/cloud_controller_ng/storage_cli_config_jsons_spec.rb @@ -0,0 +1,98 @@ +# frozen_string_literal: true + +require 'rspec' +require 'yaml' +require 'bosh/template/test' + +TEMPLATES = { + droplets: ['config/blobstore_configs.json', %w[cc droplets connection_config]], + buildpacks: ['config/blobstore_configs.json', %w[cc buildpacks connection_config]], + packages: ['config/blobstore_configs.json', %w[cc packages connection_config]], + resource_pool: ['config/blobstore_configs.json', %w[cc resource_pool connection_config]] +}.freeze + +module Bosh + module Template + module Test + RSpec.describe 'storage-cli JSON templates' do + let(:release_path) { File.join(File.dirname(__FILE__), '../..') } + let(:release) { ReleaseDir.new(release_path) } + let(:job) { release.job('cloud_controller_ng') } + let(:links) { {} } + + # Default all scopes to non-Azure so only the scope under test must be populated + let(:props) do + { + 'cc' => { + 'droplets' => { 'connection_config' => {}, 'blobstore_provider' => 'S3' }, + 'buildpacks' => { 'connection_config' => {}, 'blobstore_provider' => 'S3' }, + 'packages' => { 'connection_config' => {}, 'blobstore_provider' => 'S3' }, + 'resource_pool' => { 'connection_config' => {}, 'blobstore_provider' => 'S3' } + } + } + end + + TEMPLATES.each do |scope, (template_path, keypath)| + describe template_path do + let(:template) { job.template(template_path) } + + def set(hash, path, value) + cursor = hash + path[0..-2].each { |key| cursor = (cursor[key] ||= {}) } + cursor[path.last] = value + end + + context "when provider is AzureRM for #{scope}" do + before do + props['cc'][scope.to_s]['blobstore_provider'] = 'AzureRM' + end + + it 'renders and normalizes put_timeout_in_seconds to "41" when blank' do + set(props, keypath, { + 'provider' => 'AzureRM', + 'azure_storage_account_name' => 'acc', + 'azure_storage_access_key' => 'key', + 'container_name' => 'cont', + 'put_timeout_in_seconds' => '' + }) + + full = YAML.safe_load(template.render(props, consumes: links)) + json = full.fetch(scope.to_s) + expect(json).to include( + 'provider' => 'AzureRM', + 'account_name' => 'acc', + 'account_key' => 'key', + 'container_name' => 'cont', + 'put_timeout_in_seconds' => '41' + ) + end + + it 'keeps existing put_timeout_in_seconds when provided' do + set(props, keypath, { + 'provider' => 'AzureRM', + 'azure_storage_account_name' => 'acc', + 'azure_storage_access_key' => 'key', + 'container_name' => 'cont', + 'put_timeout_in_seconds' => '7' + }) + + full = YAML.safe_load(template.render(props, consumes: links)) + json = full.fetch(scope.to_s) + expect(json['put_timeout_in_seconds']).to eq('7') + end + end + + context "when provider is non-Azure for #{scope}" do + it 'renders {}' do + # leave default 'S3' for this scope + full = YAML.safe_load(template.render(props, consumes: links)) + json = full.fetch(scope.to_s) + expect(json).to eq({}) + end + end + end + end + end + end + end +end