Class: RightScale::CookbookRepoRetriever

Inherits:
Object
  • Object
show all
Defined in:
lib/instance/cook/cookbook_repo_retriever.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(repose_root, dev_cookbooks) ⇒ CookbookRepoRetriever

Initialize…

Parameters

repose_root (String)

root of all repose downloaded cookbooks

dev_cookbooks (Hash)

collection of repos to be checked out see RightScale::DevRepositories for hash content



73
74
75
76
77
78
79
# File 'lib/instance/cook/cookbook_repo_retriever.rb', line 73

def initialize(repose_root, dev_cookbooks)
  @checkout_root  = AgentConfig.dev_cookbook_checkout_dir
  @repose_root    = repose_root
  @dev_cookbooks  = (dev_cookbooks.nil? || dev_cookbooks.repositories.nil?) ? {} : dev_cookbooks.repositories
  @scraper        = RightScraper::Scraper.new(:kind => :cookbook, :basedir => @checkout_root)
  @registered_checkouts = {}
end

Instance Attribute Details

#checkout_rootObject (readonly)

Returns the value of attribute checkout_root.



28
29
30
# File 'lib/instance/cook/cookbook_repo_retriever.rb', line 28

def checkout_root
  @checkout_root
end

Class Method Details

.to_scraper_hash(dev_repo) ⇒ Object

Maps the given DevRepository to a has that can be consumed by the RightScraper gem TODO: May make sense for this to a member of the DevRepository class as an instance method.

Also, may want to take a version as a parameter in the future (or not...).

Parameters

dev_repo (DevRepository)

core representation of a resource repository

Returns

(Hash)
:repo_type (Symbol)

Type of repository: one of :git, :svn, :download or :local

* :git denotes a 'git' repository that should be retrieved via 'git clone'
* :svn denotes a 'svn' repository that should be retrieved via 'svn checkout'
* :download denotes a tar ball that should be retrieved via HTTP GET (HTTPS if uri starts with https://)
* :local denotes cookbook that is already local and doesn't need to be retrieved
:url (String)

URL to repository (e.g. git://github.com/opscode/chef-repo.git)

:tag (String)

git commit or svn branch that should be used to retrieve repository

Optional, use 'master' for git and 'trunk' for svn if tag is nil.
Not used for raw repositories.
:cookbooks_path (Array)

Path to cookbooks inside repostory

Optional (use location of repository as cookbook path if nil)
:first_credential (String)

Either the Private SSH key used to retrieve git repositories, or the Username used to retrieve svn and raw repositories

:second_credential (String)

Password used to retrieve svn and raw repositories



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/instance/cook/cookbook_repo_retriever.rb', line 52

def self.to_scraper_hash(dev_repo)
  repo = {}
  repo[:repo_type]            = dev_repo.repo_type.to_sym unless dev_repo.repo_type.nil?
  repo[:url]                  = dev_repo.url
  repo[:tag]                  = dev_repo.tag
  repo[:resources_path]       = dev_repo.cookbooks_path
  if !dev_repo.ssh_key.nil?
    repo[:first_credential]   = dev_repo.ssh_key
  elsif !(dev_repo.username.nil? && dev_repo.password.nil?)
    repo[:first_credential]   = dev_repo.username
    repo[:second_credential]  = dev_repo.password
  end

  repo
end

Instance Method Details

#checkout_cookbook_repos(&callback) ⇒ Object

Checkout the given repo and link each dev cookbook to it’s matching repose path

Parameters

callback (Proc)

to be called for each repo checked out see RightScraper::Scraper.scrape for details

Return

true


132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/instance/cook/cookbook_repo_retriever.rb', line 132

def checkout_cookbook_repos(&callback)
  @dev_cookbooks.each_pair do |repo_sha, dev_repo|
    repo = self.class.to_scraper_hash(dev_repo)

    # get the root dir this repo should be, or was, checked out to
    repo_dir = @scraper.repo_dir(repo)

    if File.directory?(repo_dir)
      # repo was already checked out on this machine; leave it alone
      # synthesize a scraper callback so our progress listener knows what's up
      if callback
        callback.call(:commit, :initialize, "Skipping checkout -- repository already exists in #{repo_dir}", nil)
      end
      @registered_checkouts[repo_sha] = repo_dir
    else
      # repo wasn't checked out successfully yet; check it out now
      success = false
      begin
        success = @scraper.scrape(repo, &callback)
      ensure
        if success
          @registered_checkouts[repo_sha] = repo_dir
        else
          # nuke the repo dir if checkout fails, so we try again next time
          FileUtils.rm_rf(repo_dir) unless success

          # scraper logger is an odd duck, so just transfer any errors to
          # the normal logger.
          @scraper.errors.each { |e| ::RightScale::Log.error(e) }
          ::RightScale::Log.error("Failed to checkout from #{repo[:url].inspect}")
        end
      end
    end
  end
  true
end

#has_cookbooks?Boolean

Are there any cookbooks to be checked out?

Returns

true if there are cookbooks to be checked out, false otherwise

Returns:

  • (Boolean)


85
86
87
# File 'lib/instance/cook/cookbook_repo_retriever.rb', line 85

def has_cookbooks?
  !@dev_cookbooks.empty?
end

#is_checked_out?(repo_sha) ⇒ Boolean

Was the cookbook checked out?

Parameters

repo_sha (String)

unique identifier of the cookbook repository

Returns

true if the given repo is checekd out

Returns:

  • (Boolean)


110
111
112
# File 'lib/instance/cook/cookbook_repo_retriever.rb', line 110

def is_checked_out?(repo_sha)
  !!repo_dir_for(repo_sha)
end

Creates a symlink from the checked out cookbook to the expected repose download location

Parameters

repo_sha (String)

unique identifier of the cookbook repository

position (String)

repo relative ppath of the cookbook

Returns

true if link was created, false otherwise



177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/instance/cook/cookbook_repo_retriever.rb', line 177

def link(repo_sha, position)
  # symlink to the checked out cookbook only if it was actually checked out
  if repo_dir = @registered_checkouts[repo_sha]
    checkout_path = CookbookPathMapping.checkout_path(repo_dir, position)
    raise ArgumentError.new("Missing directory cannot be linked: #{checkout_path}") unless File.directory?(checkout_path)
    repose_path   = CookbookPathMapping.repose_path(@repose_root, repo_sha, position)
    FileUtils.mkdir_p(File.dirname(repose_path))
    Platform.filesystem.create_symlink(checkout_path, repose_path)
    return true
  end
  false
end

#repo_dir_for(repo_sha) ⇒ String

Checkout directory for given repository hash.

Parameters

Return

Parameters:

  • repo_sha (String)

    for lookup

Returns:

  • (String)

    checked-out directory or nil



121
122
123
# File 'lib/instance/cook/cookbook_repo_retriever.rb', line 121

def repo_dir_for(repo_sha)
  @registered_checkouts[repo_sha]
end

#should_be_linked?(repo_sha, position) ⇒ Boolean

Should there be a link created for this cookbook?

Parameters

repo_sha (String)

unique identifier of the cookbook repository

position (String)

repo relative ppath of the cookbook

Returns

true if there is a cookbook in the given repo that should be checekd out

Returns:

  • (Boolean)


97
98
99
100
101
# File 'lib/instance/cook/cookbook_repo_retriever.rb', line 97

def should_be_linked?(repo_sha, position)
  @dev_cookbooks.has_key?(repo_sha) &&
  @dev_cookbooks[repo_sha].positions &&
  @dev_cookbooks[repo_sha].positions.detect { |dev_position| dev_position.position == position }
end