clc-fork-chef-metal 0.13.alpha.1 → 0.14.alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +50 -0
- data/README.md +0 -2
- data/bin/metal +3 -4
- data/lib/chef/provider/machine.rb +16 -3
- data/lib/chef/provider/machine_image.rb +54 -0
- data/lib/chef/resource/machine.rb +6 -0
- data/lib/chef/resource/machine_image.rb +29 -0
- data/lib/chef_metal/action_handler.rb +4 -1
- data/lib/chef_metal/chef_image_spec.rb +106 -0
- data/lib/chef_metal/chef_machine_spec.rb +4 -0
- data/lib/chef_metal/chef_run_data.rb +9 -0
- data/lib/chef_metal/convergence_strategy/no_converge.rb +0 -1
- data/lib/chef_metal/driver.rb +21 -0
- data/lib/chef_metal/image_spec.rb +70 -0
- data/lib/chef_metal/recipe_dsl.rb +10 -0
- data/lib/chef_metal/transport/ssh.rb +1 -1
- data/lib/chef_metal/transport/winrm.rb +1 -0
- data/lib/chef_metal/version.rb +1 -1
- metadata +6 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: d31f76e87ba58390c47ec3723b1365ac0e548d49
         | 
| 4 | 
            +
              data.tar.gz: 8c8ee1fb4b04a64cec1a14284662f61cd189a4b2
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 183c855125905188c74526fe492b9122bfbe762541d2bdc3432d72561387910a519ddc2d1ebc0c06b7de2a49648c34062f50f8bf154b07e7ede5a9f9d91693ca
         | 
| 7 | 
            +
              data.tar.gz: 727800f1ffd242ae4b04758235d4c4531aeefdc747ce7738750b700108561dbab7b3668b58791636fd51c624849f59d3aad5511f5b435c4584b01287cd7d4dd4
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,5 +1,55 @@ | |
| 1 1 | 
             
            # Chef Metal Changelog
         | 
| 2 2 |  | 
| 3 | 
            +
            ## 0.14.1 (8/18/2014)
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            - Fix "metal execute mario ls" to work again
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            ## 0.14 (8/18/2014)
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            - FEATURE: Add the machine_image resource (@jkeiser, @johnewart):
         | 
| 10 | 
            +
              ```ruby
         | 
| 11 | 
            +
              machine_image 'base' do
         | 
| 12 | 
            +
                machine_options :bootstrap_options => { :image_id => 'ami-1234798123431', :ssh_username => 'root' }
         | 
| 13 | 
            +
                recipe 'secure_base'
         | 
| 14 | 
            +
                recipe 'corp_users'
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
              # Build an image based on 'base' that has apache
         | 
| 17 | 
            +
              machine_image 'apache' do
         | 
| 18 | 
            +
                # All bootstrap options, like ssh_username, are carried forward
         | 
| 19 | 
            +
                from_image 'base'
         | 
| 20 | 
            +
                recipe 'apache2'
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
              # Build an image with my web app based on the apache base image
         | 
| 23 | 
            +
              machine_image 'myapp' do
         | 
| 24 | 
            +
                from_image 'apache'
         | 
| 25 | 
            +
                recipe 'mywebapp'
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
              # Build an image with mysql and my schema based on the corporate base image
         | 
| 28 | 
            +
              machine_image 'mydb' do
         | 
| 29 | 
            +
                from_image 'base'
         | 
| 30 | 
            +
                recipe 'mysql'
         | 
| 31 | 
            +
                recipe 'myschema'
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
              # Build a DB machine from mydb.  Does not reinstall stuff! :)
         | 
| 34 | 
            +
              machine 'db' do
         | 
| 35 | 
            +
                from_image 'mydb'
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
              # Build a web app machine from myapp.  Does not reinstall stuff! :)
         | 
| 38 | 
            +
              machine 'myapp1' do
         | 
| 39 | 
            +
                from_image 'myapp'
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
              ```
         | 
| 42 | 
            +
              - Creates a node with the name of the machine_image, which contains metadata
         | 
| 43 | 
            +
                like the username of the image.  This makes things like AWS image registries
         | 
| 44 | 
            +
                possible.
         | 
| 45 | 
            +
            - Fix the no_converge convergence strategy (@johnewart)
         | 
| 46 | 
            +
            - SSH port forwarding improvements:
         | 
| 47 | 
            +
              - Detects *any* IP on the localhost and forwards it--not just 127.0.0.1
         | 
| 48 | 
            +
              - Binds to localhost on the remote side instead of 127.0.0.1, allowing for IPv6 communication
         | 
| 49 | 
            +
              - Tries multiple ports--if the origin port is already taken, tries "0" (ephemeral).
         | 
| 50 | 
            +
            - Fix SSH race condition causing port forwarding to happen twice (and fail miserably)
         | 
| 51 | 
            +
            - Add ChefMetal.connect_to_machine('mario')
         | 
| 52 | 
            +
             | 
| 3 53 | 
             
            ## 0.13 (6/17/2014)
         | 
| 4 54 |  | 
| 5 55 | 
             
            - make winrm work again (@mwrock)
         | 
    
        data/README.md
    CHANGED
    
    | @@ -25,8 +25,6 @@ Try It Out | |
| 25 25 |  | 
| 26 26 | 
             
            You can try out Metal in many different flavors.
         | 
| 27 27 |  | 
| 28 | 
            -
            HINT: chef-metal looks prettiest with chef 11.14 alpha.  `gem install chef --pre` to get it.
         | 
| 29 | 
            -
             | 
| 30 28 | 
             
            ### Vagrant
         | 
| 31 29 |  | 
| 32 30 | 
             
            To give it a spin, install Vagrant and VirtualBox and try this from the `chef-metal/docs/examples` directory:
         | 
    
        data/bin/metal
    CHANGED
    
    | @@ -114,7 +114,7 @@ class ChefMetal::Application < Chef::Application | |
| 114 114 | 
             
                  case command
         | 
| 115 115 | 
             
                  when 'execute'
         | 
| 116 116 | 
             
                    connect_to_machines(cli_arguments.shift) do |machine|
         | 
| 117 | 
            -
                      machine.execute(action_handler, cli_arguments.join(' '), :read_only => config[:read_only], :stream => config[:stream], :timeout => config[:timeout].to_f)
         | 
| 117 | 
            +
                      result = machine.execute(action_handler, cli_arguments.join(' '), :read_only => config[:read_only], :stream => config[:stream], :timeout => config[:timeout].to_f)
         | 
| 118 118 | 
             
                      puts result.stdout if result.stdout != '' && !config[:stream] && Chef::Config.log_level != :debug
         | 
| 119 119 | 
             
                      STDERR.puts result.stderr if result.stderr != '' && !config[:stream] && Chef::Config.log_level != :debug
         | 
| 120 120 | 
             
                      exit_code = result.exitstatus if result.exitstatus != 0
         | 
| @@ -246,9 +246,8 @@ class ChefMetal::Application < Chef::Application | |
| 246 246 | 
             
              end
         | 
| 247 247 |  | 
| 248 248 | 
             
              def connect_to_machines(spec)
         | 
| 249 | 
            -
                 | 
| 250 | 
            -
             | 
| 251 | 
            -
                  machine_specs.map { |machine_spec| ChefMetal.connect_to_machine(machine_spec) }
         | 
| 249 | 
            +
                machine_specs(spec).each do |machine_spec|
         | 
| 250 | 
            +
                  yield ChefMetal.connect_to_machine(machine_spec)
         | 
| 252 251 | 
             
                end
         | 
| 253 252 | 
             
              end
         | 
| 254 253 |  | 
| @@ -94,18 +94,31 @@ class Chef::Provider::Machine < Chef::Provider::LWRPBase | |
| 94 94 | 
             
                end
         | 
| 95 95 | 
             
              end
         | 
| 96 96 |  | 
| 97 | 
            +
              def from_image_spec
         | 
| 98 | 
            +
                @from_image_spec ||= begin
         | 
| 99 | 
            +
                  if new_resource.from_image
         | 
| 100 | 
            +
                    ChefMetal::ChefImageSpec.get(new_resource.from_image, new_resource.chef_server)
         | 
| 101 | 
            +
                  else
         | 
| 102 | 
            +
                    nil
         | 
| 103 | 
            +
                  end
         | 
| 104 | 
            +
                end
         | 
| 105 | 
            +
              end
         | 
| 106 | 
            +
             | 
| 97 107 | 
             
              def new_machine_options
         | 
| 98 108 | 
             
                machine_options(new_driver)
         | 
| 99 109 | 
             
              end
         | 
| 100 110 |  | 
| 101 111 | 
             
              def current_machine_options
         | 
| 102 | 
            -
                 | 
| 103 | 
            -
                  machine_options(current_driver)
         | 
| 104 | 
            -
                end
         | 
| 112 | 
            +
                machine_options(current_driver)
         | 
| 105 113 | 
             
              end
         | 
| 106 114 |  | 
| 107 115 | 
             
              def machine_options(driver)
         | 
| 108 116 | 
             
                configs = []
         | 
| 117 | 
            +
             | 
| 118 | 
            +
                if from_image_spec && from_image_spec.machine_options
         | 
| 119 | 
            +
                  configs << from_image_spec.machine_options
         | 
| 120 | 
            +
                end
         | 
| 121 | 
            +
             | 
| 109 122 | 
             
                configs << {
         | 
| 110 123 | 
             
                  :convergence_options =>
         | 
| 111 124 | 
             
                    [ :chef_server,
         | 
| @@ -0,0 +1,54 @@ | |
| 1 | 
            +
            require 'chef/provider/lwrp_base'
         | 
| 2 | 
            +
            require 'chef/provider/chef_node'
         | 
| 3 | 
            +
            require 'openssl'
         | 
| 4 | 
            +
            require 'chef_metal/chef_provider_action_handler'
         | 
| 5 | 
            +
            require 'chef_metal/chef_image_spec'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            class Chef::Provider::MachineImage < Chef::Provider::LWRPBase
         | 
| 8 | 
            +
              def action_handler
         | 
| 9 | 
            +
                @action_handler ||= ChefMetal::ChefProviderActionHandler.new(self)
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              def load_current_resource
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              # Get the driver specified in the resource
         | 
| 16 | 
            +
              def new_driver
         | 
| 17 | 
            +
                @new_driver ||= run_context.chef_metal.driver_for(new_resource.driver)
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              action :create do
         | 
| 21 | 
            +
                # Get the image mapping on the server (from name to image-id)
         | 
| 22 | 
            +
                image_spec = ChefMetal::ChefImageSpec.get(new_resource.name, new_resource.chef_server) ||
         | 
| 23 | 
            +
                             ChefMetal::ChefImageSpec.empty(new_resource.name, new_resource.chef_server)
         | 
| 24 | 
            +
                if image_spec.location
         | 
| 25 | 
            +
                  # TODO check for real existence and maybe update
         | 
| 26 | 
            +
                else
         | 
| 27 | 
            +
                  #
         | 
| 28 | 
            +
                  # Create a new image
         | 
| 29 | 
            +
                  #
         | 
| 30 | 
            +
                  image_spec.machine_options = new_resource.machine_options
         | 
| 31 | 
            +
                  create_image(image_spec)
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
              action :destroy do
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
              def create_image(image_spec)
         | 
| 39 | 
            +
                # 1. Create the exemplar machine
         | 
| 40 | 
            +
                machine_provider = Chef::Provider::Machine.new(new_resource, run_context)
         | 
| 41 | 
            +
                machine_provider.load_current_resource
         | 
| 42 | 
            +
                machine_provider.action_converge
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                # 2. Create the image
         | 
| 45 | 
            +
                new_driver.allocate_image(action_handler, image_spec, new_resource.image_options,
         | 
| 46 | 
            +
                                          machine_provider.machine_spec)
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                # 3. Save the linkage from name -> image id
         | 
| 49 | 
            +
                image_spec.save(action_handler)
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                # 4. Wait for image to be ready
         | 
| 52 | 
            +
                new_driver.ready_image(action_handler, image_spec, new_resource.image_options)
         | 
| 53 | 
            +
              end
         | 
| 54 | 
            +
            end
         | 
| @@ -57,6 +57,12 @@ class Chef::Resource::Machine < Chef::Resource::LWRPBase | |
| 57 57 | 
             
              # files '/remote/path.txt' => { :content => 'woo' }
         | 
| 58 58 | 
             
              attribute :files, :kind_of => Hash
         | 
| 59 59 |  | 
| 60 | 
            +
              # The named machine_image to start from.  Specify the name of a machine_image
         | 
| 61 | 
            +
              # object and the default machine_options will be set to use that image.
         | 
| 62 | 
            +
              # == Examples
         | 
| 63 | 
            +
              # from_image 'company_base_image'
         | 
| 64 | 
            +
              attribute :from_image, :kind_of => String
         | 
| 65 | 
            +
             | 
| 60 66 | 
             
              # A single file to upload, in the format REMOTE_PATH, LOCAL_PATH|HASH.
         | 
| 61 67 | 
             
              # This directive may be passed multiple times, and multiple files will be uploaded.
         | 
| 62 68 | 
             
              # == Examples
         | 
| @@ -0,0 +1,29 @@ | |
| 1 | 
            +
            require 'chef/resource/lwrp_base'
         | 
| 2 | 
            +
            require 'cheffish'
         | 
| 3 | 
            +
            require 'chef_metal'
         | 
| 4 | 
            +
            require 'cheffish/merged_config'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            class Chef::Resource::MachineImage < Chef::Resource::Machine
         | 
| 7 | 
            +
              self.resource_name = 'machine_image'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              def initialize(*args)
         | 
| 10 | 
            +
                super
         | 
| 11 | 
            +
                @image_options = run_context.chef_metal.current_image_options
         | 
| 12 | 
            +
                @machine_options = run_context.chef_metal.current_machine_options
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              # TODO check if we still have all the actions from machine
         | 
| 16 | 
            +
              actions :create, :destroy, :archive
         | 
| 17 | 
            +
              default_action :create
         | 
| 18 | 
            +
             | 
| 19 | 
            +
              attribute :image_options, :kind_of => Hash
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              # TODO
         | 
| 22 | 
            +
              # - policy for old version cleanup
         | 
| 23 | 
            +
              # - when attributes or recipes of the machine_image changes, or when the actual
         | 
| 24 | 
            +
              #   recipes therein change, we will regenerate the image
         | 
| 25 | 
            +
              # - attribute to force or turn off image updates
         | 
| 26 | 
            +
              # - ability to rebuild new image based on the previous image
         | 
| 27 | 
            +
              # - ability to specify whether and how to keep the image-building machine around
         | 
| 28 | 
            +
              # - ability to specify whether to leave the chef config around or not
         | 
| 29 | 
            +
            end
         | 
| @@ -42,9 +42,12 @@ module ChefMetal | |
| 42 42 | 
             
                # action that needs to be done.
         | 
| 43 43 | 
             
                def perform_action(description)
         | 
| 44 44 | 
             
                  if should_perform_actions
         | 
| 45 | 
            -
                    yield
         | 
| 45 | 
            +
                    result = yield
         | 
| 46 | 
            +
                  else
         | 
| 47 | 
            +
                    result = nil
         | 
| 46 48 | 
             
                  end
         | 
| 47 49 | 
             
                  performed_action(description)
         | 
| 50 | 
            +
                  result
         | 
| 48 51 | 
             
                end
         | 
| 49 52 |  | 
| 50 53 | 
             
                # Open a stream which can be printed to and closed
         | 
| @@ -0,0 +1,106 @@ | |
| 1 | 
            +
            require 'chef_metal'
         | 
| 2 | 
            +
            require 'cheffish'
         | 
| 3 | 
            +
            require 'chef_metal/image_spec'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module ChefMetal
         | 
| 6 | 
            +
              #
         | 
| 7 | 
            +
              # Specification for a image. Sufficient information to find and contact it
         | 
| 8 | 
            +
              # after it has been set up.
         | 
| 9 | 
            +
              #
         | 
| 10 | 
            +
              class ChefImageSpec < ImageSpec
         | 
| 11 | 
            +
                def initialize(node, chef_server)
         | 
| 12 | 
            +
                  super(node)
         | 
| 13 | 
            +
                  @chef_server = chef_server
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                #
         | 
| 17 | 
            +
                # Get a ImageSpec from the chef server.  If the node does not exist on the
         | 
| 18 | 
            +
                # server, it returns nil.
         | 
| 19 | 
            +
                #
         | 
| 20 | 
            +
                def self.get(name, chef_server = Cheffish.default_chef_server)
         | 
| 21 | 
            +
                  chef_api = Cheffish.chef_server_api(chef_server)
         | 
| 22 | 
            +
                  begin
         | 
| 23 | 
            +
                    data = chef_api.get("/data/images/#{name}")
         | 
| 24 | 
            +
                    data['machine_options'] = strings_to_symbols(data['machine_options'])
         | 
| 25 | 
            +
                    ChefImageSpec.new(data, chef_server)
         | 
| 26 | 
            +
                  rescue Net::HTTPServerException => e
         | 
| 27 | 
            +
                    if e.response.code == '404'
         | 
| 28 | 
            +
                      nil
         | 
| 29 | 
            +
                    else
         | 
| 30 | 
            +
                      raise
         | 
| 31 | 
            +
                    end
         | 
| 32 | 
            +
                  end
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                # Creates a new empty ImageSpec with the given name.
         | 
| 36 | 
            +
                def self.empty(id, chef_server = Cheffish.default_chef_server)
         | 
| 37 | 
            +
                  ChefImageSpec.new({ 'id' => id }, chef_server)
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                #
         | 
| 41 | 
            +
                # Globally unique identifier for this image. Does not depend on the image's
         | 
| 42 | 
            +
                # location or existence.
         | 
| 43 | 
            +
                #
         | 
| 44 | 
            +
                def id
         | 
| 45 | 
            +
                  ChefImageSpec.id_from(chef_server, name)
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                def self.id_from(chef_server, name)
         | 
| 49 | 
            +
                  "#{chef_server[:chef_server_url]}/data/images/#{name}"
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                #
         | 
| 53 | 
            +
                # Save this node to the server.  If you have significant information that
         | 
| 54 | 
            +
                # could be lost, you should do this as quickly as possible.  Data will be
         | 
| 55 | 
            +
                # saved automatically for you after allocate_image and ready_image.
         | 
| 56 | 
            +
                #
         | 
| 57 | 
            +
                def save(action_handler)
         | 
| 58 | 
            +
                  # Save the node to the server.
         | 
| 59 | 
            +
                  _self = self
         | 
| 60 | 
            +
                  _chef_server = _self.chef_server
         | 
| 61 | 
            +
                  ChefMetal.inline_resource(action_handler) do
         | 
| 62 | 
            +
                    chef_data_bag_item _self.name do
         | 
| 63 | 
            +
                      data_bag 'images'
         | 
| 64 | 
            +
                      chef_server _chef_server
         | 
| 65 | 
            +
                      raw_data _self.image_data
         | 
| 66 | 
            +
                    end
         | 
| 67 | 
            +
                  end
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                def delete(action_handler)
         | 
| 71 | 
            +
                  # Save the node to the server.
         | 
| 72 | 
            +
                  _self = self
         | 
| 73 | 
            +
                  _chef_server = _self.chef_server
         | 
| 74 | 
            +
                  ChefMetal.inline_resource(action_handler) do
         | 
| 75 | 
            +
                    chef_data_bag_item _self.name do
         | 
| 76 | 
            +
                      data_bag 'images'
         | 
| 77 | 
            +
                      chef_server _chef_server
         | 
| 78 | 
            +
                      action :destroy
         | 
| 79 | 
            +
                    end
         | 
| 80 | 
            +
                  end
         | 
| 81 | 
            +
                end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                protected
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                attr_reader :chef_server
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                #
         | 
| 88 | 
            +
                # Chef API object for the given Chef server
         | 
| 89 | 
            +
                #
         | 
| 90 | 
            +
                def chef_api
         | 
| 91 | 
            +
                  Cheffish.server_api_for(chef_server)
         | 
| 92 | 
            +
                end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                def self.strings_to_symbols(data)
         | 
| 95 | 
            +
                  if data.is_a?(Hash)
         | 
| 96 | 
            +
                    result = {}
         | 
| 97 | 
            +
                    data.each_pair do |key, value|
         | 
| 98 | 
            +
                      result[key.to_sym] = strings_to_symbols(value)
         | 
| 99 | 
            +
                    end
         | 
| 100 | 
            +
                    result
         | 
| 101 | 
            +
                  else
         | 
| 102 | 
            +
                    data
         | 
| 103 | 
            +
                  end
         | 
| 104 | 
            +
                end
         | 
| 105 | 
            +
              end
         | 
| 106 | 
            +
            end
         | 
| @@ -1,3 +1,4 @@ | |
| 1 | 
            +
            require 'pry'
         | 
| 1 2 | 
             
            require 'chef_metal'
         | 
| 2 3 | 
             
            require 'cheffish'
         | 
| 3 4 | 
             
            require 'chef_metal/machine_spec'
         | 
| @@ -53,6 +54,9 @@ module ChefMetal | |
| 53 54 | 
             
                # saved automatically for you after allocate_machine and ready_machine.
         | 
| 54 55 | 
             
                #
         | 
| 55 56 | 
             
                def save(action_handler)
         | 
| 57 | 
            +
                  if location && (!location.is_a?(Hash) || !location['driver_url'])
         | 
| 58 | 
            +
                    raise "Drivers must specify a canonical driver_url in machine_spec.location.  Contact your driver's author."
         | 
| 59 | 
            +
                  end
         | 
| 56 60 | 
             
                  # Save the node to the server.
         | 
| 57 61 | 
             
                  _self = self
         | 
| 58 62 | 
             
                  _chef_server = _self.chef_server
         | 
| @@ -16,6 +16,7 @@ module ChefMetal | |
| 16 16 | 
             
                attr_reader :current_driver
         | 
| 17 17 |  | 
| 18 18 | 
             
                with :machine_options
         | 
| 19 | 
            +
                with :image_options
         | 
| 19 20 |  | 
| 20 21 | 
             
                def with_driver(driver, options = nil, &block)
         | 
| 21 22 | 
             
                  if drivers[driver] && options
         | 
| @@ -49,6 +50,14 @@ module ChefMetal | |
| 49 50 | 
             
                  end
         | 
| 50 51 | 
             
                end
         | 
| 51 52 |  | 
| 53 | 
            +
                def current_image_options
         | 
| 54 | 
            +
                  if @current_image_options
         | 
| 55 | 
            +
                    @current_image_options
         | 
| 56 | 
            +
                  else
         | 
| 57 | 
            +
                    {}
         | 
| 58 | 
            +
                  end
         | 
| 59 | 
            +
                end
         | 
| 60 | 
            +
             | 
| 52 61 | 
             
                def add_machine_options(options, &block)
         | 
| 53 62 | 
             
                  with_machine_options(Chef::Mixin::DeepMerge.hash_only_merge(current_machine_options, options), &block)
         | 
| 54 63 | 
             
                end
         | 
    
        data/lib/chef_metal/driver.rb
    CHANGED
    
    | @@ -182,6 +182,27 @@ module ChefMetal | |
| 182 182 | 
             
                  raise "#{self.class} does not implement stop_machine"
         | 
| 183 183 | 
             
                end
         | 
| 184 184 |  | 
| 185 | 
            +
                #
         | 
| 186 | 
            +
                # Allocate an image. Returns quickly with an ID that tracks the image.
         | 
| 187 | 
            +
                #
         | 
| 188 | 
            +
                def allocate_image(action_handler, image_spec, image_options, machine_spec)
         | 
| 189 | 
            +
                  raise "#{self.class} does not implement create_image"
         | 
| 190 | 
            +
                end
         | 
| 191 | 
            +
             | 
| 192 | 
            +
                #
         | 
| 193 | 
            +
                # Ready an image, waiting till the point where it is ready to be used.
         | 
| 194 | 
            +
                #
         | 
| 195 | 
            +
                def ready_image(action_handler, image_spec, image_options)
         | 
| 196 | 
            +
                  raise "#{self.class} does not implement ready_image"
         | 
| 197 | 
            +
                end
         | 
| 198 | 
            +
             | 
| 199 | 
            +
                #
         | 
| 200 | 
            +
                # Destroy an image.
         | 
| 201 | 
            +
                #
         | 
| 202 | 
            +
                def destroy_image(action_handler, image_spec, image_options)
         | 
| 203 | 
            +
                  raise "#{self.class} does not implement destroy_image"
         | 
| 204 | 
            +
                end
         | 
| 205 | 
            +
             | 
| 185 206 | 
             
                #
         | 
| 186 207 | 
             
                # Optional interface methods
         | 
| 187 208 | 
             
                #
         | 
| @@ -0,0 +1,70 @@ | |
| 1 | 
            +
            module ChefMetal
         | 
| 2 | 
            +
              #
         | 
| 3 | 
            +
              # Specification for a image. Sufficient information to find and contact it
         | 
| 4 | 
            +
              # after it has been set up.
         | 
| 5 | 
            +
              #
         | 
| 6 | 
            +
              class ImageSpec
         | 
| 7 | 
            +
                def initialize(image_data)
         | 
| 8 | 
            +
                  @image_data = image_data
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                attr_reader :image_data
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                #
         | 
| 14 | 
            +
                # Globally unique identifier for this image. Does not depend on the image's
         | 
| 15 | 
            +
                # location or existence.
         | 
| 16 | 
            +
                #
         | 
| 17 | 
            +
                def id
         | 
| 18 | 
            +
                  raise "id unimplemented"
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                #
         | 
| 22 | 
            +
                # Name of the image. Corresponds to the name in "image 'name' do" ...
         | 
| 23 | 
            +
                #
         | 
| 24 | 
            +
                def name
         | 
| 25 | 
            +
                  image_data['id']
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                #
         | 
| 29 | 
            +
                # Location of this image. This should be a freeform hash, with enough
         | 
| 30 | 
            +
                # information for the driver to look it up and create a image object to
         | 
| 31 | 
            +
                # access it.
         | 
| 32 | 
            +
                #
         | 
| 33 | 
            +
                # This MUST include a 'driver_url' attribute with the driver's URL in it.
         | 
| 34 | 
            +
                #
         | 
| 35 | 
            +
                # chef-metal will do its darnedest to not lose this information.
         | 
| 36 | 
            +
                #
         | 
| 37 | 
            +
                def location
         | 
| 38 | 
            +
                  image_data['location']
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                #
         | 
| 42 | 
            +
                # Set the location for this image.
         | 
| 43 | 
            +
                #
         | 
| 44 | 
            +
                def location=(value)
         | 
| 45 | 
            +
                  image_data['location'] = value
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                def machine_options
         | 
| 49 | 
            +
                  image_data['machine_options']
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                def machine_options=(value)
         | 
| 53 | 
            +
                  image_data['machine_options'] = value
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                # URL to the driver.  Convenience for location['driver_url']
         | 
| 57 | 
            +
                def driver_url
         | 
| 58 | 
            +
                  location ? location['driver_url'] : nil
         | 
| 59 | 
            +
                end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                #
         | 
| 62 | 
            +
                # Save this image_data to the server.  If you have significant information that
         | 
| 63 | 
            +
                # could be lost, you should do this as quickly as possible.  image_data will be
         | 
| 64 | 
            +
                # saved automatically for you after allocate_image and ready_image.
         | 
| 65 | 
            +
                #
         | 
| 66 | 
            +
                def save(action_handler)
         | 
| 67 | 
            +
                  raise "save unimplemented"
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
            end
         | 
| @@ -9,6 +9,8 @@ require 'chef/resource/machine_file' | |
| 9 9 | 
             
            require 'chef/provider/machine_file'
         | 
| 10 10 | 
             
            require 'chef/resource/machine_execute'
         | 
| 11 11 | 
             
            require 'chef/provider/machine_execute'
         | 
| 12 | 
            +
            require 'chef/resource/machine_image'
         | 
| 13 | 
            +
            require 'chef/provider/machine_image'
         | 
| 12 14 |  | 
| 13 15 | 
             
            class Chef
         | 
| 14 16 | 
             
              module DSL
         | 
| @@ -29,6 +31,14 @@ class Chef | |
| 29 31 | 
             
                    run_context.chef_metal.add_machine_options(options, &block)
         | 
| 30 32 | 
             
                  end
         | 
| 31 33 |  | 
| 34 | 
            +
                  def with_image_options(image_options, &block)
         | 
| 35 | 
            +
                    run_context.chef_metal.with_image_options(image_options, &block)
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  def current_image_options
         | 
| 39 | 
            +
                    run_context.chef_metal.current_image_options
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
             | 
| 32 42 | 
             
                  NOT_PASSED = Object.new
         | 
| 33 43 |  | 
| 34 44 | 
             
                  def auto_batch_machines(value = NOT_PASSED)
         | 
| @@ -141,7 +141,7 @@ module ChefMetal | |
| 141 141 | 
             
                    # If you can't pwd within 10 seconds, you can't pwd
         | 
| 142 142 | 
             
                    execute('pwd', :timeout => 10)
         | 
| 143 143 | 
             
                    true
         | 
| 144 | 
            -
                  rescue Timeout::Error, Errno::EHOSTUNREACH, Errno::ETIMEDOUT, Errno::ECONNREFUSED, Errno::ECONNRESET, Net::SSH::Disconnect
         | 
| 144 | 
            +
                  rescue Timeout::Error, Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::EHOSTDOWN, Errno::ETIMEDOUT, Errno::ECONNREFUSED, Errno::ECONNRESET, Net::SSH::Disconnect
         | 
| 145 145 | 
             
                    Chef::Log.debug("#{username}@#{host} unavailable: network connection failed or broke: #{$!.inspect}")
         | 
| 146 146 | 
             
                    disconnect
         | 
| 147 147 | 
             
                    false
         | 
| @@ -19,6 +19,7 @@ module ChefMetal | |
| 19 19 |  | 
| 20 20 | 
             
                  def execute(command, execute_options = {})
         | 
| 21 21 | 
             
                    output = with_execute_timeout(execute_options) do
         | 
| 22 | 
            +
                      session.set_timeout(execute_timeout(execute_options))
         | 
| 22 23 | 
             
                      session.run_powershell_script(command) do |stdout, stderr|
         | 
| 23 24 | 
             
                        stream_chunk(execute_options, stdout, stderr)
         | 
| 24 25 | 
             
                      end
         | 
    
        data/lib/chef_metal/version.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: clc-fork-chef-metal
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.14.alpha.1
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - John Keiser
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2014- | 
| 11 | 
            +
            date: 2014-09-04 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: chef
         | 
| @@ -155,13 +155,16 @@ files: | |
| 155 155 | 
             
            - lib/chef/provider/machine_batch.rb
         | 
| 156 156 | 
             
            - lib/chef/provider/machine_execute.rb
         | 
| 157 157 | 
             
            - lib/chef/provider/machine_file.rb
         | 
| 158 | 
            +
            - lib/chef/provider/machine_image.rb
         | 
| 158 159 | 
             
            - lib/chef/resource/machine.rb
         | 
| 159 160 | 
             
            - lib/chef/resource/machine_batch.rb
         | 
| 160 161 | 
             
            - lib/chef/resource/machine_execute.rb
         | 
| 161 162 | 
             
            - lib/chef/resource/machine_file.rb
         | 
| 163 | 
            +
            - lib/chef/resource/machine_image.rb
         | 
| 162 164 | 
             
            - lib/chef_metal.rb
         | 
| 163 165 | 
             
            - lib/chef_metal/action_handler.rb
         | 
| 164 166 | 
             
            - lib/chef_metal/add_prefix_action_handler.rb
         | 
| 167 | 
            +
            - lib/chef_metal/chef_image_spec.rb
         | 
| 165 168 | 
             
            - lib/chef_metal/chef_machine_spec.rb
         | 
| 166 169 | 
             
            - lib/chef_metal/chef_provider_action_handler.rb
         | 
| 167 170 | 
             
            - lib/chef_metal/chef_run_data.rb
         | 
| @@ -172,6 +175,7 @@ files: | |
| 172 175 | 
             
            - lib/chef_metal/convergence_strategy/no_converge.rb
         | 
| 173 176 | 
             
            - lib/chef_metal/convergence_strategy/precreate_chef_objects.rb
         | 
| 174 177 | 
             
            - lib/chef_metal/driver.rb
         | 
| 178 | 
            +
            - lib/chef_metal/image_spec.rb
         | 
| 175 179 | 
             
            - lib/chef_metal/machine.rb
         | 
| 176 180 | 
             
            - lib/chef_metal/machine/basic_machine.rb
         | 
| 177 181 | 
             
            - lib/chef_metal/machine/unix_machine.rb
         |