require "stringio" require "sfn" module Sfn class Command # Import command class Import < Command include Sfn::CommandModule::Base include Sfn::Utils::JSON include Sfn::Utils::ObjectStorage include Sfn::Utils::PathSelector # Run the import action def execute! raise NotImplementedError.new "Implementation updates required" stack_name, json_file = name_args ui.info "#{ui.color("Stack Import:", :bold)} #{stack_name}" unless json_file entries = [].tap do |_entries| _entries.push("s3") if config[:bucket] _entries.push("fs") if config[:path] end if entries.size > 1 valid = false until valid if config[:interactive_parameters] answer = ui.ask_question( "Import via file system (fs) or remote bucket (remote)?", :default => "remote", ) else answer = "remote" end valid = true if %w(remote fs).include?(answer) entries = [answer] end elsif entries.size < 1 ui.fatal "No path or bucket set. Unable to perform dynamic lookup!" exit 1 end case entries.first when "remote" json_file = remote_discovery else json_file = local_discovery end end if File.exists?(json_file) || json_file.is_a?(IO) content = json_file.is_a?(IO) ? json_file.read : File.read(json_file) export = Mash.new(_from_json(content)) begin creator = namespace.const_val(:Create).new( Smash.new( :template => _from_json(export[:stack][:template]), :options => _from_json(export[:stack][:options]), ), [stack_name] ) ui.info " - Starting creation of import" creator.execute! ui.info "#{ui.color("Stack Import", :bold)} (#{json_file}): #{ui.color("complete", :green)}" rescue => e ui.fatal "Failed to import stack: #{e}" debug "#{e.class}: #{e}\n#{e.backtrace.join("\n")}" raise end else ui.fatal "Failed to locate JSON export file (#{json_file})" raise end end # Generate bucket prefix # # @return [String, NilClass] def bucket_prefix if prefix = config[:bucket_prefix] if prefix.respond_to?(:call) prefix.call else prefix.to_s end end end # Discover remote file # # @return [IO] stack export IO def remote_discovery storage = provider.service_for(:storage) directory = storage.directories.get(config[:bucket]) file = prompt_for_file( directory, :directories_name => "Collections", :files_names => "Exports", :filter_prefix => bucket_prefix, ) if file remote_file = storage.files.get(file) StringIO.new(remote_file.body) end end # Discover remote file # # @return [IO] stack export IO def local_discovery _, bucket = config[:path].split("/", 2) storage = provider.service_for(:storage, :provider => :local, :local_root => "/") directory = storage.directories.get(bucket) prompt_for_file( directory, :directories_name => "Collections", :files_names => "Exports", ) end end end end