module Dpl module Providers class ChefSupermarket < Provider register :'chef-supermarket' register :chef_supermarket status :alpha full_name 'Chef Supermarket' description sq(<<-str) tbd str gem 'chef', '~> 12.0', require: %w( chef/cookbook/cookbook_version_loader chef/cookbook_site_streaming_uploader chef/cookbook_uploader ) gem 'json' gem 'mime-types', '~> 3.2.2' gem 'net-telnet', '~> 0.1.0' if ruby_pre?('2.3') gem 'rack' env :chef opt '--user_id ID', 'Chef Supermarket user name', required: true opt '--name NAME', 'Cookbook name', note: 'defaults to the name given in metadata.json or metadata.rb', alias: :cookbook_name, deprecated: :cookbook_name opt '--category CAT', 'Cookbook category in Supermarket', required: true, see: 'https://docs.getchef.com/knife_cookbook_site.html#id12', alias: :cookbook_category, deprecated: :cookbook_category opt '--client_key KEY', 'Client API key file name', default: 'client.pem' opt '--dir DIR', 'Directory containing the cookbook', default: '.' URL = "https://supermarket.chef.io/api/v1/cookbooks" msgs validate: 'Validating cookbook', upload: 'Uploading cookbook %{name} to %{url}', missing_file: 'Missing file: %s', unknown_error: 'Unknown error while sharing cookbook: %s', version_exists: 'The same version of this cookbook already exists on the Opscode Cookbook Site.' def setup Chef::Config[:client_key] = client_key chdir dir end def validate info :validate validate_file client_key uploader.validate_cookbooks end def deploy info :upload upload end private def upload res = Chef::CookbookSiteStreamingUploader.post(URL, user_id, client_key, params) handle_error(res.body) if res.code.to_i != 201 end def params { cookbook: json(category: category), tarball: tarball } end def tarball shell "tar -czf /tmp/#{name}.tgz -C #{build_dir} ." shell "tar -tvf /tmp/#{name}.tgz" open "/tmp/#{name}.tgz" end def name @name ||= name_from_json || name_from_rb || error(:missing_file, 'metadata.json or metadata.rb') end def name_from_json JSON.load(read('metadata.json'))['name'] if file?('metadata.json') end def name_from_rb Chef::Cookbook::Metadata.new.from_file('metadata.rb') if file?('metadata.rb') end def cookbook @cookbook ||= loader.cookbook_version end def loader Chef::Cookbook::CookbookVersionLoader.new('.').tap(&:load!) end def uploader Chef::CookbookUploader.new(cookbook) end def build_dir @build_dir ||= Chef::CookbookSiteStreamingUploader.create_build_dir(cookbook) end def validate_file(path) error :missing_file, path unless file?(path) end def url URL end def handle_error(res) res = JSON.parse(res) unknown_error(res) unless res['error_messages'] version_exists if res['error_messages'][0].include?('Version already exists') error "#{res['error_messages'][0]}" end def unknown_error(msg) error :unknown_error, msg end def version_exists error :version_exists end def json(obj) JSON.dump(obj) end end end end