lib/kontena/cli/apps/common.rb in kontena-cli-0.13.4 vs lib/kontena/cli/apps/common.rb in kontena-cli-0.14.0
- old
+ new
@@ -1,7 +1,10 @@
require 'yaml'
require_relative '../services/services_helper'
+require_relative './service_generator'
+require_relative './service_generator_v2'
+require_relative './yaml/reader'
module Kontena::Cli::Apps
module Common
include Kontena::Cli::Services::ServicesHelper
@@ -11,26 +14,68 @@
# @param [String] filename
# @param [Array<String>] service_list
# @param [String] prefix
# @return [Hash]
- def load_services(filename, service_list, prefix)
- services = parse_services(filename, nil, prefix)
- services.delete_if { |name, service| !service_list.include?(name)} unless service_list.empty?
+ def services_from_yaml(filename, service_list, prefix)
+ set_env_variables(prefix, current_grid)
+ reader = YAML::Reader.new(filename)
+ outcome = reader.execute
+ hint_on_validation_notifications(outcome[:notifications]) if outcome[:notifications].size > 0
+ abort_on_validation_errors(outcome[:errors]) if outcome[:errors].size > 0
+ kontena_services = generate_services(outcome[:services], outcome[:version])
+ kontena_services.delete_if { |name, service| !service_list.include?(name)} unless service_list.empty?
+ kontena_services
+ end
+
+ ##
+ # @param [Hash] yaml
+ # @param [String] version
+ # @return [Hash]
+ def generate_services(yaml_services, version)
+ services = {}
+ if version == '2'
+ generator_klass = ServiceGeneratorV2
+ else
+ generator_klass = ServiceGenerator
+ end
+ yaml_services.each do |service_name, config|
+ abort("Image is missing for #{service_name}. Aborting.") unless config['image']
+ services[service_name] = generator_klass.new(config).generate
+ end
services
end
+ def set_env_variables(project, grid)
+ ENV['project'] = project
+ ENV['grid'] = grid
+ end
+
+ def service_prefix
+ @service_prefix ||= project_name || project_name_from_yaml(filename) || current_dir
+ end
+
+ def project_name_from_yaml(file)
+ reader = YAML::Reader.new(file, true)
+ outcome = reader.execute
+ if outcome[:version] == '2'
+ outcome[:name]
+ else
+ nil
+ end
+ end
+
+
# @return [String]
def token
@token ||= require_token
end
# @param [String] name
# @return [String]
def prefixed_name(name)
return name if service_prefix.strip == ""
-
"#{service_prefix}-#{name}"
end
# @return [String]
def current_dir
@@ -41,80 +86,10 @@
# @return [Boolean]
def service_exists?(name)
get_service(token, prefixed_name(name)) rescue false
end
- # @param [String] file
- # @param [String,NilClass] name
- # @param [String] prefix
- # @return [Hash]
- def parse_services(file, name = nil, prefix = '')
- services = YAML.load(File.read(File.expand_path(file)) % {project: prefix, grid: current_grid})
- Dir.chdir(File.dirname(File.expand_path(file))) do
- services.each do |name, options|
- normalize_env_vars(options)
- if options.has_key?('extends')
- extension_file = options['extends']['file']
- service_name = options['extends']['service']
- options.delete('extends')
- services[name] = extend_options(options, extension_file , service_name, prefix)
- end
- end
- end
- if name.nil?
- services
- else
- abort("Service #{name} not found in #{file}") unless services.has_key?(name)
- services[name]
- end
- end
-
- # @param [Hash] options
- # @param [String] file
- # @param [String] service_name
- # @param [String] prefix
- # @return [Hash]
- def extend_options(options, file, service_name, prefix)
- parent_options = parse_services(file, service_name, prefix)
- options['environment'] = extend_env_vars(parent_options['environment'], options['environment'])
- options['secrets'] = extend_secrets(parent_options['secrets'], options['secrets'])
- parent_options.merge(options)
- end
-
- # @param [Hash] options
- def normalize_env_vars(options)
- if options['environment'].is_a?(Hash)
- options['environment'] = options['environment'].map{|k, v| "#{k}=#{v}"}
- end
- end
-
- # @param [Array] from
- # @param [Array] to
- # @return [Array]
- def extend_env_vars(from, to)
- env_vars = to || []
- if from
- from.each do |env|
- env_vars << env unless to && to.find {|key| key.split('=').first == env.split('=').first}
- end
- end
- env_vars
- end
-
- # @param [Array] from
- # @param [Array] to
- # @return [Array]
- def extend_secrets(from, to)
- secrets = to || []
- if from
- from.each do |from_secret|
- secrets << from_secret unless to && to.any? {|to_secret| to_secret['secret'] == from_secret['secret']}
- end
- end
- secrets
- end
-
# @param [Hash] services
# @param [String] file
def create_yml(services, file = 'kontena.yml')
yml = File.new(file, 'w')
yml.puts services.to_yaml
@@ -127,9 +102,40 @@
@app_json = JSON.parse(File.read('app.json'))
else
@app_json = {}
end
@app_json
+ end
+
+ def display_notifications(messages, color = :yellow)
+ messages.each do |files|
+ files.each do |file, services|
+ STDERR.puts "#{file}:".colorize(color)
+ services.each do |service|
+ service.each do |name, errors|
+ STDERR.puts " #{name}:".colorize(color)
+ if errors.is_a?(String)
+ STDERR.puts " - #{errors}".colorize(color)
+ else
+ errors.each do |key, error|
+ STDERR.puts " - #{key}: #{error.to_json}".colorize(color)
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+
+ def hint_on_validation_notifications(errors)
+ STDERR.puts "YAML contains the following unsupported options and they were rejected:".colorize(:yellow)
+ display_notifications(errors)
+ end
+
+ def abort_on_validation_errors(errors)
+ STDERR.puts "YAML validation failed! Aborting.".colorize(:red)
+ display_notifications(errors, :red)
+ abort
end
def valid_addons(prefix=nil)
if prefix
prefix = "#{prefix}-"