# # Author:: Christo De Lange (<opscode@dldinternet.com>) # Copyright:: Copyright (c) 2013 DLDInternet, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require 'chef/knife/chop_base' require 'chef/knife/chop_upload' # Because knife chop translate --action upload ... class Chef class Knife class ChopTranslate < Knife include ChopBase # -------------------------------------------------------------------------------- def run $stdout.sync = true watch_for_break @config[:parts].each{ |p| @config[:actions].each{ |a| actor = @actors[a] raise ChopInternalError.new("Actor for action '#{a.to_s}' cannot be nil!") unless actor method = %(#{a.to_s}_#{p.to_s}) raise ChopInternalError.new "Internal error: Method '#{method}' is not implemented in actor #{actor.class.name}!" unless actor.respond_to?(method,true) actor.send(method) } } end # -------------------------------------------------------------------------------- private # -------------------------------------------------------------------------------- # -------------------------------------------------------------------------------- def getNameArgs(xtra,set,key=nil) @logger.info "Translating these #{set.map{|name,file| file}.ai} ... " name_args = [] name_args << xtra if xtra != '' name_args << key if key name_args << set.map{ |name,file| file } name_args.flatten end # -------------------------------------------------------------------------------- def translateSet(set,args={}) raise ChopInternalError.new "Incorrect use of translateSet method from #{Kernel.caller[0].ai}. Received #{args.class.name}" unless args.is_a?(Hash) raise ChopError.new "Must specify the :resource type" unless args[:resource] @logger.debug "Translate set: #{set.ai}" unless set.size > 0 @logger.warn("The translate set is empty!") return end rsrc = args[:resource] verb = args[:verb] || "from file" xtra = args[:extra] || '' cmdp = args[:command] || lambda{|rsrc,verb,xtra| %(knife #{rsrc} #{verb} #{xtra}) } filp = args[:fileproc] || lambda{|cmd,name,file| # name not used/needed %(#{cmd} #{file}) } cmd = callCmdProc(cmdp, rsrc,verb,xtra) raise ChopInternalError.new("Translation not possible without using Chef/Knife API") unless @use_knife_api argv = "#{rsrc} #{verb}".split(%r(\s+)) klass= Chef::Knife.subcommand_class_from(argv) subc = klass.new() subc.config = @config.dup subc.config[:logger] = subc.logger = @logger scna = [] if args[:aggregate] and @use_knife_api if rsrc == 'data bag' set.each{|k,v| scna << getNameArgs(xtra,v,k) } else scna << getNameArgs(xtra,set) end else scna << set.map{ |name,file| if @use_knife_api "#{xtra} #{rsrc == 'cookbook' ? name : file}" else cmd = callCmdProc(filp, cmd, name, file) cmd end } end unless @config[:dry_run] begin scna.each{|batch| if args[:aggregate] and @use_knife_api subc.name_args = batch subc.translate() else batch.each{|a| if @use_knife_api subc.name_args = a subc.translate() else a.each{|file,cmd| execute cmd,"#{File.basename(file)} ... " } end } end } rescue => e @logger.error "#{e.class.name} #{e.message}" raise e end end end # -------------------------------------------------------------------------------- def translate_environments() logStep "Translate environments" # We are only interested in the ext we are starting with! translateSet(environments(@config,[@config[:translate][0]]), :resource => "environment", :aggregate => true) end # -------------------------------------------------------------------------------- def translate_roles() logStep "Translate roles" translateSet(roles(@config,[@config[:translate][0]]), :resource => "role", :aggregate => true) end # -------------------------------------------------------------------------------- def translate_databags() @logger.warn("Data bags cannot be translated to Ruby! (yet?)") #logStep "Translate databags" #translateSet(databags(@config,[@config[:translate][0]]), :resource => "data bag", :aggregate => true) end # -------------------------------------------------------------------------------- def translate_cookbooks() @logger.info("Cookbooks do not need to be translated to Ruby!") end end end end