lib/command/apply_template.rb in cpl-1.4.0 vs lib/command/apply_template.rb in cpl-2.2.0
- old
+ new
@@ -6,11 +6,12 @@
USAGE = "apply-template TEMPLATE [TEMPLATE] ... [TEMPLATE]"
REQUIRES_ARGS = true
OPTIONS = [
app_option(required: true),
location_option,
- skip_confirm_option
+ skip_confirm_option,
+ add_app_identity_option
].freeze
DESCRIPTION = "Applies application-specific configs from templates"
LONG_DESCRIPTION = <<~DESC
- Applies application-specific configs from templates (e.g., for every review-app)
- Publishes (creates or updates) those at Control Plane infrastructure
@@ -34,73 +35,58 @@
```sh
# Applies single template.
cpl apply-template redis -a $APP_NAME
# Applies several templates (practically creating full app).
- cpl apply-template gvc postgres redis rails -a $APP_NAME
+ cpl apply-template app postgres redis rails -a $APP_NAME
```
EX
+ VALIDATIONS = %w[config templates].freeze
- def call # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
+ def call # rubocop:disable Metrics/MethodLength
+ @template_parser = TemplateParser.new(config)
+ @names_to_filenames = config.args.to_h do |name|
+ [name, @template_parser.template_filename(name)]
+ end
+
ensure_templates!
@created_items = []
@failed_templates = []
@skipped_templates = []
- @asked_for_confirmation = false
-
- pending_templates = templates.select do |template|
- if template == "gvc"
- confirm_app(template)
- else
- confirm_workload(template)
- end
+ templates = @template_parser.parse(@names_to_filenames.values)
+ pending_templates = confirm_templates(templates)
+ add_app_identity_template(pending_templates) if config.options[:add_app_identity]
+ pending_templates.each do |template|
+ apply_template(template)
end
- progress.puts if @asked_for_confirmation
-
- @deprecated_variables = []
-
- pending_templates.each do |template, filename|
- step("Applying template '#{template}'", abort_on_error: false) do
- items = apply_template(filename)
- if items
- items.each do |item|
- report_success(item)
- end
- else
- report_failure(template)
- end
-
- $CHILD_STATUS.success?
- end
- end
-
- warn_deprecated_variables
-
print_created_items
print_failed_templates
print_skipped_templates
- exit(1) if @failed_templates.any?
+ exit(ExitCode::ERROR_DEFAULT) if @failed_templates.any?
end
private
- def templates
- @templates ||= config.args.to_h do |template|
- [template, "#{config.app_cpln_dir}/templates/#{template}.yml"]
+ def template_kind(template)
+ case template["kind"]
+ when "gvc"
+ "app"
+ else
+ template["kind"]
end
end
def ensure_templates!
- missing_templates = templates.reject { |_template, filename| File.exist?(filename) }.to_h
+ missing_templates = @names_to_filenames.reject { |_, filename| File.exist?(filename) }
return if missing_templates.empty?
- missing_templates_str = missing_templates.map do |template, filename|
- " - #{template} (#{filename})"
+ missing_templates_str = missing_templates.map do |name, filename|
+ " - #{name} (#{filename})"
end.join("\n")
progress.puts("#{Shell.color('Missing templates:', :red)}\n#{missing_templates_str}\n\n")
raise "Can't find templates above, please create them."
end
@@ -111,78 +97,82 @@
@asked_for_confirmation = true
Shell.confirm(message)
end
def confirm_app(template)
- app = cp.fetch_gvc
+ app = cp.fetch_gvc(template["name"])
return true unless app
- confirmed = confirm_apply("App '#{config.app}' already exists, do you want to re-create it?")
+ confirmed = confirm_apply("App '#{template['name']}' already exists, do you want to re-create it?")
return true if confirmed
report_skipped(template)
false
end
def confirm_workload(template)
- workload = cp.fetch_workload(template)
+ workload = cp.fetch_workload(template["name"])
return true unless workload
- confirmed = confirm_apply("Workload '#{template}' already exists, do you want to re-create it?")
+ confirmed = confirm_apply("Workload '#{template['name']}' already exists, do you want to re-create it?")
return true if confirmed
report_skipped(template)
false
end
- def apply_template(filename) # rubocop:disable Metrics/MethodLength
- data = File.read(filename)
- .gsub("{{APP_ORG}}", config.org)
- .gsub("{{APP_NAME}}", config.app)
- .gsub("{{APP_LOCATION}}", config.location)
- .gsub("{{APP_LOCATION_LINK}}", app_location_link)
- .gsub("{{APP_IMAGE}}", latest_image)
- .gsub("{{APP_IMAGE_LINK}}", app_image_link)
- .gsub("{{APP_IDENTITY}}", app_identity)
- .gsub("{{APP_IDENTITY_LINK}}", app_identity_link)
- .gsub("{{APP_SECRETS}}", app_secrets)
- .gsub("{{APP_SECRETS_POLICY}}", app_secrets_policy)
+ def confirm_templates(templates) # rubocop:disable Metrics/MethodLength
+ @asked_for_confirmation = false
- find_deprecated_variables(data)
+ pending_templates = templates.select do |template|
+ case template["kind"]
+ when "gvc"
+ confirm_app(template)
+ when "workload"
+ confirm_workload(template)
+ else
+ true
+ end
+ end
- # Kept for backwards compatibility
- data = data
- .gsub("APP_ORG", config.org)
- .gsub("APP_GVC", config.app)
- .gsub("APP_LOCATION", config.location)
- .gsub("APP_IMAGE", latest_image)
+ progress.puts if @asked_for_confirmation
- # Don't read in YAML.safe_load as that doesn't handle multiple documents
- cp.apply_template(data)
+ pending_templates
end
- def new_variables
+ def add_app_identity_template(templates)
+ app_template_index = templates.index { |template| template["name"] == config.app }
+ app_identity_template_index = templates.index { |template| template["name"] == config.identity }
+
+ return unless app_template_index && app_identity_template_index.nil?
+
+ # Adding the identity template right after the app template is important since:
+ # a) we can't create the identity at the beginning because the app doesn't exist yet
+ # b) we also can't create it at the end because any workload templates associated with it will fail to apply
+ templates.insert(app_template_index + 1, build_app_identity_hash)
+ end
+
+ def build_app_identity_hash
{
- "APP_ORG" => "{{APP_ORG}}",
- "APP_GVC" => "{{APP_NAME}}",
- "APP_LOCATION" => "{{APP_LOCATION}}",
- "APP_IMAGE" => "{{APP_IMAGE}}"
+ "kind" => "identity",
+ "name" => config.identity
}
end
- def find_deprecated_variables(data)
- @deprecated_variables.push(*new_variables.keys.select { |old_key| data.include?(old_key) })
- @deprecated_variables = @deprecated_variables.uniq.sort
- end
+ def apply_template(template) # rubocop:disable Metrics/MethodLength
+ step("Applying template for #{template_kind(template)} '#{template['name']}'", abort_on_error: false) do
+ items = cp.apply_hash(template)
+ unless items
+ report_failure(template)
+ next false
+ end
- def warn_deprecated_variables
- return unless @deprecated_variables.any?
-
- message = "Please replace these variables in the templates, " \
- "as support for them will be removed in a future major version bump:"
- deprecated = @deprecated_variables.map { |old_key| " - #{old_key} -> #{new_variables[old_key]}" }.join("\n")
- progress.puts("\n#{Shell.color("DEPRECATED: #{message}", :yellow)}\n#{deprecated}")
+ items.each do |item|
+ report_success(item)
+ end
+ true
+ end
end
def report_success(item)
@created_items.push(item)
end
@@ -203,17 +193,17 @@
end
def print_failed_templates
return unless @failed_templates.any?
- failed = @failed_templates.map { |template| " - #{template}" }.join("\n")
+ failed = @failed_templates.map { |template| " - [#{template_kind(template)}] #{template['name']}" }.join("\n")
progress.puts("\n#{Shell.color('Failed to apply templates:', :red)}\n#{failed}")
end
def print_skipped_templates
return unless @skipped_templates.any?
- skipped = @skipped_templates.map { |template| " - #{template}" }.join("\n")
+ skipped = @skipped_templates.map { |template| " - [#{template_kind(template)}] #{template['name']}" }.join("\n")
progress.puts("\n#{Shell.color('Skipped templates (already exist):', :blue)}\n#{skipped}")
end
end
end