diff --git a/jobs/blobstore_benchmark/templates/storage_cli_config_buildpacks.json.erb b/jobs/blobstore_benchmark/templates/storage_cli_config_buildpacks.json.erb index 2e6886adf7..8317e6d134 100644 --- a/jobs/blobstore_benchmark/templates/storage_cli_config_buildpacks.json.erb +++ b/jobs/blobstore_benchmark/templates/storage_cli_config_buildpacks.json.erb @@ -91,21 +91,30 @@ if provider == "aliyun" || provider == "alioss" options["bucket_name"] = l.p("#{scope}.aliyun_oss_bucket") end -# WebDAV/dav support intentionally excluded (not fully implemented) +# Support both native storage-cli types (dav) AND legacy fog names (webdav) +# Legacy fog name support to be REMOVED May 2026 if provider == "webdav" || provider == "dav" - options["provider"] = provider + options["provider"] = "dav" options["user"] = l.p("#{scope}.username") options["password"] = l.p("#{scope}.password") - options["endpoint"] = l.p("#{scope}.public_endpoint") + + # Resource-specific directory for compatibility with fog/webdav + resource_dir = l.p("cc.buildpacks.buildpack_directory_key", "cc-buildpacks") + + private_base = l.p("#{scope}.private_endpoint") + options["endpoint"] = "#{private_base}/admin/#{resource_dir}" + + add_optional(options, "public_endpoint", l.p("#{scope}.public_endpoint", nil)) add_optional(options, "secret", l.p("#{scope}.secret", nil)) + add_optional(options, "signed_url_format", l.p("#{scope}.signed_url_format", nil)) add_optional(options, "retry_attempts", l.p("#{scope}.retry_attempts", nil)) # TLS nested object with a Cert inside ca_cert=l.p("#{scope}.ca_cert",nil) - unless ca_cert.empty? - options["tls"]={"cert"=>ca_cert} + unless ca_cert.nil? || ca_cert.empty? + options["tls"]={"cert"=>{"ca"=>ca_cert}} end end -%> -<%= JSON.pretty_generate(options) %> \ No newline at end of file +<%= JSON.pretty_generate(options) %> diff --git a/jobs/blobstore_benchmark/templates/storage_cli_config_droplets.json.erb b/jobs/blobstore_benchmark/templates/storage_cli_config_droplets.json.erb index c72cf61b76..61cb14b3ed 100644 --- a/jobs/blobstore_benchmark/templates/storage_cli_config_droplets.json.erb +++ b/jobs/blobstore_benchmark/templates/storage_cli_config_droplets.json.erb @@ -91,21 +91,30 @@ if provider == "aliyun" || provider == "alioss" options["bucket_name"] = l.p("#{scope}.aliyun_oss_bucket") end -# WebDAV/dav support intentionally excluded (not fully implemented) +# Support both native storage-cli types (dav) AND legacy fog names (webdav) +# Legacy fog name support to be REMOVED May 2026 if provider == "webdav" || provider == "dav" - options["provider"] = provider + options["provider"] = "dav" options["user"] = l.p("#{scope}.username") options["password"] = l.p("#{scope}.password") - options["endpoint"] = l.p("#{scope}.public_endpoint") + + # Resource-specific directory for compatibility with fog/webdav + resource_dir = l.p("cc.droplets.droplet_directory_key", "cc-droplets") + + private_base = l.p("#{scope}.private_endpoint") + options["endpoint"] = "#{private_base}/admin/#{resource_dir}" + + add_optional(options, "public_endpoint", l.p("#{scope}.public_endpoint", nil)) add_optional(options, "secret", l.p("#{scope}.secret", nil)) + add_optional(options, "signed_url_format", l.p("#{scope}.signed_url_format", nil)) add_optional(options, "retry_attempts", l.p("#{scope}.retry_attempts", nil)) # TLS nested object with a Cert inside ca_cert=l.p("#{scope}.ca_cert",nil) - unless ca_cert.empty? - options["tls"]={"cert"=>ca_cert} + unless ca_cert.nil? || ca_cert.empty? + options["tls"]={"cert"=>{"ca"=>ca_cert}} end end -%> -<%= JSON.pretty_generate(options) %> \ No newline at end of file +<%= JSON.pretty_generate(options) %> diff --git a/jobs/blobstore_benchmark/templates/storage_cli_config_packages.json.erb b/jobs/blobstore_benchmark/templates/storage_cli_config_packages.json.erb index 62b6703cfa..65ae733f99 100644 --- a/jobs/blobstore_benchmark/templates/storage_cli_config_packages.json.erb +++ b/jobs/blobstore_benchmark/templates/storage_cli_config_packages.json.erb @@ -91,21 +91,30 @@ if provider == "aliyun" || provider == "alioss" options["bucket_name"] = l.p("#{scope}.aliyun_oss_bucket") end -# WebDAV/dav support intentionally excluded (not fully implemented) +# Support both native storage-cli types (dav) AND legacy fog names (webdav) +# Legacy fog name support to be REMOVED May 2026 if provider == "webdav" || provider == "dav" - options["provider"] = provider + options["provider"] = "dav" options["user"] = l.p("#{scope}.username") options["password"] = l.p("#{scope}.password") - options["endpoint"] = l.p("#{scope}.public_endpoint") + + # Resource-specific directory for compatibility with fog/webdav + resource_dir = l.p("cc.packages.app_package_directory_key", "cc-packages") + + private_base = l.p("#{scope}.private_endpoint") + options["endpoint"] = "#{private_base}/admin/#{resource_dir}" + + add_optional(options, "public_endpoint", l.p("#{scope}.public_endpoint", nil)) add_optional(options, "secret", l.p("#{scope}.secret", nil)) + add_optional(options, "signed_url_format", l.p("#{scope}.signed_url_format", nil)) add_optional(options, "retry_attempts", l.p("#{scope}.retry_attempts", nil)) # TLS nested object with a Cert inside ca_cert=l.p("#{scope}.ca_cert",nil) - unless ca_cert.empty? - options["tls"]={"cert"=>ca_cert} + unless ca_cert.nil? || ca_cert.empty? + options["tls"]={"cert"=>{"ca"=>ca_cert}} end end -%> -<%= JSON.pretty_generate(options) %> \ No newline at end of file +<%= JSON.pretty_generate(options) %> diff --git a/jobs/blobstore_benchmark/templates/storage_cli_config_resource_pool.json.erb b/jobs/blobstore_benchmark/templates/storage_cli_config_resource_pool.json.erb index 575efadebb..573cf18262 100644 --- a/jobs/blobstore_benchmark/templates/storage_cli_config_resource_pool.json.erb +++ b/jobs/blobstore_benchmark/templates/storage_cli_config_resource_pool.json.erb @@ -91,21 +91,30 @@ if provider == "aliyun" || provider == "alioss" options["bucket_name"] = l.p("#{scope}.aliyun_oss_bucket") end -# WebDAV/dav support intentionally excluded (not fully implemented) +# Support both native storage-cli types (dav) AND legacy fog names (webdav) +# Legacy fog name support to be REMOVED May 2026 if provider == "webdav" || provider == "dav" - options["provider"] = provider + options["provider"] = "dav" options["user"] = l.p("#{scope}.username") options["password"] = l.p("#{scope}.password") - options["endpoint"] = l.p("#{scope}.public_endpoint") + + # Resource-specific directory for compatibility with fog/webdav + resource_dir = l.p("cc.resource_pool.resource_directory_key", "cc-resources") + + private_base = l.p("#{scope}.private_endpoint") + options["endpoint"] = "#{private_base}/admin/#{resource_dir}" + + add_optional(options, "public_endpoint", l.p("#{scope}.public_endpoint", nil)) add_optional(options, "secret", l.p("#{scope}.secret", nil)) + add_optional(options, "signed_url_format", l.p("#{scope}.signed_url_format", nil)) add_optional(options, "retry_attempts", l.p("#{scope}.retry_attempts", nil)) # TLS nested object with a Cert inside ca_cert=l.p("#{scope}.ca_cert",nil) - unless ca_cert.empty? - options["tls"]={"cert"=>ca_cert} + unless ca_cert.nil? || ca_cert.empty? + options["tls"]={"cert"=>{"ca"=>ca_cert}} end end -%> -<%= JSON.pretty_generate(options) %> \ No newline at end of file +<%= JSON.pretty_generate(options) %> diff --git a/jobs/cc_deployment_updater/templates/storage_cli_config_buildpacks.json.erb b/jobs/cc_deployment_updater/templates/storage_cli_config_buildpacks.json.erb index f5454cf125..d3361af8e9 100644 --- a/jobs/cc_deployment_updater/templates/storage_cli_config_buildpacks.json.erb +++ b/jobs/cc_deployment_updater/templates/storage_cli_config_buildpacks.json.erb @@ -90,22 +90,31 @@ if provider == "aliyun" || provider == "alioss" options["endpoint"] = l.p("#{scope}.aliyun_oss_endpoint") options["bucket_name"] = l.p("#{scope}.aliyun_oss_bucket") end - -# WebDAV/dav support intentionally excluded (not fully implemented) + +# Support both native storage-cli types (dav) AND legacy fog names (webdav) +# Legacy fog name support to be REMOVED May 2026 if provider == "webdav" || provider == "dav" - options["provider"] = provider + options["provider"] = "dav" options["user"] = l.p("#{scope}.username") options["password"] = l.p("#{scope}.password") - options["endpoint"] = l.p("#{scope}.public_endpoint") + + # Resource-specific directory for compatibility with fog/webdav + resource_dir = l.p("cc.buildpacks.buildpack_directory_key", "cc-buildpacks") + + private_base = l.p("#{scope}.private_endpoint") + options["endpoint"] = "#{private_base}/admin/#{resource_dir}" + + add_optional(options, "public_endpoint", l.p("#{scope}.public_endpoint", nil)) add_optional(options, "secret", l.p("#{scope}.secret", nil)) + add_optional(options, "signed_url_format", l.p("#{scope}.signed_url_format", nil)) add_optional(options, "retry_attempts", l.p("#{scope}.retry_attempts", nil)) # TLS nested object with a Cert inside ca_cert=l.p("#{scope}.ca_cert",nil) - unless ca_cert.empty? - options["tls"]={"cert"=>ca_cert} + unless ca_cert.nil? || ca_cert.empty? + options["tls"]={"cert"=>{"ca"=>ca_cert}} end end -%> -<%= JSON.pretty_generate(options) %> \ No newline at end of file +<%= JSON.pretty_generate(options) %> diff --git a/jobs/cc_deployment_updater/templates/storage_cli_config_droplets.json.erb b/jobs/cc_deployment_updater/templates/storage_cli_config_droplets.json.erb index 050c260f39..26a5a84996 100644 --- a/jobs/cc_deployment_updater/templates/storage_cli_config_droplets.json.erb +++ b/jobs/cc_deployment_updater/templates/storage_cli_config_droplets.json.erb @@ -91,21 +91,30 @@ if provider == "aliyun" || provider == "alioss" options["bucket_name"] = l.p("#{scope}.aliyun_oss_bucket") end -# WebDAV/dav support intentionally excluded (not fully implemented) +# Support both native storage-cli types (dav) AND legacy fog names (webdav) +# Legacy fog name support to be REMOVED May 2026 if provider == "webdav" || provider == "dav" - options["provider"] = provider + options["provider"] = "dav" options["user"] = l.p("#{scope}.username") options["password"] = l.p("#{scope}.password") - options["endpoint"] = l.p("#{scope}.public_endpoint") + + # Resource-specific directory for compatibility with fog/webdav + resource_dir = l.p("cc.droplets.droplet_directory_key", "cc-droplets") + + private_base = l.p("#{scope}.private_endpoint") + options["endpoint"] = "#{private_base}/admin/#{resource_dir}" + + add_optional(options, "public_endpoint", l.p("#{scope}.public_endpoint", nil)) add_optional(options, "secret", l.p("#{scope}.secret", nil)) + add_optional(options, "signed_url_format", l.p("#{scope}.signed_url_format", nil)) add_optional(options, "retry_attempts", l.p("#{scope}.retry_attempts", nil)) # TLS nested object with a Cert inside ca_cert=l.p("#{scope}.ca_cert",nil) - unless ca_cert.empty? - options["tls"]={"cert"=>ca_cert} + unless ca_cert.nil? || ca_cert.empty? + options["tls"]={"cert"=>{"ca"=>ca_cert}} end end -%> -<%= JSON.pretty_generate(options) %> \ No newline at end of file +<%= JSON.pretty_generate(options) %> diff --git a/jobs/cc_deployment_updater/templates/storage_cli_config_packages.json.erb b/jobs/cc_deployment_updater/templates/storage_cli_config_packages.json.erb index 62b6703cfa..65ae733f99 100644 --- a/jobs/cc_deployment_updater/templates/storage_cli_config_packages.json.erb +++ b/jobs/cc_deployment_updater/templates/storage_cli_config_packages.json.erb @@ -91,21 +91,30 @@ if provider == "aliyun" || provider == "alioss" options["bucket_name"] = l.p("#{scope}.aliyun_oss_bucket") end -# WebDAV/dav support intentionally excluded (not fully implemented) +# Support both native storage-cli types (dav) AND legacy fog names (webdav) +# Legacy fog name support to be REMOVED May 2026 if provider == "webdav" || provider == "dav" - options["provider"] = provider + options["provider"] = "dav" options["user"] = l.p("#{scope}.username") options["password"] = l.p("#{scope}.password") - options["endpoint"] = l.p("#{scope}.public_endpoint") + + # Resource-specific directory for compatibility with fog/webdav + resource_dir = l.p("cc.packages.app_package_directory_key", "cc-packages") + + private_base = l.p("#{scope}.private_endpoint") + options["endpoint"] = "#{private_base}/admin/#{resource_dir}" + + add_optional(options, "public_endpoint", l.p("#{scope}.public_endpoint", nil)) add_optional(options, "secret", l.p("#{scope}.secret", nil)) + add_optional(options, "signed_url_format", l.p("#{scope}.signed_url_format", nil)) add_optional(options, "retry_attempts", l.p("#{scope}.retry_attempts", nil)) # TLS nested object with a Cert inside ca_cert=l.p("#{scope}.ca_cert",nil) - unless ca_cert.empty? - options["tls"]={"cert"=>ca_cert} + unless ca_cert.nil? || ca_cert.empty? + options["tls"]={"cert"=>{"ca"=>ca_cert}} end end -%> -<%= JSON.pretty_generate(options) %> \ No newline at end of file +<%= JSON.pretty_generate(options) %> diff --git a/jobs/cc_deployment_updater/templates/storage_cli_config_resource_pool.json.erb b/jobs/cc_deployment_updater/templates/storage_cli_config_resource_pool.json.erb index cc3f84adb0..81ede9da33 100644 --- a/jobs/cc_deployment_updater/templates/storage_cli_config_resource_pool.json.erb +++ b/jobs/cc_deployment_updater/templates/storage_cli_config_resource_pool.json.erb @@ -91,21 +91,30 @@ if provider == "aliyun" || provider == "alioss" options["bucket_name"] = l.p("#{scope}.aliyun_oss_bucket") end -# WebDAV/dav support intentionally excluded (not fully implemented) +# Support both native storage-cli types (dav) AND legacy fog names (webdav) +# Legacy fog name support to be REMOVED May 2026 if provider == "webdav" || provider == "dav" - options["provider"] = provider + options["provider"] = "dav" options["user"] = l.p("#{scope}.username") options["password"] = l.p("#{scope}.password") - options["endpoint"] = l.p("#{scope}.public_endpoint") + + # Resource-specific directory for compatibility with fog/webdav + resource_dir = l.p("cc.resource_pool.resource_directory_key", "cc-resources") + + private_base = l.p("#{scope}.private_endpoint") + options["endpoint"] = "#{private_base}/admin/#{resource_dir}" + + add_optional(options, "public_endpoint", l.p("#{scope}.public_endpoint", nil)) add_optional(options, "secret", l.p("#{scope}.secret", nil)) + add_optional(options, "signed_url_format", l.p("#{scope}.signed_url_format", nil)) add_optional(options, "retry_attempts", l.p("#{scope}.retry_attempts", nil)) # TLS nested object with a Cert inside ca_cert=l.p("#{scope}.ca_cert",nil) - unless ca_cert.empty? - options["tls"]={"cert"=>ca_cert} + unless ca_cert.nil? || ca_cert.empty? + options["tls"]={"cert"=>{"ca"=>ca_cert}} end end -%> -<%= JSON.pretty_generate(options) %> \ No newline at end of file +<%= JSON.pretty_generate(options) %> diff --git a/jobs/cloud_controller_clock/templates/storage_cli_config_buildpacks.json.erb b/jobs/cloud_controller_clock/templates/storage_cli_config_buildpacks.json.erb index 3df22410bd..52eb1d04d4 100644 --- a/jobs/cloud_controller_clock/templates/storage_cli_config_buildpacks.json.erb +++ b/jobs/cloud_controller_clock/templates/storage_cli_config_buildpacks.json.erb @@ -89,21 +89,30 @@ if provider == "aliyun" || provider == "alioss" options["bucket_name"] = p("#{scope}.aliyun_oss_bucket") end -# WebDAV/dav support intentionally excluded (not fully implemented) +# Support both native storage-cli types (dav) AND legacy fog names (webdav) +# Legacy fog name support to be REMOVED May 2026 if provider == "webdav" || provider == "dav" - options["provider"] = provider + options["provider"] = "dav" options["user"] = p("#{scope}.username") options["password"] = p("#{scope}.password") - options["endpoint"] = p("#{scope}.public_endpoint") + + # Resource-specific directory for compatibility with fog/webdav + resource_dir = p("cc.buildpacks.buildpack_directory_key", "cc-buildpacks") + + private_base = p("#{scope}.private_endpoint") + options["endpoint"] = "#{private_base}/admin/#{resource_dir}" + + add_optional(options, "public_endpoint", p("#{scope}.public_endpoint", nil)) add_optional(options, "secret", p("#{scope}.secret", nil)) + add_optional(options, "signed_url_format", p("#{scope}.signed_url_format", nil)) add_optional(options, "retry_attempts", p("#{scope}.retry_attempts", nil)) # TLS nested object with a Cert inside ca_cert=p("#{scope}.ca_cert",nil) - unless ca_cert.empty? - options["tls"]={"cert"=>ca_cert} + unless ca_cert.nil? || ca_cert.empty? + options["tls"]={"cert"=>{"ca"=>ca_cert}} end end -%> -<%= JSON.pretty_generate(options) %> \ No newline at end of file +<%= JSON.pretty_generate(options) %> diff --git a/jobs/cloud_controller_clock/templates/storage_cli_config_droplets.json.erb b/jobs/cloud_controller_clock/templates/storage_cli_config_droplets.json.erb index 4616d8afe9..89002191a8 100644 --- a/jobs/cloud_controller_clock/templates/storage_cli_config_droplets.json.erb +++ b/jobs/cloud_controller_clock/templates/storage_cli_config_droplets.json.erb @@ -89,21 +89,30 @@ if provider == "aliyun" || provider == "alioss" options["bucket_name"] = p("#{scope}.aliyun_oss_bucket") end -# WebDAV/dav support intentionally excluded (not fully implemented) +# Support both native storage-cli types (dav) AND legacy fog names (webdav) +# Legacy fog name support to be REMOVED May 2026 if provider == "webdav" || provider == "dav" - options["provider"] = provider + options["provider"] = "dav" options["user"] = p("#{scope}.username") options["password"] = p("#{scope}.password") - options["endpoint"] = p("#{scope}.public_endpoint") + + # Resource-specific directory for compatibility with fog/webdav + resource_dir = p("cc.droplets.droplet_directory_key", "cc-droplets") + + private_base = p("#{scope}.private_endpoint") + options["endpoint"] = "#{private_base}/admin/#{resource_dir}" + + add_optional(options, "public_endpoint", p("#{scope}.public_endpoint", nil)) add_optional(options, "secret", p("#{scope}.secret", nil)) + add_optional(options, "signed_url_format", p("#{scope}.signed_url_format", nil)) add_optional(options, "retry_attempts", p("#{scope}.retry_attempts", nil)) # TLS nested object with a Cert inside ca_cert=p("#{scope}.ca_cert",nil) - unless ca_cert.empty? - options["tls"]={"cert"=>ca_cert} + unless ca_cert.nil? || ca_cert.empty? + options["tls"]={"cert"=>{"ca"=>ca_cert}} end end -%> -<%= JSON.pretty_generate(options) %> \ No newline at end of file +<%= JSON.pretty_generate(options) %> diff --git a/jobs/cloud_controller_clock/templates/storage_cli_config_packages.json.erb b/jobs/cloud_controller_clock/templates/storage_cli_config_packages.json.erb index 9b35f91c78..6e391a6061 100644 --- a/jobs/cloud_controller_clock/templates/storage_cli_config_packages.json.erb +++ b/jobs/cloud_controller_clock/templates/storage_cli_config_packages.json.erb @@ -89,21 +89,30 @@ if provider == "aliyun" || provider == "alioss" options["bucket_name"] = p("#{scope}.aliyun_oss_bucket") end -# WebDAV/dav support intentionally excluded (not fully implemented) +# Support both native storage-cli types (dav) AND legacy fog names (webdav) +# Legacy fog name support to be REMOVED May 2026 if provider == "webdav" || provider == "dav" - options["provider"] = provider + options["provider"] = "dav" options["user"] = p("#{scope}.username") options["password"] = p("#{scope}.password") - options["endpoint"] = p("#{scope}.public_endpoint") + + # Resource-specific directory for compatibility with fog/webdav + resource_dir = p("cc.packages.app_package_directory_key", "cc-packages") + + private_base = p("#{scope}.private_endpoint") + options["endpoint"] = "#{private_base}/admin/#{resource_dir}" + + add_optional(options, "public_endpoint", p("#{scope}.public_endpoint", nil)) add_optional(options, "secret", p("#{scope}.secret", nil)) + add_optional(options, "signed_url_format", p("#{scope}.signed_url_format", nil)) add_optional(options, "retry_attempts", p("#{scope}.retry_attempts", nil)) # TLS nested object with a Cert inside ca_cert=p("#{scope}.ca_cert",nil) - unless ca_cert.empty? - options["tls"]={"cert"=>ca_cert} + unless ca_cert.nil? || ca_cert.empty? + options["tls"]={"cert"=>{"ca"=>ca_cert}} end end -%> -<%= JSON.pretty_generate(options) %> \ No newline at end of file +<%= JSON.pretty_generate(options) %> diff --git a/jobs/cloud_controller_clock/templates/storage_cli_config_resource_pool.json.erb b/jobs/cloud_controller_clock/templates/storage_cli_config_resource_pool.json.erb index 024e57456e..36401322e7 100644 --- a/jobs/cloud_controller_clock/templates/storage_cli_config_resource_pool.json.erb +++ b/jobs/cloud_controller_clock/templates/storage_cli_config_resource_pool.json.erb @@ -89,21 +89,30 @@ if provider == "aliyun" || provider == "alioss" options["bucket_name"] = p("#{scope}.aliyun_oss_bucket") end -# WebDAV/dav support intentionally excluded (not fully implemented) +# Support both native storage-cli types (dav) AND legacy fog names (webdav) +# Legacy fog name support to be REMOVED May 2026 if provider == "webdav" || provider == "dav" - options["provider"] = provider + options["provider"] = "dav" options["user"] = p("#{scope}.username") options["password"] = p("#{scope}.password") - options["endpoint"] = p("#{scope}.public_endpoint") + + # Resource-specific directory for compatibility with fog/webdav + resource_dir = p("cc.resource_pool.resource_directory_key", "cc-resources") + + private_base = p("#{scope}.private_endpoint") + options["endpoint"] = "#{private_base}/admin/#{resource_dir}" + + add_optional(options, "public_endpoint", p("#{scope}.public_endpoint", nil)) add_optional(options, "secret", p("#{scope}.secret", nil)) + add_optional(options, "signed_url_format", p("#{scope}.signed_url_format", nil)) add_optional(options, "retry_attempts", p("#{scope}.retry_attempts", nil)) # TLS nested object with a Cert inside ca_cert=p("#{scope}.ca_cert",nil) - unless ca_cert.empty? - options["tls"]={"cert"=>ca_cert} + unless ca_cert.nil? || ca_cert.empty? + options["tls"]={"cert"=>{"ca"=>ca_cert}} end end -%> -<%= JSON.pretty_generate(options) %> \ No newline at end of file +<%= JSON.pretty_generate(options) %> diff --git a/jobs/cloud_controller_ng/templates/storage_cli_config_buildpacks.json.erb b/jobs/cloud_controller_ng/templates/storage_cli_config_buildpacks.json.erb index 3df22410bd..52eb1d04d4 100644 --- a/jobs/cloud_controller_ng/templates/storage_cli_config_buildpacks.json.erb +++ b/jobs/cloud_controller_ng/templates/storage_cli_config_buildpacks.json.erb @@ -89,21 +89,30 @@ if provider == "aliyun" || provider == "alioss" options["bucket_name"] = p("#{scope}.aliyun_oss_bucket") end -# WebDAV/dav support intentionally excluded (not fully implemented) +# Support both native storage-cli types (dav) AND legacy fog names (webdav) +# Legacy fog name support to be REMOVED May 2026 if provider == "webdav" || provider == "dav" - options["provider"] = provider + options["provider"] = "dav" options["user"] = p("#{scope}.username") options["password"] = p("#{scope}.password") - options["endpoint"] = p("#{scope}.public_endpoint") + + # Resource-specific directory for compatibility with fog/webdav + resource_dir = p("cc.buildpacks.buildpack_directory_key", "cc-buildpacks") + + private_base = p("#{scope}.private_endpoint") + options["endpoint"] = "#{private_base}/admin/#{resource_dir}" + + add_optional(options, "public_endpoint", p("#{scope}.public_endpoint", nil)) add_optional(options, "secret", p("#{scope}.secret", nil)) + add_optional(options, "signed_url_format", p("#{scope}.signed_url_format", nil)) add_optional(options, "retry_attempts", p("#{scope}.retry_attempts", nil)) # TLS nested object with a Cert inside ca_cert=p("#{scope}.ca_cert",nil) - unless ca_cert.empty? - options["tls"]={"cert"=>ca_cert} + unless ca_cert.nil? || ca_cert.empty? + options["tls"]={"cert"=>{"ca"=>ca_cert}} end end -%> -<%= JSON.pretty_generate(options) %> \ No newline at end of file +<%= JSON.pretty_generate(options) %> diff --git a/jobs/cloud_controller_ng/templates/storage_cli_config_droplets.json.erb b/jobs/cloud_controller_ng/templates/storage_cli_config_droplets.json.erb index 45024f6ccd..bde13bdb34 100644 --- a/jobs/cloud_controller_ng/templates/storage_cli_config_droplets.json.erb +++ b/jobs/cloud_controller_ng/templates/storage_cli_config_droplets.json.erb @@ -21,6 +21,11 @@ end scope = "cc.droplets.connection_config" provider = p("cc.droplets.blobstore_provider", nil) + +# Normalize legacy fog provider names to storage-cli names +# Legacy fog name support to be REMOVED May 2026 +provider = "dav" if provider == "webdav" + options = {} # Support both native storage-cli types (azurebs) AND legacy fog names (AzureRM) @@ -89,19 +94,29 @@ if provider == "aliyun" || provider == "alioss" options["bucket_name"] = p("#{scope}.aliyun_oss_bucket") end -# WebDAV/dav support intentionally excluded (not fully implemented) -if provider == "webdav" || provider == "dav" - options["provider"] = provider +if provider == "dav" + options["provider"] = "dav" options["user"] = p("#{scope}.username") options["password"] = p("#{scope}.password") - options["endpoint"] = p("#{scope}.public_endpoint") + + # Resource-specific directory for compatibility with fog/webdav + resource_dir = p("cc.droplets.droplet_directory_key", "cc-droplets") + + # Private endpoint includes /admin/ for Basic Auth operations (PUT, GET, DELETE, COPY, etc) + private_base = p("#{scope}.private_endpoint") + options["endpoint"] = "#{private_base}/admin/#{resource_dir}" + + # Public endpoint (optional) for user-facing signed URLs (API downloads via gorouter) + add_optional(options, "public_endpoint", p("#{scope}.public_endpoint", nil)) + add_optional(options, "secret", p("#{scope}.secret", nil)) + add_optional(options, "signed_url_format", p("#{scope}.signed_url_format", nil)) add_optional(options, "retry_attempts", p("#{scope}.retry_attempts", nil)) # TLS nested object with a Cert inside ca_cert=p("#{scope}.ca_cert",nil) - unless ca_cert.empty? - options["tls"]={"cert"=>ca_cert} + unless ca_cert.nil? || ca_cert.empty? + options["tls"]={"cert"=>{"ca"=>ca_cert}} end end diff --git a/jobs/cloud_controller_ng/templates/storage_cli_config_packages.json.erb b/jobs/cloud_controller_ng/templates/storage_cli_config_packages.json.erb index d345fe3d88..6e391a6061 100644 --- a/jobs/cloud_controller_ng/templates/storage_cli_config_packages.json.erb +++ b/jobs/cloud_controller_ng/templates/storage_cli_config_packages.json.erb @@ -88,22 +88,31 @@ if provider == "aliyun" || provider == "alioss" options["endpoint"] = p("#{scope}.aliyun_oss_endpoint") options["bucket_name"] = p("#{scope}.aliyun_oss_bucket") end - -# WebDAV/dav support intentionally excluded (not fully implemented) + +# Support both native storage-cli types (dav) AND legacy fog names (webdav) +# Legacy fog name support to be REMOVED May 2026 if provider == "webdav" || provider == "dav" - options["provider"] = provider + options["provider"] = "dav" options["user"] = p("#{scope}.username") options["password"] = p("#{scope}.password") - options["endpoint"] = p("#{scope}.public_endpoint") + + # Resource-specific directory for compatibility with fog/webdav + resource_dir = p("cc.packages.app_package_directory_key", "cc-packages") + + private_base = p("#{scope}.private_endpoint") + options["endpoint"] = "#{private_base}/admin/#{resource_dir}" + + add_optional(options, "public_endpoint", p("#{scope}.public_endpoint", nil)) add_optional(options, "secret", p("#{scope}.secret", nil)) + add_optional(options, "signed_url_format", p("#{scope}.signed_url_format", nil)) add_optional(options, "retry_attempts", p("#{scope}.retry_attempts", nil)) # TLS nested object with a Cert inside ca_cert=p("#{scope}.ca_cert",nil) - unless ca_cert.empty? - options["tls"]={"cert"=>ca_cert} + unless ca_cert.nil? || ca_cert.empty? + options["tls"]={"cert"=>{"ca"=>ca_cert}} end end -%> -<%= JSON.pretty_generate(options) %> \ No newline at end of file +<%= JSON.pretty_generate(options) %> diff --git a/jobs/cloud_controller_ng/templates/storage_cli_config_resource_pool.json.erb b/jobs/cloud_controller_ng/templates/storage_cli_config_resource_pool.json.erb index 024e57456e..36401322e7 100644 --- a/jobs/cloud_controller_ng/templates/storage_cli_config_resource_pool.json.erb +++ b/jobs/cloud_controller_ng/templates/storage_cli_config_resource_pool.json.erb @@ -89,21 +89,30 @@ if provider == "aliyun" || provider == "alioss" options["bucket_name"] = p("#{scope}.aliyun_oss_bucket") end -# WebDAV/dav support intentionally excluded (not fully implemented) +# Support both native storage-cli types (dav) AND legacy fog names (webdav) +# Legacy fog name support to be REMOVED May 2026 if provider == "webdav" || provider == "dav" - options["provider"] = provider + options["provider"] = "dav" options["user"] = p("#{scope}.username") options["password"] = p("#{scope}.password") - options["endpoint"] = p("#{scope}.public_endpoint") + + # Resource-specific directory for compatibility with fog/webdav + resource_dir = p("cc.resource_pool.resource_directory_key", "cc-resources") + + private_base = p("#{scope}.private_endpoint") + options["endpoint"] = "#{private_base}/admin/#{resource_dir}" + + add_optional(options, "public_endpoint", p("#{scope}.public_endpoint", nil)) add_optional(options, "secret", p("#{scope}.secret", nil)) + add_optional(options, "signed_url_format", p("#{scope}.signed_url_format", nil)) add_optional(options, "retry_attempts", p("#{scope}.retry_attempts", nil)) # TLS nested object with a Cert inside ca_cert=p("#{scope}.ca_cert",nil) - unless ca_cert.empty? - options["tls"]={"cert"=>ca_cert} + unless ca_cert.nil? || ca_cert.empty? + options["tls"]={"cert"=>{"ca"=>ca_cert}} end end -%> -<%= JSON.pretty_generate(options) %> \ No newline at end of file +<%= JSON.pretty_generate(options) %> diff --git a/jobs/cloud_controller_worker/templates/storage_cli_config_buildpacks.json.erb b/jobs/cloud_controller_worker/templates/storage_cli_config_buildpacks.json.erb index 3df22410bd..52eb1d04d4 100644 --- a/jobs/cloud_controller_worker/templates/storage_cli_config_buildpacks.json.erb +++ b/jobs/cloud_controller_worker/templates/storage_cli_config_buildpacks.json.erb @@ -89,21 +89,30 @@ if provider == "aliyun" || provider == "alioss" options["bucket_name"] = p("#{scope}.aliyun_oss_bucket") end -# WebDAV/dav support intentionally excluded (not fully implemented) +# Support both native storage-cli types (dav) AND legacy fog names (webdav) +# Legacy fog name support to be REMOVED May 2026 if provider == "webdav" || provider == "dav" - options["provider"] = provider + options["provider"] = "dav" options["user"] = p("#{scope}.username") options["password"] = p("#{scope}.password") - options["endpoint"] = p("#{scope}.public_endpoint") + + # Resource-specific directory for compatibility with fog/webdav + resource_dir = p("cc.buildpacks.buildpack_directory_key", "cc-buildpacks") + + private_base = p("#{scope}.private_endpoint") + options["endpoint"] = "#{private_base}/admin/#{resource_dir}" + + add_optional(options, "public_endpoint", p("#{scope}.public_endpoint", nil)) add_optional(options, "secret", p("#{scope}.secret", nil)) + add_optional(options, "signed_url_format", p("#{scope}.signed_url_format", nil)) add_optional(options, "retry_attempts", p("#{scope}.retry_attempts", nil)) # TLS nested object with a Cert inside ca_cert=p("#{scope}.ca_cert",nil) - unless ca_cert.empty? - options["tls"]={"cert"=>ca_cert} + unless ca_cert.nil? || ca_cert.empty? + options["tls"]={"cert"=>{"ca"=>ca_cert}} end end -%> -<%= JSON.pretty_generate(options) %> \ No newline at end of file +<%= JSON.pretty_generate(options) %> diff --git a/jobs/cloud_controller_worker/templates/storage_cli_config_droplets.json.erb b/jobs/cloud_controller_worker/templates/storage_cli_config_droplets.json.erb index 4616d8afe9..89002191a8 100644 --- a/jobs/cloud_controller_worker/templates/storage_cli_config_droplets.json.erb +++ b/jobs/cloud_controller_worker/templates/storage_cli_config_droplets.json.erb @@ -89,21 +89,30 @@ if provider == "aliyun" || provider == "alioss" options["bucket_name"] = p("#{scope}.aliyun_oss_bucket") end -# WebDAV/dav support intentionally excluded (not fully implemented) +# Support both native storage-cli types (dav) AND legacy fog names (webdav) +# Legacy fog name support to be REMOVED May 2026 if provider == "webdav" || provider == "dav" - options["provider"] = provider + options["provider"] = "dav" options["user"] = p("#{scope}.username") options["password"] = p("#{scope}.password") - options["endpoint"] = p("#{scope}.public_endpoint") + + # Resource-specific directory for compatibility with fog/webdav + resource_dir = p("cc.droplets.droplet_directory_key", "cc-droplets") + + private_base = p("#{scope}.private_endpoint") + options["endpoint"] = "#{private_base}/admin/#{resource_dir}" + + add_optional(options, "public_endpoint", p("#{scope}.public_endpoint", nil)) add_optional(options, "secret", p("#{scope}.secret", nil)) + add_optional(options, "signed_url_format", p("#{scope}.signed_url_format", nil)) add_optional(options, "retry_attempts", p("#{scope}.retry_attempts", nil)) # TLS nested object with a Cert inside ca_cert=p("#{scope}.ca_cert",nil) - unless ca_cert.empty? - options["tls"]={"cert"=>ca_cert} + unless ca_cert.nil? || ca_cert.empty? + options["tls"]={"cert"=>{"ca"=>ca_cert}} end end -%> -<%= JSON.pretty_generate(options) %> \ No newline at end of file +<%= JSON.pretty_generate(options) %> diff --git a/jobs/cloud_controller_worker/templates/storage_cli_config_packages.json.erb b/jobs/cloud_controller_worker/templates/storage_cli_config_packages.json.erb index d345fe3d88..c31a33b6a0 100644 --- a/jobs/cloud_controller_worker/templates/storage_cli_config_packages.json.erb +++ b/jobs/cloud_controller_worker/templates/storage_cli_config_packages.json.erb @@ -89,21 +89,30 @@ if provider == "aliyun" || provider == "alioss" options["bucket_name"] = p("#{scope}.aliyun_oss_bucket") end -# WebDAV/dav support intentionally excluded (not fully implemented) +# Support both native storage-cli types (dav) AND legacy fog names (webdav) +# Legacy fog name support to be REMOVED May 2026 if provider == "webdav" || provider == "dav" - options["provider"] = provider + options["provider"] = "dav" options["user"] = p("#{scope}.username") options["password"] = p("#{scope}.password") - options["endpoint"] = p("#{scope}.public_endpoint") + + # Resource-specific directory for compatibility with fog/webdav + resource_dir = p("cc.packages.app_package_directory_key", "cc-packages") + + private_base = p("#{scope}.private_endpoint") + options["endpoint"] = "#{private_base}/admin/#{resource_dir}" + + add_optional(options, "public_endpoint", p("#{scope}.public_endpoint", nil)) add_optional(options, "secret", p("#{scope}.secret", nil)) + add_optional(options, "signed_url_format", p("#{scope}.signed_url_format", nil)) add_optional(options, "retry_attempts", p("#{scope}.retry_attempts", nil)) # TLS nested object with a Cert inside ca_cert=p("#{scope}.ca_cert",nil) - unless ca_cert.empty? - options["tls"]={"cert"=>ca_cert} + unless ca_cert.nil? || ca_cert.empty? + options["tls"]={"cert"=>{"ca"=>ca_cert}} end end -%> -<%= JSON.pretty_generate(options) %> \ No newline at end of file +<%= JSON.pretty_generate(options) %> diff --git a/jobs/cloud_controller_worker/templates/storage_cli_config_resource_pool.json.erb b/jobs/cloud_controller_worker/templates/storage_cli_config_resource_pool.json.erb index 024e57456e..b3e65773a5 100644 --- a/jobs/cloud_controller_worker/templates/storage_cli_config_resource_pool.json.erb +++ b/jobs/cloud_controller_worker/templates/storage_cli_config_resource_pool.json.erb @@ -88,22 +88,31 @@ if provider == "aliyun" || provider == "alioss" options["endpoint"] = p("#{scope}.aliyun_oss_endpoint") options["bucket_name"] = p("#{scope}.aliyun_oss_bucket") end - -# WebDAV/dav support intentionally excluded (not fully implemented) + +# Support both native storage-cli types (dav) AND legacy fog names (webdav) +# Legacy fog name support to be REMOVED May 2026 if provider == "webdav" || provider == "dav" - options["provider"] = provider + options["provider"] = "dav" options["user"] = p("#{scope}.username") options["password"] = p("#{scope}.password") - options["endpoint"] = p("#{scope}.public_endpoint") + + # Resource-specific directory for compatibility with fog/webdav + resource_dir = p("cc.resource_pool.resource_directory_key", "cc-resources") + + private_base = p("#{scope}.private_endpoint") + options["endpoint"] = "#{private_base}/admin/#{resource_dir}" + + add_optional(options, "public_endpoint", p("#{scope}.public_endpoint", nil)) add_optional(options, "secret", p("#{scope}.secret", nil)) + add_optional(options, "signed_url_format", p("#{scope}.signed_url_format", nil)) add_optional(options, "retry_attempts", p("#{scope}.retry_attempts", nil)) # TLS nested object with a Cert inside ca_cert=p("#{scope}.ca_cert",nil) - unless ca_cert.empty? - options["tls"]={"cert"=>ca_cert} + unless ca_cert.nil? || ca_cert.empty? + options["tls"]={"cert"=>{"ca"=>ca_cert}} end end -%> -<%= JSON.pretty_generate(options) %> \ No newline at end of file +<%= JSON.pretty_generate(options) %> diff --git a/spec/cc_deployment_updater/storage_cli_config_jsons_spec.rb b/spec/cc_deployment_updater/storage_cli_config_jsons_spec.rb index 24bec8ab58..8ba6c47ce2 100644 --- a/spec/cc_deployment_updater/storage_cli_config_jsons_spec.rb +++ b/spec/cc_deployment_updater/storage_cli_config_jsons_spec.rb @@ -4,18 +4,20 @@ require 'yaml' require 'bosh/template/test' -TEMPLATES = { - droplets: ['config/storage_cli_config_droplets.json', %w[cc droplets connection_config]], - buildpacks: ['config/storage_cli_config_buildpacks.json', %w[cc buildpacks connection_config]], - packages: ['config/storage_cli_config_packages.json', %w[cc packages connection_config]], - resource_pool: ['config/storage_cli_config_resource_pool.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__), '../..') } + def self.storage_cli_templates + [ + ['config/storage_cli_config_droplets.json', %w[cc droplets connection_config]], + ['config/storage_cli_config_buildpacks.json', %w[cc buildpacks connection_config]], + ['config/storage_cli_config_packages.json', %w[cc packages connection_config]], + ['config/storage_cli_config_resource_pool.json', %w[cc resource_pool connection_config]] + ] + end + + let(:release_path) { File.expand_path('../..', __dir__) } let(:release) { ReleaseDir.new(release_path) } let(:job) { release.job('cc_deployment_updater') } @@ -47,7 +49,7 @@ def props_for_provider(provider) let(:links) { [cc_link] } let(:props) { {} } - TEMPLATES.each_value do |(template_path, _keypath)| + storage_cli_templates.each do |(template_path, _keypath)| describe template_path do let(:template) { job.template(template_path) } @@ -70,7 +72,7 @@ def props_for_provider(provider) let(:links) { [cc_link] } let(:props) { {} } - TEMPLATES.each_value do |(template_path, keypath)| + storage_cli_templates.each do |(template_path, keypath)| describe template_path do let(:template) { job.template(template_path) } @@ -118,7 +120,7 @@ def props_for_provider(provider) let(:links) { [cc_link] } let(:props) { {} } - TEMPLATES.each_value do |(template_path, keypath)| + storage_cli_templates.each do |(template_path, keypath)| describe template_path do let(:template) { job.template(template_path) } @@ -230,7 +232,7 @@ def props_for_provider(provider) let(:links) { [cc_link] } let(:props) { {} } - TEMPLATES.each_value do |(template_path, keypath)| + storage_cli_templates.each do |(template_path, keypath)| describe template_path do let(:template) { job.template(template_path) } @@ -284,7 +286,7 @@ def props_for_provider(provider) let(:links) { [cc_link] } let(:props) { {} } - TEMPLATES.each_value do |(template_path, keypath)| + storage_cli_templates.each do |(template_path, keypath)| describe template_path do let(:template) { job.template(template_path) } @@ -320,49 +322,98 @@ def props_for_provider(provider) let(:links) { [cc_link] } let(:props) { {} } - TEMPLATES.each_value do |(template_path, keypath)| + # Helper to determine expected directory key based on template path + def expected_directory_key(template_path) + case template_path + when /droplets/ then 'cc-droplets' + when /packages/ then 'cc-packages' + when /buildpacks/ then 'cc-buildpacks' + when /resource_pool/ then 'cc-resources' + end + end + + storage_cli_templates.each do |(template_path, keypath)| describe template_path do let(:template) { job.template(template_path) } + let(:directory_key) { expected_directory_key(template_path) } it 'maps required properties into the rendered config' do set(link_props, keypath, { - 'provider' => 'webdav', + 'provider' => 'dav', + 'username' => 'user', + 'password' => 'secret', + 'private_endpoint' => 'https://webdav.internal', + 'ca_cert' => 'some_cert' + }) + json = YAML.safe_load(template.render(props, consumes: links)) + expect(json).to include( + 'provider' => 'dav', + 'user' => 'user', + 'password' => 'secret', + 'endpoint' => "https://webdav.internal/admin/#{directory_key}", + 'tls' => { 'cert' => { 'ca' => 'some_cert' } } + ) + expect(json).not_to have_key('public_endpoint') + end + + it 'includes public_endpoint when provided' do + set(link_props, keypath, { + 'provider' => 'dav', 'username' => 'user', 'password' => 'secret', - 'public_endpoint' => 'webdav.com', + 'private_endpoint' => 'https://webdav.internal', + 'public_endpoint' => 'https://webdav.example.com', 'ca_cert' => 'some_cert' }) json = YAML.safe_load(template.render(props, consumes: links)) expect(json).to include( - 'provider' => 'webdav', + 'provider' => 'dav', 'user' => 'user', 'password' => 'secret', - 'endpoint' => 'webdav.com', - 'tls' => { 'cert' => 'some_cert' } + 'endpoint' => "https://webdav.internal/admin/#{directory_key}", + 'public_endpoint' => 'https://webdav.example.com', + 'tls' => { 'cert' => { 'ca' => 'some_cert' } } ) end it 'includes optional properties when provided' do set(link_props, keypath, { - 'provider' => 'webdav', + 'provider' => 'dav', 'username' => 'user', 'password' => 'secret', - 'public_endpoint' => 'webdav.com', + 'private_endpoint' => 'https://webdav.internal', + 'public_endpoint' => 'https://webdav.example.com', 'ca_cert' => 'some_cert', - 'secret' => 'secret', + 'secret' => 'my-secret', + 'signed_url_format' => 'external-nginx-secure-link-signer', 'retry_attempts' => '4' }) json = YAML.safe_load(template.render(props, consumes: links)) expect(json).to include( - 'provider' => 'webdav', + 'provider' => 'dav', 'user' => 'user', 'password' => 'secret', - 'endpoint' => 'webdav.com', - 'tls' => { 'cert' => 'some_cert' }, - 'secret' => 'secret', + 'endpoint' => "https://webdav.internal/admin/#{directory_key}", + 'public_endpoint' => 'https://webdav.example.com', + 'tls' => { 'cert' => { 'ca' => 'some_cert' } }, + 'secret' => 'my-secret', + 'signed_url_format' => 'external-nginx-secure-link-signer', 'retry_attempts' => '4' ) end + + it 'omits public_endpoint when empty' do + set(link_props, keypath, { + 'provider' => 'dav', + 'username' => 'user', + 'password' => 'secret', + 'private_endpoint' => 'https://webdav.internal', + 'public_endpoint' => '', + 'ca_cert' => 'some_cert' + }) + json = YAML.safe_load(template.render(props, consumes: links)) + expect(json).not_to have_key('public_endpoint') + end end end end diff --git a/spec/cloud_controller_clock/storage_cli_config_jsons_spec.rb b/spec/cloud_controller_clock/storage_cli_config_jsons_spec.rb index ff1fbc52a1..a8b71761bb 100644 --- a/spec/cloud_controller_clock/storage_cli_config_jsons_spec.rb +++ b/spec/cloud_controller_clock/storage_cli_config_jsons_spec.rb @@ -4,18 +4,20 @@ require 'yaml' require 'bosh/template/test' -TEMPLATES = { - droplets: ['config/storage_cli_config_droplets.json', %w[cc droplets connection_config]], - buildpacks: ['config/storage_cli_config_buildpacks.json', %w[cc buildpacks connection_config]], - packages: ['config/storage_cli_config_packages.json', %w[cc packages connection_config]], - resource_pool: ['config/storage_cli_config_resource_pool.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__), '../..') } + def self.storage_cli_templates + [ + ['config/storage_cli_config_droplets.json', %w[cc droplets connection_config]], + ['config/storage_cli_config_buildpacks.json', %w[cc buildpacks connection_config]], + ['config/storage_cli_config_packages.json', %w[cc packages connection_config]], + ['config/storage_cli_config_resource_pool.json', %w[cc resource_pool connection_config]] + ] + end + + let(:release_path) { File.expand_path('../..', __dir__) } let(:release) { ReleaseDir.new(release_path) } let(:job) { release.job('cloud_controller_clock') } let(:links) { {} } @@ -40,7 +42,7 @@ def props_for_provider(provider) describe 'unsupported provider' do let(:props) { props_for_provider('Unsupported') } - TEMPLATES.each_value do |(template_path, _keypath)| + storage_cli_templates.each do |(template_path, _keypath)| describe template_path do let(:template) { job.template(template_path) } @@ -55,7 +57,7 @@ def props_for_provider(provider) describe 'when provider is AzureRM' do let(:props) { props_for_provider('AzureRM') } - TEMPLATES.each_value do |(template_path, keypath)| + storage_cli_templates.each do |(template_path, keypath)| describe template_path do let(:template) { job.template(template_path) } @@ -95,7 +97,7 @@ def props_for_provider(provider) describe 'when provider is AWS' do let(:props) { props_for_provider('AWS') } - TEMPLATES.each_value do |(template_path, keypath)| + storage_cli_templates.each do |(template_path, keypath)| describe template_path do let(:template) { job.template(template_path) } @@ -199,7 +201,7 @@ def props_for_provider(provider) describe 'when provider is Google' do let(:props) { props_for_provider('Google') } - TEMPLATES.each_value do |(template_path, keypath)| + storage_cli_templates.each do |(template_path, keypath)| describe template_path do let(:template) { job.template(template_path) } @@ -245,7 +247,7 @@ def props_for_provider(provider) describe 'when provider is aliyun' do let(:props) { props_for_provider('aliyun') } - TEMPLATES.each_value do |(template_path, keypath)| + storage_cli_templates.each do |(template_path, keypath)| describe template_path do let(:template) { job.template(template_path) } @@ -273,25 +275,57 @@ def props_for_provider(provider) describe 'when provider is webdav' do let(:props) { props_for_provider('webdav') } - TEMPLATES.each_value do |(template_path, keypath)| + # Helper to determine expected directory key based on template path + def expected_directory_key(template_path) + case template_path + when /droplets/ then 'cc-droplets' + when /packages/ then 'cc-packages' + when /buildpacks/ then 'cc-buildpacks' + when /resource_pool/ then 'cc-resources' + end + end + + storage_cli_templates.each do |(template_path, keypath)| describe template_path do let(:template) { job.template(template_path) } + let(:directory_key) { expected_directory_key(template_path) } it 'maps required properties into the rendered config' do set(props, keypath, { 'provider' => 'webdav', 'username' => 'user', 'password' => 'secret', - 'public_endpoint' => 'webdav.com', + 'private_endpoint' => 'https://webdav.internal', + 'ca_cert' => 'some_cert' + }) + json = YAML.safe_load(template.render(props, consumes: links)) + expect(json).to include( + 'provider' => 'dav', + 'user' => 'user', + 'password' => 'secret', + 'endpoint' => "https://webdav.internal/admin/#{directory_key}", + 'tls' => { 'cert' => { 'ca' => 'some_cert' } } + ) + expect(json).not_to have_key('public_endpoint') + end + + it 'includes public_endpoint when provided' do + set(props, keypath, { + 'provider' => 'webdav', + 'username' => 'user', + 'password' => 'secret', + 'private_endpoint' => 'https://webdav.internal', + 'public_endpoint' => 'https://webdav.example.com', 'ca_cert' => 'some_cert' }) json = YAML.safe_load(template.render(props, consumes: links)) expect(json).to include( - 'provider' => 'webdav', + 'provider' => 'dav', 'user' => 'user', 'password' => 'secret', - 'endpoint' => 'webdav.com', - 'tls' => { 'cert' => 'some_cert' } + 'endpoint' => "https://webdav.internal/admin/#{directory_key}", + 'public_endpoint' => 'https://webdav.example.com', + 'tls' => { 'cert' => { 'ca' => 'some_cert' } } ) end @@ -300,22 +334,39 @@ def props_for_provider(provider) 'provider' => 'webdav', 'username' => 'user', 'password' => 'secret', - 'public_endpoint' => 'webdav.com', + 'private_endpoint' => 'https://webdav.internal', + 'public_endpoint' => 'https://webdav.example.com', 'ca_cert' => 'some_cert', - 'secret' => 'secret', + 'secret' => 'my-secret', + 'signed_url_format' => 'external-nginx-secure-link-signer', 'retry_attempts' => '4' }) json = YAML.safe_load(template.render(props, consumes: links)) expect(json).to include( - 'provider' => 'webdav', + 'provider' => 'dav', 'user' => 'user', 'password' => 'secret', - 'endpoint' => 'webdav.com', - 'tls' => { 'cert' => 'some_cert' }, - 'secret' => 'secret', + 'endpoint' => "https://webdav.internal/admin/#{directory_key}", + 'public_endpoint' => 'https://webdav.example.com', + 'tls' => { 'cert' => { 'ca' => 'some_cert' } }, + 'secret' => 'my-secret', + 'signed_url_format' => 'external-nginx-secure-link-signer', 'retry_attempts' => '4' ) end + + it 'omits public_endpoint when empty' do + set(props, keypath, { + 'provider' => 'webdav', + 'username' => 'user', + 'password' => 'secret', + 'private_endpoint' => 'https://webdav.internal', + 'public_endpoint' => '', + 'ca_cert' => 'some_cert' + }) + json = YAML.safe_load(template.render(props, consumes: links)) + expect(json).not_to have_key('public_endpoint') + 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 index a44653048c..34170a6878 100644 --- a/spec/cloud_controller_ng/storage_cli_config_jsons_spec.rb +++ b/spec/cloud_controller_ng/storage_cli_config_jsons_spec.rb @@ -1,22 +1,23 @@ # frozen_string_literal: true require 'rspec' -require 'yaml' # frozen_string_literal: true - +require 'yaml' require 'bosh/template/test' -TEMPLATES = { - droplets: ['config/storage_cli_config_droplets.json', %w[cc droplets connection_config]], - buildpacks: ['config/storage_cli_config_buildpacks.json', %w[cc buildpacks connection_config]], - packages: ['config/storage_cli_config_packages.json', %w[cc packages connection_config]], - resource_pool: ['config/storage_cli_config_resource_pool.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__), '../..') } + def self.storage_cli_templates + [ + ['config/storage_cli_config_droplets.json', %w[cc droplets connection_config]], + ['config/storage_cli_config_buildpacks.json', %w[cc buildpacks connection_config]], + ['config/storage_cli_config_packages.json', %w[cc packages connection_config]], + ['config/storage_cli_config_resource_pool.json', %w[cc resource_pool connection_config]] + ] + end + + let(:release_path) { File.expand_path('../..', __dir__) } let(:release) { ReleaseDir.new(release_path) } let(:job) { release.job('cloud_controller_ng') } let(:links) { {} } @@ -41,7 +42,7 @@ def props_for_provider(provider) describe 'unsupported provider' do let(:props) { props_for_provider('Unsupported') } - TEMPLATES.each_value do |(template_path, _keypath)| + storage_cli_templates.each do |(template_path, _keypath)| describe template_path do let(:template) { job.template(template_path) } @@ -56,7 +57,7 @@ def props_for_provider(provider) describe 'when provider is AzureRM' do let(:props) { props_for_provider('AzureRM') } - TEMPLATES.each_value do |(template_path, keypath)| + storage_cli_templates.each do |(template_path, keypath)| describe template_path do let(:template) { job.template(template_path) } @@ -96,7 +97,7 @@ def props_for_provider(provider) describe 'when provider is AWS' do let(:props) { props_for_provider('AWS') } - TEMPLATES.each_value do |(template_path, keypath)| + storage_cli_templates.each do |(template_path, keypath)| describe template_path do let(:template) { job.template(template_path) } @@ -200,7 +201,7 @@ def props_for_provider(provider) describe 'when provider is Google' do let(:props) { props_for_provider('Google') } - TEMPLATES.each_value do |(template_path, keypath)| + storage_cli_templates.each do |(template_path, keypath)| describe template_path do let(:template) { job.template(template_path) } @@ -246,7 +247,7 @@ def props_for_provider(provider) describe 'when provider is aliyun' do let(:props) { props_for_provider('aliyun') } - TEMPLATES.each_value do |(template_path, keypath)| + storage_cli_templates.each do |(template_path, keypath)| describe template_path do let(:template) { job.template(template_path) } @@ -274,25 +275,57 @@ def props_for_provider(provider) describe 'when provider is webdav' do let(:props) { props_for_provider('webdav') } - TEMPLATES.each_value do |(template_path, keypath)| + # Helper to determine expected directory key based on template path + def expected_directory_key(template_path) + case template_path + when /droplets/ then 'cc-droplets' + when /packages/ then 'cc-packages' + when /buildpacks/ then 'cc-buildpacks' + when /resource_pool/ then 'cc-resources' + end + end + + storage_cli_templates.each do |(template_path, keypath)| describe template_path do let(:template) { job.template(template_path) } + let(:directory_key) { expected_directory_key(template_path) } it 'maps required properties into the rendered config' do set(props, keypath, { 'provider' => 'webdav', 'username' => 'user', 'password' => 'secret', - 'public_endpoint' => 'webdav.com', + 'private_endpoint' => 'https://webdav.internal', 'ca_cert' => 'some_cert' }) json = YAML.safe_load(template.render(props, consumes: links)) expect(json).to include( - 'provider' => 'webdav', + 'provider' => 'dav', 'user' => 'user', 'password' => 'secret', - 'endpoint' => 'webdav.com', - 'tls' => { 'cert' => 'some_cert' } + 'endpoint' => "https://webdav.internal/admin/#{directory_key}", + 'tls' => { 'cert' => { 'ca' => 'some_cert' } } + ) + expect(json).not_to have_key('public_endpoint') + end + + it 'includes public_endpoint when provided' do + set(props, keypath, { + 'provider' => 'webdav', + 'username' => 'user', + 'password' => 'secret', + 'private_endpoint' => 'https://webdav.internal', + 'public_endpoint' => 'https://webdav.example.com', + 'ca_cert' => 'some_cert' + }) + json = YAML.safe_load(template.render(props, consumes: links)) + expect(json).to include( + 'provider' => 'dav', + 'user' => 'user', + 'password' => 'secret', + 'endpoint' => "https://webdav.internal/admin/#{directory_key}", + 'public_endpoint' => 'https://webdav.example.com', + 'tls' => { 'cert' => { 'ca' => 'some_cert' } } ) end @@ -301,22 +334,39 @@ def props_for_provider(provider) 'provider' => 'webdav', 'username' => 'user', 'password' => 'secret', - 'public_endpoint' => 'webdav.com', + 'private_endpoint' => 'https://webdav.internal', + 'public_endpoint' => 'https://webdav.example.com', 'ca_cert' => 'some_cert', - 'secret' => 'secret', + 'secret' => 'my-secret', + 'signed_url_format' => 'external-nginx-secure-link-signer', 'retry_attempts' => '4' }) json = YAML.safe_load(template.render(props, consumes: links)) expect(json).to include( - 'provider' => 'webdav', + 'provider' => 'dav', 'user' => 'user', 'password' => 'secret', - 'endpoint' => 'webdav.com', - 'tls' => { 'cert' => 'some_cert' }, - 'secret' => 'secret', + 'endpoint' => "https://webdav.internal/admin/#{directory_key}", + 'public_endpoint' => 'https://webdav.example.com', + 'tls' => { 'cert' => { 'ca' => 'some_cert' } }, + 'secret' => 'my-secret', + 'signed_url_format' => 'external-nginx-secure-link-signer', 'retry_attempts' => '4' ) end + + it 'omits public_endpoint when empty' do + set(props, keypath, { + 'provider' => 'webdav', + 'username' => 'user', + 'password' => 'secret', + 'private_endpoint' => 'https://webdav.internal', + 'public_endpoint' => '', + 'ca_cert' => 'some_cert' + }) + json = YAML.safe_load(template.render(props, consumes: links)) + expect(json).not_to have_key('public_endpoint') + end end end end diff --git a/spec/cloud_controller_worker/storage_cli_config_jsons_spec.rb b/spec/cloud_controller_worker/storage_cli_config_jsons_spec.rb index 8d08c5f950..41f36ee898 100644 --- a/spec/cloud_controller_worker/storage_cli_config_jsons_spec.rb +++ b/spec/cloud_controller_worker/storage_cli_config_jsons_spec.rb @@ -4,18 +4,20 @@ require 'yaml' require 'bosh/template/test' -TEMPLATES = { - droplets: ['config/storage_cli_config_droplets.json', %w[cc droplets connection_config]], - buildpacks: ['config/storage_cli_config_buildpacks.json', %w[cc buildpacks connection_config]], - packages: ['config/storage_cli_config_packages.json', %w[cc packages connection_config]], - resource_pool: ['config/storage_cli_config_resource_pool.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__), '../..') } + def self.storage_cli_templates + [ + ['config/storage_cli_config_droplets.json', %w[cc droplets connection_config]], + ['config/storage_cli_config_buildpacks.json', %w[cc buildpacks connection_config]], + ['config/storage_cli_config_packages.json', %w[cc packages connection_config]], + ['config/storage_cli_config_resource_pool.json', %w[cc resource_pool connection_config]] + ] + end + + let(:release_path) { File.expand_path('../..', __dir__) } let(:release) { ReleaseDir.new(release_path) } let(:job) { release.job('cloud_controller_worker') } let(:links) { {} } @@ -40,7 +42,7 @@ def props_for_provider(provider) describe 'unsupported provider' do let(:props) { props_for_provider('Unsupported') } - TEMPLATES.each_value do |(template_path, _keypath)| + storage_cli_templates.each do |(template_path, _keypath)| describe template_path do let(:template) { job.template(template_path) } @@ -55,7 +57,7 @@ def props_for_provider(provider) describe 'when provider is AzureRM' do let(:props) { props_for_provider('AzureRM') } - TEMPLATES.each_value do |(template_path, keypath)| + storage_cli_templates.each do |(template_path, keypath)| describe template_path do let(:template) { job.template(template_path) } @@ -95,7 +97,7 @@ def props_for_provider(provider) describe 'when provider is AWS' do let(:props) { props_for_provider('AWS') } - TEMPLATES.each_value do |(template_path, keypath)| + storage_cli_templates.each do |(template_path, keypath)| describe template_path do let(:template) { job.template(template_path) } @@ -199,7 +201,7 @@ def props_for_provider(provider) describe 'when provider is Google' do let(:props) { props_for_provider('Google') } - TEMPLATES.each_value do |(template_path, keypath)| + storage_cli_templates.each do |(template_path, keypath)| describe template_path do let(:template) { job.template(template_path) } @@ -245,7 +247,7 @@ def props_for_provider(provider) describe 'when provider is aliyun' do let(:props) { props_for_provider('aliyun') } - TEMPLATES.each_value do |(template_path, keypath)| + storage_cli_templates.each do |(template_path, keypath)| describe template_path do let(:template) { job.template(template_path) } @@ -273,25 +275,57 @@ def props_for_provider(provider) describe 'when provider is webdav' do let(:props) { props_for_provider('webdav') } - TEMPLATES.each_value do |(template_path, keypath)| + # Helper to determine expected directory key based on template path + def expected_directory_key(template_path) + case template_path + when /droplets/ then 'cc-droplets' + when /packages/ then 'cc-packages' + when /buildpacks/ then 'cc-buildpacks' + when /resource_pool/ then 'cc-resources' + end + end + + storage_cli_templates.each do |(template_path, keypath)| describe template_path do let(:template) { job.template(template_path) } + let(:directory_key) { expected_directory_key(template_path) } it 'maps required properties into the rendered config' do set(props, keypath, { 'provider' => 'webdav', 'username' => 'user', 'password' => 'secret', - 'public_endpoint' => 'webdav.com', + 'private_endpoint' => 'https://webdav.internal', + 'ca_cert' => 'some_cert' + }) + json = YAML.safe_load(template.render(props, consumes: links)) + expect(json).to include( + 'provider' => 'dav', + 'user' => 'user', + 'password' => 'secret', + 'endpoint' => "https://webdav.internal/admin/#{directory_key}", + 'tls' => { 'cert' => { 'ca' => 'some_cert' } } + ) + expect(json).not_to have_key('public_endpoint') + end + + it 'includes public_endpoint when provided' do + set(props, keypath, { + 'provider' => 'webdav', + 'username' => 'user', + 'password' => 'secret', + 'private_endpoint' => 'https://webdav.internal', + 'public_endpoint' => 'https://webdav.example.com', 'ca_cert' => 'some_cert' }) json = YAML.safe_load(template.render(props, consumes: links)) expect(json).to include( - 'provider' => 'webdav', + 'provider' => 'dav', 'user' => 'user', 'password' => 'secret', - 'endpoint' => 'webdav.com', - 'tls' => { 'cert' => 'some_cert' } + 'endpoint' => "https://webdav.internal/admin/#{directory_key}", + 'public_endpoint' => 'https://webdav.example.com', + 'tls' => { 'cert' => { 'ca' => 'some_cert' } } ) end @@ -300,22 +334,39 @@ def props_for_provider(provider) 'provider' => 'webdav', 'username' => 'user', 'password' => 'secret', - 'public_endpoint' => 'webdav.com', + 'private_endpoint' => 'https://webdav.internal', + 'public_endpoint' => 'https://webdav.example.com', 'ca_cert' => 'some_cert', - 'secret' => 'secret', + 'secret' => 'my-secret', + 'signed_url_format' => 'external-nginx-secure-link-signer', 'retry_attempts' => '4' }) json = YAML.safe_load(template.render(props, consumes: links)) expect(json).to include( - 'provider' => 'webdav', + 'provider' => 'dav', 'user' => 'user', 'password' => 'secret', - 'endpoint' => 'webdav.com', - 'tls' => { 'cert' => 'some_cert' }, - 'secret' => 'secret', + 'endpoint' => "https://webdav.internal/admin/#{directory_key}", + 'public_endpoint' => 'https://webdav.example.com', + 'tls' => { 'cert' => { 'ca' => 'some_cert' } }, + 'secret' => 'my-secret', + 'signed_url_format' => 'external-nginx-secure-link-signer', 'retry_attempts' => '4' ) end + + it 'omits public_endpoint when empty' do + set(props, keypath, { + 'provider' => 'webdav', + 'username' => 'user', + 'password' => 'secret', + 'private_endpoint' => 'https://webdav.internal', + 'public_endpoint' => '', + 'ca_cert' => 'some_cert' + }) + json = YAML.safe_load(template.render(props, consumes: links)) + expect(json).not_to have_key('public_endpoint') + end end end end