fog-openstack 0.1.22 → 0.1.23
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/.travis.yml +6 -10
- data/fog-openstack.gemspec +4 -4
- data/lib/fog/compute/openstack.rb +9 -4
- data/lib/fog/compute/openstack/models/server_group.rb +1 -1
- data/lib/fog/openstack.rb +1 -0
- data/lib/fog/openstack/version.rb +1 -7
- data/lib/fog/orchestration/openstack/models/stack.rb +2 -1
- data/lib/fog/orchestration/openstack/requests/create_stack.rb +23 -0
- data/lib/fog/orchestration/openstack/requests/update_stack.rb +27 -5
- data/lib/fog/orchestration/util/recursive_hot_file_loader.rb +220 -0
- metadata +20 -20
- data/gemfiles/Gemfile-1.9 +0 -22
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 57deefcd73bd729138eb23ed6b27a7d5edebd986
         | 
| 4 | 
            +
              data.tar.gz: 3f0e6066357fcac8d96ef1acace0ecc03336de19
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: be0002aaf6e52c2578b3ec290e5cbe1dd7ef3fb30e1c5d58827e0de2c8fef58a99b812cf6e64c131f36a09c7b3d025d00731a277da19fa96f0e1f7080c67f8a5
         | 
| 7 | 
            +
              data.tar.gz: 76d3fffed28f2442446a69c41a71eeba4eb1684183417fb605ee16a524425cc7a93dc4fc8c57d9da76901107b97514eaf9d1cba2eec2c80228fc948780a3c6a3
         | 
    
        data/.travis.yml
    CHANGED
    
    | @@ -1,5 +1,7 @@ | |
| 1 1 | 
             
            language: ruby
         | 
| 2 2 | 
             
            sudo: false
         | 
| 3 | 
            +
            before_install:
         | 
| 4 | 
            +
              - gem update bundler
         | 
| 3 5 | 
             
            script:
         | 
| 4 6 | 
             
              - bundle exec rake test
         | 
| 5 7 | 
             
              - bundle exec rake spec
         | 
| @@ -8,20 +10,14 @@ env: | |
| 8 10 | 
             
            matrix:
         | 
| 9 11 | 
             
              fast_finish: true
         | 
| 10 12 | 
             
              include:
         | 
| 11 | 
            -
              - rvm: 1.9.3
         | 
| 12 | 
            -
                gemfile: gemfiles/Gemfile-1.9
         | 
| 13 | 
            -
              - rvm: 2.0.0
         | 
| 14 | 
            -
                gemfile: Gemfile
         | 
| 15 | 
            -
              - rvm: 2.1.0
         | 
| 16 | 
            -
                gemfile: Gemfile
         | 
| 17 | 
            -
              - rvm: 2.1.1
         | 
| 18 | 
            -
                gemfile: Gemfile
         | 
| 19 13 | 
             
              - rvm: 2.2.0
         | 
| 20 14 | 
             
                gemfile: Gemfile
         | 
| 21 15 | 
             
              - rvm: 2.3.0
         | 
| 22 16 | 
             
                gemfile: Gemfile
         | 
| 23 | 
            -
              - rvm:  | 
| 24 | 
            -
                gemfile:  | 
| 17 | 
            +
              - rvm: 2.3.1
         | 
| 18 | 
            +
                gemfile: Gemfile
         | 
| 19 | 
            +
              - rvm: 2.4.2
         | 
| 20 | 
            +
                gemfile: Gemfile
         | 
| 25 21 | 
             
              - rvm: jruby-head
         | 
| 26 22 | 
             
                gemfile: Gemfile
         | 
| 27 23 | 
             
              allow_failures:
         | 
    
        data/fog-openstack.gemspec
    CHANGED
    
    | @@ -19,18 +19,18 @@ Gem::Specification.new do |spec| | |
| 19 19 | 
             
              spec.executables   = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
         | 
| 20 20 | 
             
              spec.require_paths = ["lib"]
         | 
| 21 21 |  | 
| 22 | 
            -
              spec. | 
| 22 | 
            +
              spec.required_ruby_version = '>= 2.1.0'
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              spec.add_dependency 'fog-core',  '~> 1.40'
         | 
| 23 25 | 
             
              spec.add_dependency 'fog-json',  '>= 1.0'
         | 
| 24 26 | 
             
              spec.add_dependency 'ipaddress', '>= 0.8'
         | 
| 25 27 |  | 
| 26 28 | 
             
              spec.add_development_dependency 'bundler', '~> 1.6'
         | 
| 27 | 
            -
             | 
| 28 | 
            -
            #  spec.add_development_dependency 'coveralls'
         | 
| 29 | 
            +
              spec.add_development_dependency 'coveralls'
         | 
| 29 30 | 
             
              spec.add_development_dependency "mime-types"
         | 
| 30 31 | 
             
              spec.add_development_dependency "mime-types-data"
         | 
| 31 32 | 
             
              spec.add_development_dependency 'rake',    '~> 10.0'
         | 
| 32 33 | 
             
              spec.add_development_dependency 'rubocop'
         | 
| 33 | 
            -
              spec.add_development_dependency 'rubyzip', '~> 0.9.9'
         | 
| 34 34 | 
             
              spec.add_development_dependency 'shindo',  '~> 0.3'
         | 
| 35 35 | 
             
              spec.add_development_dependency 'minitest'
         | 
| 36 36 | 
             
              spec.add_development_dependency 'vcr'
         | 
| @@ -1,8 +1,9 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
             | 
| 3 1 | 
             
            module Fog
         | 
| 4 2 | 
             
              module Compute
         | 
| 5 3 | 
             
                class OpenStack < Fog::Service
         | 
| 4 | 
            +
                  SUPPORTED_VERSIONS = /v2\.0|v2\.1/
         | 
| 5 | 
            +
                  SUPPORTED_MICROVERSION = '2.15'.freeze
         | 
| 6 | 
            +
             | 
| 6 7 | 
             
                  requires :openstack_auth_url
         | 
| 7 8 | 
             
                  recognizes :openstack_auth_token, :openstack_management_url,
         | 
| 8 9 | 
             
                             :persistent, :openstack_service_type, :openstack_service_name,
         | 
| @@ -380,6 +381,10 @@ module Fog | |
| 380 381 | 
             
                    end
         | 
| 381 382 |  | 
| 382 383 | 
             
                    def initialize(options = {})
         | 
| 384 | 
            +
                      @supported_versions = SUPPORTED_VERSIONS
         | 
| 385 | 
            +
                      @supported_microversion = SUPPORTED_MICROVERSION
         | 
| 386 | 
            +
                      @microversion_key = 'X-OpenStack-Nova-API-Version'
         | 
| 387 | 
            +
             | 
| 383 388 | 
             
                      initialize_identity options
         | 
| 384 389 |  | 
| 385 390 | 
             
                      @openstack_identity_service_type = options[:openstack_identity_service_type] || 'identity'
         | 
| @@ -391,9 +396,9 @@ module Fog | |
| 391 396 |  | 
| 392 397 | 
             
                      authenticate
         | 
| 393 398 |  | 
| 394 | 
            -
                      unless @path =~ / | 
| 399 | 
            +
                      unless @path =~ %r{/(v2|v2\.0|v2\.1)/}
         | 
| 395 400 | 
             
                        raise Fog::OpenStack::Errors::ServiceUnavailable,
         | 
| 396 | 
            -
                              "OpenStack compute binding only supports version  | 
| 401 | 
            +
                              "OpenStack compute binding only supports version v2 and v2.1"
         | 
| 397 402 | 
             
                      end
         | 
| 398 403 |  | 
| 399 404 | 
             
                      @persistent = options[:persistent] || false
         | 
| @@ -9,7 +9,7 @@ module Fog | |
| 9 9 | 
             
                    attribute :policies, :type => :array
         | 
| 10 10 | 
             
                    attribute :members
         | 
| 11 11 |  | 
| 12 | 
            -
                    VALID_SERVER_GROUP_POLICIES = ['affinity', 'anti-affinity'].freeze
         | 
| 12 | 
            +
                    VALID_SERVER_GROUP_POLICIES = ['affinity', 'anti-affinity', 'soft-affinity', 'soft-anti-affinity'].freeze
         | 
| 13 13 |  | 
| 14 14 | 
             
                    def self.validate_server_group_policy(policy)
         | 
| 15 15 | 
             
                      raise ArgumentError, "#{policy} is an invalid policy... must use one of #{VALID_SERVER_GROUP_POLICIES.join(', ')}" \
         | 
    
        data/lib/fog/openstack.rb
    CHANGED
    
    
| @@ -1,11 +1,5 @@ | |
| 1 1 | 
             
            module Fog
         | 
| 2 2 | 
             
              module Openstack
         | 
| 3 | 
            -
                VERSION = "0.1. | 
| 4 | 
            -
             | 
| 5 | 
            -
                def self.included(base)
         | 
| 6 | 
            -
                  if RUBY_VERSION < "2"
         | 
| 7 | 
            -
                    puts "DEPRECATION WARNING - Support for Ruby 1.9 will be dropped in fog-openstack 0.2 and higher. Please upgrade to Ruby 2 or above."
         | 
| 8 | 
            -
                  end
         | 
| 9 | 
            -
                end
         | 
| 3 | 
            +
                VERSION = "0.1.23"
         | 
| 10 4 | 
             
              end
         | 
| 11 5 | 
             
            end
         | 
| @@ -8,7 +8,7 @@ module Fog | |
| 8 8 |  | 
| 9 9 | 
             
                    %w(capabilities description disable_rollback links notification_topics outputs parameters
         | 
| 10 10 | 
             
                       stack_name stack_status stack_status_reason template_description timeout_mins parent
         | 
| 11 | 
            -
                       creation_time updated_time stack_user_project_id stack_owner).each do |a|
         | 
| 11 | 
            +
                       creation_time updated_time stack_user_project_id stack_owner files).each do |a|
         | 
| 12 12 | 
             
                      attribute a.to_sym
         | 
| 13 13 | 
             
                    end
         | 
| 14 14 |  | 
| @@ -118,6 +118,7 @@ module Fog | |
| 118 118 | 
             
                      }
         | 
| 119 119 | 
             
                      options[:template] = template_content if template_content
         | 
| 120 120 | 
             
                      options[:template_url] = @template_url if @template_url
         | 
| 121 | 
            +
                      options[:files] = @files if @files
         | 
| 121 122 | 
             
                      options
         | 
| 122 123 | 
             
                    end
         | 
| 123 124 | 
             
                    private :default_options
         | 
| @@ -10,6 +10,7 @@ module Fog | |
| 10 10 | 
             
                    #   * :template [String] Structure containing the template body.
         | 
| 11 11 | 
             
                    #   or (one of the two Template parameters is required)
         | 
| 12 12 | 
             
                    #   * :template_url [String] URL of file containing the template body.
         | 
| 13 | 
            +
                    #   * :files [Hash] Hash with files resources.
         | 
| 13 14 | 
             
                    #   * :disable_rollback [Boolean] Controls rollback on stack creation failure, defaults to false.
         | 
| 14 15 | 
             
                    #   * :parameters [Hash] Hash of providers to supply to template
         | 
| 15 16 | 
             
                    #   * :timeout_mins [Integer] Minutes to wait before status is set to CREATE_FAILED
         | 
| @@ -28,6 +29,18 @@ module Fog | |
| 28 29 | 
             
                        }.merge(arg2.nil? ? {} : arg2)
         | 
| 29 30 | 
             
                      end
         | 
| 30 31 |  | 
| 32 | 
            +
                      # Templates should always:
         | 
| 33 | 
            +
                      #  - be strings
         | 
| 34 | 
            +
                      #  - contain URI references instead of relative paths.
         | 
| 35 | 
            +
                      # Passing :template_url may not work well with `get_file` and remote `type`:
         | 
| 36 | 
            +
                      #  the python client implementation in shade retrieves from :template_uri
         | 
| 37 | 
            +
                      #  and replaces it with :template.
         | 
| 38 | 
            +
                      #  see https://github.com/openstack-infra/shade/blob/master/shade/openstackcloud.py#L1201
         | 
| 39 | 
            +
                      #  see https://developer.openstack.org/api-ref/orchestration/v1/index.html#create-stack
         | 
| 40 | 
            +
                      file_resolver = Util::RecursiveHotFileLoader.new(options[:template] || options[:template_url], options[:files])
         | 
| 41 | 
            +
                      options[:template] = file_resolver.template
         | 
| 42 | 
            +
                      options[:files] = file_resolver.files unless file_resolver.files.empty?
         | 
| 43 | 
            +
             | 
| 31 44 | 
             
                      request(
         | 
| 32 45 | 
             
                        :expects => 201,
         | 
| 33 46 | 
             
                        :path    => 'stacks',
         | 
| @@ -68,6 +81,16 @@ module Fog | |
| 68 81 | 
             
                        'id'    => stack_id,
         | 
| 69 82 | 
             
                        'links' => [{"href" => "http://localhost:8004/v1/fake_tenant_id/stacks/#{options[:stack_name]}/#{stack_id}", "rel" => "self"}]
         | 
| 70 83 | 
             
                      }
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                      if options.key?(:files)
         | 
| 86 | 
            +
                        response.body['files'] = {'foo.sh' => 'hello'}
         | 
| 87 | 
            +
                      end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                      if options.key?(:template) || options.key?(:template_url)
         | 
| 90 | 
            +
                        file_resolver = Util::RecursiveHotFileLoader.new(options[:template] || options[:template_url], options[:files])
         | 
| 91 | 
            +
                        response.body['files'] = file_resolver.files unless file_resolver.files.empty?
         | 
| 92 | 
            +
                      end
         | 
| 93 | 
            +
             | 
| 71 94 | 
             
                      response
         | 
| 72 95 | 
             
                    end
         | 
| 73 96 | 
             
                  end
         | 
| @@ -10,6 +10,7 @@ module Fog | |
| 10 10 | 
             
                    #   or (one of the two Template parameters is required)
         | 
| 11 11 | 
             
                    #   * :template_url [String] URL of file containing the template body.
         | 
| 12 12 | 
             
                    #   * :parameters [Hash] Hash of providers to supply to template.
         | 
| 13 | 
            +
                    #   * :files [Hash] Hash with files resources.
         | 
| 13 14 | 
             
                    #
         | 
| 14 15 | 
             
                    def update_stack(arg1, arg2 = nil, arg3 = nil)
         | 
| 15 16 | 
             
                      if arg1.kind_of?(Stack)
         | 
| @@ -17,22 +18,34 @@ module Fog | |
| 17 18 | 
             
                        stack = arg1
         | 
| 18 19 | 
             
                        stack_name = stack.stack_name
         | 
| 19 20 | 
             
                        stack_id = stack.id
         | 
| 20 | 
            -
                         | 
| 21 | 
            +
                        options = arg2.nil? ? {} : arg2
         | 
| 21 22 | 
             
                      else
         | 
| 22 23 | 
             
                        # Deprecated, update_stack(stack_id, stack_name, options = {})
         | 
| 23 24 | 
             
                        Fog::Logger.deprecation("#update_stack(stack_id, stack_name, options) is deprecated, use #update_stack(stack, options) instead [light_black](#{caller.first})[/]")
         | 
| 24 25 | 
             
                        stack_id = arg1
         | 
| 25 26 | 
             
                        stack_name = arg2
         | 
| 26 | 
            -
                         | 
| 27 | 
            +
                        options = {
         | 
| 27 28 | 
             
                          :stack_name => stack_name
         | 
| 28 29 | 
             
                        }.merge(arg3.nil? ? {} : arg3)
         | 
| 29 30 | 
             
                      end
         | 
| 30 31 |  | 
| 32 | 
            +
                      # Templates should always:
         | 
| 33 | 
            +
                      #  - be strings
         | 
| 34 | 
            +
                      #  - contain URI references instead of relative paths.
         | 
| 35 | 
            +
                      # Passing :template_url may not work well with `get_file` and remote `type`:
         | 
| 36 | 
            +
                      #  the python client implementation in shade retrieves from :template_uri
         | 
| 37 | 
            +
                      #  and replaces it with :template.
         | 
| 38 | 
            +
                      #  see https://github.com/openstack-infra/shade/blob/master/shade/openstackcloud.py#L1201
         | 
| 39 | 
            +
                      #  see https://developer.openstack.org/api-ref/orchestration/v1/index.html#create-stack
         | 
| 40 | 
            +
                      file_resolver = Util::RecursiveHotFileLoader.new(options[:template] || options[:template_url], options[:files])
         | 
| 41 | 
            +
                      options[:template] = file_resolver.template
         | 
| 42 | 
            +
                      options[:files] = file_resolver.files unless file_resolver.files.empty?
         | 
| 43 | 
            +
             | 
| 31 44 | 
             
                      request(
         | 
| 32 45 | 
             
                        :expects => 202,
         | 
| 33 46 | 
             
                        :path    => "stacks/#{stack_name}/#{stack_id}",
         | 
| 34 47 | 
             
                        :method  => 'PUT',
         | 
| 35 | 
            -
                        :body    => Fog::JSON.encode( | 
| 48 | 
            +
                        :body    => Fog::JSON.encode(options)
         | 
| 36 49 | 
             
                      )
         | 
| 37 50 | 
             
                    end
         | 
| 38 51 | 
             
                  end
         | 
| @@ -44,17 +57,26 @@ module Fog | |
| 44 57 | 
             
                        stack = arg1
         | 
| 45 58 | 
             
                        stack_name = stack.stack_name
         | 
| 46 59 | 
             
                        stack_id = stack.id
         | 
| 47 | 
            -
                         | 
| 60 | 
            +
                        options = arg2.nil? ? {} : arg2
         | 
| 48 61 | 
             
                      else
         | 
| 49 62 | 
             
                        # Deprecated, update_stack(stack_id, stack_name, options = {})
         | 
| 50 63 | 
             
                        Fog::Logger.deprecation("#update_stack(stack_id, stack_name, options) is deprecated, use #update_stack(stack, options) instead [light_black](#{caller.first})[/]")
         | 
| 51 64 | 
             
                        stack_id = arg1
         | 
| 52 65 | 
             
                        stack_name = arg2
         | 
| 53 | 
            -
                         | 
| 66 | 
            +
                        options = {
         | 
| 54 67 | 
             
                          :stack_name => stack_name
         | 
| 55 68 | 
             
                        }.merge(arg3.nil? ? {} : arg3)
         | 
| 56 69 | 
             
                      end
         | 
| 57 70 |  | 
| 71 | 
            +
                      if options.key?(:files)
         | 
| 72 | 
            +
                        response.body['files'] = {'foo.sh' => 'hello'}
         | 
| 73 | 
            +
                      end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                      if options.key?(:template) || options.key?(:template_url)
         | 
| 76 | 
            +
                        file_resolver = Util::RecursiveHotFileLoader.new(options[:template] || options[:template_url], options[:files])
         | 
| 77 | 
            +
                        response.body['files'] = file_resolver.files unless file_resolver.files.empty?
         | 
| 78 | 
            +
                      end
         | 
| 79 | 
            +
             | 
| 58 80 | 
             
                      response = Excon::Response.new
         | 
| 59 81 | 
             
                      response.status = 202
         | 
| 60 82 | 
             
                      response.body = {}
         | 
| @@ -0,0 +1,220 @@ | |
| 1 | 
            +
            require 'set'
         | 
| 2 | 
            +
            require 'yaml'
         | 
| 3 | 
            +
            require 'open-uri'
         | 
| 4 | 
            +
            require 'objspace'
         | 
| 5 | 
            +
            require 'fog/core'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            module Fog
         | 
| 8 | 
            +
              module Orchestration
         | 
| 9 | 
            +
                module Util
         | 
| 10 | 
            +
                  #
         | 
| 11 | 
            +
                  # Resolve get_file resources found in a HOT template populating
         | 
| 12 | 
            +
                  #  a files Hash conforming to Heat Specs
         | 
| 13 | 
            +
                  #  https://developer.openstack.org/api-ref/orchestration/v1/index.html?expanded=create-stack-detail#stacks
         | 
| 14 | 
            +
                  #
         | 
| 15 | 
            +
                  # Files present in :files are not processed further. The others
         | 
| 16 | 
            +
                  #   are added to the Hash. This behavior is the same implemented in openstack-infra/shade
         | 
| 17 | 
            +
                  #   see https://github.com/openstack-infra/shade/blob/1d16f64fbf376a956cafed1b3edd8e51ccc16f2c/shade/openstackcloud.py#L1200
         | 
| 18 | 
            +
                  #
         | 
| 19 | 
            +
                  # This implementation just process nested templates but not resource
         | 
| 20 | 
            +
                  #  registries.
         | 
| 21 | 
            +
                  class RecursiveHotFileLoader
         | 
| 22 | 
            +
                    attr_reader :files
         | 
| 23 | 
            +
                    attr_reader :template
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                    def initialize(template, files = nil)
         | 
| 26 | 
            +
                      # According to https://github.com/fog/fog-openstack/blame/master/docs/orchestration.md#L122
         | 
| 27 | 
            +
                      #  templates can be either String or Hash.
         | 
| 28 | 
            +
                      #  If it's an Hash, we deep_copy it so the passed argument
         | 
| 29 | 
            +
                      #  is not modified by get_file_contents.
         | 
| 30 | 
            +
                      template = deep_copy(template)
         | 
| 31 | 
            +
                      @visited = Set.new
         | 
| 32 | 
            +
                      @files = files || {}
         | 
| 33 | 
            +
                      @template = get_template_contents(template)
         | 
| 34 | 
            +
                    end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                    # Return string
         | 
| 37 | 
            +
                    def url_join(prefix, suffix)
         | 
| 38 | 
            +
                      if prefix
         | 
| 39 | 
            +
                        # URI.join replaces prefix parts before a
         | 
| 40 | 
            +
                        #  trailing slash. See https://docs.ruby-lang.org/en/2.3.0/URI.html.
         | 
| 41 | 
            +
                        prefix += '/' unless prefix.to_s.end_with?("/")
         | 
| 42 | 
            +
                        suffix = URI.join(prefix, suffix)
         | 
| 43 | 
            +
                        # Force URI to use traditional file scheme representation.
         | 
| 44 | 
            +
                        suffix.host = "" if suffix.scheme == "file"
         | 
| 45 | 
            +
                      end
         | 
| 46 | 
            +
                      suffix.to_s
         | 
| 47 | 
            +
                    end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                    # Retrieve a template content.
         | 
| 50 | 
            +
                    #
         | 
| 51 | 
            +
                    # @param template_file can be either:
         | 
| 52 | 
            +
                    #          - a raw_template string
         | 
| 53 | 
            +
                    #          - an URI string
         | 
| 54 | 
            +
                    #          - an Hash containing the parsed template.
         | 
| 55 | 
            +
                    #
         | 
| 56 | 
            +
                    # XXX: we could use named parameters
         | 
| 57 | 
            +
                    # and better mimic heatclient implementation.
         | 
| 58 | 
            +
                    def get_template_contents(template_file)
         | 
| 59 | 
            +
                      Fog::Logger.debug("get_template_contents [#{template_file}]")
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                      raise "template_file should be Hash or String, not #{template_file.class.name}" unless
         | 
| 62 | 
            +
                        template_file.kind_of?(String) || template_file.kind_of?(Hash)
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                      local_base_url = url_join("file:/", File.absolute_path(Dir.pwd))
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                      if template_file.kind_of?(Hash)
         | 
| 67 | 
            +
                        template_base_url = local_base_url
         | 
| 68 | 
            +
                        template = template_file
         | 
| 69 | 
            +
                      elsif template_is_raw?(template_file)
         | 
| 70 | 
            +
                        template_base_url = local_base_url
         | 
| 71 | 
            +
                        template = YAML.safe_load(template_file, [Date])
         | 
| 72 | 
            +
                      elsif template_is_url?(template_file)
         | 
| 73 | 
            +
                        template_file = normalise_file_path_to_url(template_file)
         | 
| 74 | 
            +
                        template_base_url = base_url_for_url(template_file)
         | 
| 75 | 
            +
                        raw_template = read_uri(template_file)
         | 
| 76 | 
            +
                        template = YAML.safe_load(raw_template, [Date])
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                        Fog::Logger.debug("Template visited: #{@visited}")
         | 
| 79 | 
            +
                        @visited.add(template_file)
         | 
| 80 | 
            +
                      else
         | 
| 81 | 
            +
                        raise "template_file is not a string of the expected form"
         | 
| 82 | 
            +
                      end
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                      get_file_contents(template, template_base_url)
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                      template
         | 
| 87 | 
            +
                    end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                    # Traverse the template tree looking for get_file and type
         | 
| 90 | 
            +
                    #   and populating the @files attribute with their content.
         | 
| 91 | 
            +
                    #   Resource referenced by get_file and type are eventually
         | 
| 92 | 
            +
                    #   replaced with their absolute URI as done in heatclient
         | 
| 93 | 
            +
                    #   and shade.
         | 
| 94 | 
            +
                    #
         | 
| 95 | 
            +
                    def get_file_contents(from_data, base_url)
         | 
| 96 | 
            +
                      Fog::Logger.debug("Processing #{from_data} with base_url #{base_url}")
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                      # Recursively traverse the tree
         | 
| 99 | 
            +
                      #   if recurse_data is Array or Hash
         | 
| 100 | 
            +
                      recurse_data = from_data.kind_of?(Hash) ? from_data.values : from_data
         | 
| 101 | 
            +
                      recurse_data.each { |value| get_file_contents(value, base_url) } if recurse_data.kind_of?(Array)
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                      # I'm on a Hash, process it.
         | 
| 104 | 
            +
                      return unless from_data.kind_of?(Hash)
         | 
| 105 | 
            +
                      from_data.each do |key, value|
         | 
| 106 | 
            +
                        next if ignore_if(key, value)
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                        # Resolve relative paths.
         | 
| 109 | 
            +
                        str_url = url_join(base_url, value)
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                        next if @files.key?(str_url)
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                        file_content = read_uri(str_url)
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                        # get_file should not recurse hot templates.
         | 
| 116 | 
            +
                        if key == "type" && template_is_raw?(file_content) && !@visited.include?(str_url)
         | 
| 117 | 
            +
                          template = get_template_contents(str_url)
         | 
| 118 | 
            +
                          file_content = YAML.dump(template)
         | 
| 119 | 
            +
                        end
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                        @files[str_url] = file_content
         | 
| 122 | 
            +
                        # replace the data value with the normalised absolute URL as required
         | 
| 123 | 
            +
                        #  by https://docs.openstack.org/heat/pike/template_guide/hot_spec.html#get-file
         | 
| 124 | 
            +
                        from_data[key] = str_url
         | 
| 125 | 
            +
                      end
         | 
| 126 | 
            +
                    end
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                    private
         | 
| 129 | 
            +
             | 
| 130 | 
            +
                    # Retrive the content of a local or remote file.
         | 
| 131 | 
            +
                    #
         | 
| 132 | 
            +
                    # @param A local or remote uri.
         | 
| 133 | 
            +
                    #
         | 
| 134 | 
            +
                    # @raise ArgumentError if it's not a valid uri
         | 
| 135 | 
            +
                    #
         | 
| 136 | 
            +
                    # Protect open-uri from malign arguments like
         | 
| 137 | 
            +
                    #  - "|ls"
         | 
| 138 | 
            +
                    #  - multiline strings
         | 
| 139 | 
            +
                    def read_uri(uri_or_filename)
         | 
| 140 | 
            +
                      remote_schemes = %w[http https ftp]
         | 
| 141 | 
            +
                      Fog::Logger.debug("Opening #{uri_or_filename}")
         | 
| 142 | 
            +
             | 
| 143 | 
            +
                      begin
         | 
| 144 | 
            +
                        # Validate URI to protect from open-uri attacks.
         | 
| 145 | 
            +
                        url = URI(uri_or_filename)
         | 
| 146 | 
            +
             | 
| 147 | 
            +
                        if remote_schemes.include?(url.scheme)
         | 
| 148 | 
            +
                          # Remote schemes must contain an host.
         | 
| 149 | 
            +
                          raise ArgumentError if url.host.nil?
         | 
| 150 | 
            +
             | 
| 151 | 
            +
                          # Encode URI with spaces.
         | 
| 152 | 
            +
                          uri_or_filename = uri_or_filename.gsub(/ /, "%20")
         | 
| 153 | 
            +
                        end
         | 
| 154 | 
            +
                      rescue URI::InvalidURIError
         | 
| 155 | 
            +
                        raise ArgumentError, "Not a valid URI: #{uri_or_filename}"
         | 
| 156 | 
            +
                      end
         | 
| 157 | 
            +
             | 
| 158 | 
            +
                      # TODO: A future revision may implement a retry.
         | 
| 159 | 
            +
                      content = ''
         | 
| 160 | 
            +
                      # open-uri doesn't open "file:///" uris.
         | 
| 161 | 
            +
                      uri_or_filename = uri_or_filename.sub(/^file:/, "")
         | 
| 162 | 
            +
             | 
| 163 | 
            +
                      open(uri_or_filename) { |f| content = f.read }
         | 
| 164 | 
            +
                      content
         | 
| 165 | 
            +
                    end
         | 
| 166 | 
            +
             | 
| 167 | 
            +
                    # Return true if the file is an heat template, false otherwise.
         | 
| 168 | 
            +
                    def template_is_raw?(content)
         | 
| 169 | 
            +
                      htv = content.strip.index("heat_template_version")
         | 
| 170 | 
            +
                      # Tolerate some leading character in case of a json template.
         | 
| 171 | 
            +
                      htv && htv < 5
         | 
| 172 | 
            +
                    end
         | 
| 173 | 
            +
             | 
| 174 | 
            +
                    # Return true if it's an URI, false otherwise.
         | 
| 175 | 
            +
                    def template_is_url?(path)
         | 
| 176 | 
            +
                      normalise_file_path_to_url(path)
         | 
| 177 | 
            +
                      true
         | 
| 178 | 
            +
                    rescue ArgumentError, URI::InvalidURIError
         | 
| 179 | 
            +
                      false
         | 
| 180 | 
            +
                    end
         | 
| 181 | 
            +
             | 
| 182 | 
            +
                    # Return true if I should I process this this file.
         | 
| 183 | 
            +
                    #
         | 
| 184 | 
            +
                    # @param [String] An heat template key
         | 
| 185 | 
            +
                    #
         | 
| 186 | 
            +
                    def ignore_if(key, value)
         | 
| 187 | 
            +
                      return true if key != 'get_file' && key != 'type'
         | 
| 188 | 
            +
             | 
| 189 | 
            +
                      return true unless value.kind_of?(String)
         | 
| 190 | 
            +
             | 
| 191 | 
            +
                      return true if key == 'type' &&
         | 
| 192 | 
            +
                                     !value.end_with?('.yaml', '.template')
         | 
| 193 | 
            +
             | 
| 194 | 
            +
                      false
         | 
| 195 | 
            +
                    end
         | 
| 196 | 
            +
             | 
| 197 | 
            +
                    # Returns the string baseurl of the given url.
         | 
| 198 | 
            +
                    def base_url_for_url(url)
         | 
| 199 | 
            +
                      parsed = URI(url)
         | 
| 200 | 
            +
                      parsed_dir = File.dirname(parsed.path)
         | 
| 201 | 
            +
                      url_join(parsed, parsed_dir)
         | 
| 202 | 
            +
                    end
         | 
| 203 | 
            +
             | 
| 204 | 
            +
                    def normalise_file_path_to_url(path)
         | 
| 205 | 
            +
                      # Nothing to do on URIs
         | 
| 206 | 
            +
                      return path if URI(path).scheme
         | 
| 207 | 
            +
             | 
| 208 | 
            +
                      path = File.absolute_path(path)
         | 
| 209 | 
            +
                      url_join('file:/', path)
         | 
| 210 | 
            +
                    end
         | 
| 211 | 
            +
             | 
| 212 | 
            +
                    def deep_copy(item)
         | 
| 213 | 
            +
                      return item if item.kind_of?(String)
         | 
| 214 | 
            +
             | 
| 215 | 
            +
                      YAML.safe_load(YAML.dump(item), [Date])
         | 
| 216 | 
            +
                    end
         | 
| 217 | 
            +
                  end
         | 
| 218 | 
            +
                end
         | 
| 219 | 
            +
              end
         | 
| 220 | 
            +
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,27 +1,27 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: fog-openstack
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.1. | 
| 4 | 
            +
              version: 0.1.23
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Matt Darby
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2018-01-15 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: fog-core
         | 
| 15 15 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 16 16 | 
             
                requirements:
         | 
| 17 | 
            -
                - - " | 
| 17 | 
            +
                - - "~>"
         | 
| 18 18 | 
             
                  - !ruby/object:Gem::Version
         | 
| 19 19 | 
             
                    version: '1.40'
         | 
| 20 20 | 
             
              type: :runtime
         | 
| 21 21 | 
             
              prerelease: false
         | 
| 22 22 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 23 23 | 
             
                requirements:
         | 
| 24 | 
            -
                - - " | 
| 24 | 
            +
                - - "~>"
         | 
| 25 25 | 
             
                  - !ruby/object:Gem::Version
         | 
| 26 26 | 
             
                    version: '1.40'
         | 
| 27 27 | 
             
            - !ruby/object:Gem::Dependency
         | 
| @@ -66,6 +66,20 @@ dependencies: | |
| 66 66 | 
             
                - - "~>"
         | 
| 67 67 | 
             
                  - !ruby/object:Gem::Version
         | 
| 68 68 | 
             
                    version: '1.6'
         | 
| 69 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 70 | 
            +
              name: coveralls
         | 
| 71 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 72 | 
            +
                requirements:
         | 
| 73 | 
            +
                - - ">="
         | 
| 74 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 75 | 
            +
                    version: '0'
         | 
| 76 | 
            +
              type: :development
         | 
| 77 | 
            +
              prerelease: false
         | 
| 78 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 79 | 
            +
                requirements:
         | 
| 80 | 
            +
                - - ">="
         | 
| 81 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 82 | 
            +
                    version: '0'
         | 
| 69 83 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 70 84 | 
             
              name: mime-types
         | 
| 71 85 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -122,20 +136,6 @@ dependencies: | |
| 122 136 | 
             
                - - ">="
         | 
| 123 137 | 
             
                  - !ruby/object:Gem::Version
         | 
| 124 138 | 
             
                    version: '0'
         | 
| 125 | 
            -
            - !ruby/object:Gem::Dependency
         | 
| 126 | 
            -
              name: rubyzip
         | 
| 127 | 
            -
              requirement: !ruby/object:Gem::Requirement
         | 
| 128 | 
            -
                requirements:
         | 
| 129 | 
            -
                - - "~>"
         | 
| 130 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 131 | 
            -
                    version: 0.9.9
         | 
| 132 | 
            -
              type: :development
         | 
| 133 | 
            -
              prerelease: false
         | 
| 134 | 
            -
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 135 | 
            -
                requirements:
         | 
| 136 | 
            -
                - - "~>"
         | 
| 137 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 138 | 
            -
                    version: 0.9.9
         | 
| 139 139 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 140 140 | 
             
              name: shindo
         | 
| 141 141 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -245,7 +245,6 @@ files: | |
| 245 245 | 
             
            - examples/volume/backups.rb
         | 
| 246 246 | 
             
            - examples/workflow/workflow-examples.rb
         | 
| 247 247 | 
             
            - fog-openstack.gemspec
         | 
| 248 | 
            -
            - gemfiles/Gemfile-1.9
         | 
| 249 248 | 
             
            - lib/fog/baremetal/openstack.rb
         | 
| 250 249 | 
             
            - lib/fog/baremetal/openstack/models/chassis.rb
         | 
| 251 250 | 
             
            - lib/fog/baremetal/openstack/models/chassis_collection.rb
         | 
| @@ -1043,6 +1042,7 @@ files: | |
| 1043 1042 | 
             
            - lib/fog/orchestration/openstack/requests/show_stack_details.rb
         | 
| 1044 1043 | 
             
            - lib/fog/orchestration/openstack/requests/update_stack.rb
         | 
| 1045 1044 | 
             
            - lib/fog/orchestration/openstack/requests/validate_template.rb
         | 
| 1045 | 
            +
            - lib/fog/orchestration/util/recursive_hot_file_loader.rb
         | 
| 1046 1046 | 
             
            - lib/fog/planning/openstack.rb
         | 
| 1047 1047 | 
             
            - lib/fog/planning/openstack/models/plan.rb
         | 
| 1048 1048 | 
             
            - lib/fog/planning/openstack/models/plans.rb
         | 
| @@ -1352,7 +1352,7 @@ required_ruby_version: !ruby/object:Gem::Requirement | |
| 1352 1352 | 
             
              requirements:
         | 
| 1353 1353 | 
             
              - - ">="
         | 
| 1354 1354 | 
             
                - !ruby/object:Gem::Version
         | 
| 1355 | 
            -
                  version:  | 
| 1355 | 
            +
                  version: 2.1.0
         | 
| 1356 1356 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 1357 1357 | 
             
              requirements:
         | 
| 1358 1358 | 
             
              - - ">="
         | 
    
        data/gemfiles/Gemfile-1.9
    DELETED
    
    | @@ -1,22 +0,0 @@ | |
| 1 | 
            -
            source "https://rubygems.org"
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            group :development, :test do
         | 
| 4 | 
            -
              gem "fog-core",        ">= 1.35"
         | 
| 5 | 
            -
              gem "fog-json",        ">= 1.0"
         | 
| 6 | 
            -
              gem "fog-xml",         ">= 0.1"
         | 
| 7 | 
            -
              gem "ipaddress",       ">= 0.8"
         | 
| 8 | 
            -
              gem "bundler",         "~> 1.6"
         | 
| 9 | 
            -
              gem "mime-types",      "2.6.2"
         | 
| 10 | 
            -
              gem "nokogiri",        "< 1.7.0"
         | 
| 11 | 
            -
              gem "rake",            "~> 10.0"
         | 
| 12 | 
            -
              gem "rubocop",         "< 0.42"
         | 
| 13 | 
            -
              gem "rubyzip",         "~> 0.9.9"
         | 
| 14 | 
            -
              gem "shindo",          "~> 0.3"
         | 
| 15 | 
            -
              gem "minitest"
         | 
| 16 | 
            -
              gem "vcr"
         | 
| 17 | 
            -
              gem "webmock",         "~> 1.24.6"
         | 
| 18 | 
            -
              gem "json",            "< 2.0"
         | 
| 19 | 
            -
            # TODO: remove when https://github.com/fog/fog-openstack/issues/202 is fixed
         | 
| 20 | 
            -
            #  gem "coveralls",       "< 0.8.15"
         | 
| 21 | 
            -
              gem "public_suffix",    "~> 1.4.6"
         | 
| 22 | 
            -
            end
         |