Class: Puppet::GoogleAPI Private

Inherits:
Object
  • Object
show all
Defined in:
lib/puppet/google_api.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

A helper to capture logic around authentication and interaction with the Google API, especially around authentication with the OAuth2 system.

Constant Summary collapse

StandardImageProjects =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

The list of “standard” projects to search for images when hunting by name; the Google supplied images live in these.

['debian-cloud', 'centos-cloud']
StandardKernelProjects =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

The list of “standard” projects to search for kernels when hunting by name; the Google supplied kernels live in these.

['google']

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(client_id = nil, client_secret = nil) ⇒ GoogleAPI

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Note:

you are under no obligation to supply a client id or secret while

Create a new instance; this will implicitly authorize if required, or otherwise refresh the access token. It makes state changes in the rest of the system – potentially storing the refresh token in the statedir, or updating cached data about the token for other clients.

password-equivalent authorization, we need to make sure that we treat the file content as atomic, as well as secure, against cross-process activity.

policy for handling on-disk storage of tokens, since no other guidance was given by Google documentation. No effort has been made to, eg, merge partial updates to authentication state, etc.

the registration / auth query process if that is required

the registration / auth query process if that is required.

setting this up and, in most cases, you probably shouldn’t supply them. If a previous set were given we will have them stored away in our state supply as required – and if not, the user should call ‘register` at the face level and provide them. Don’t routinely supply these data.

Parameters:

  • client_id (String) (defaults to: nil)

    the (optional) client ID to use during

  • client_secret (String) (defaults to: nil)

    the (optional) client secret to use during



44
45
46
47
48
49
50
51
# File 'lib/puppet/google_api.rb', line 44

def initialize(client_id = nil, client_secret = nil)
  # First, load our state from disk if it is available.
  load_state!

  # ...and now try and authenticate with the server; this will request
  # authorization if required.
  authenticate!(client_id, client_secret)
end

Class Method Details

.hash_to_human_s(hash) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

TODO:

danielp 2013-09-16: I don’t like putting this here, but there

A helper to render a hash as human-focused text

doesn’t seem to be anywhere better, and Puppet doesn’t offer the capability. The default behaviour is “render as a human-hostile JSON string”, so that won’t do either. Oh, well.



122
123
124
125
126
127
128
# File 'lib/puppet/google_api.rb', line 122

def self.hash_to_human_s(hash)
  keylen = hash.keys.map{|k| k.to_s.length}.max
  hash.map do |key, value|
    key.to_s.rjust(keylen) + ': ' +
      value.to_s.gsub("\n", "\n#{' ' * (keylen + 2)}")
  end.join("\n")
end

Instance Method Details

#computeObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



111
112
113
# File 'lib/puppet/google_api.rb', line 111

def compute
  @compute ||= Puppet::GoogleAPI::Compute.new(self)
end

#discover(name, version) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



53
54
55
56
57
58
59
60
61
62
63
# File 'lib/puppet/google_api.rb', line 53

def discover(name, version)
  # @todo danielp 2013-09-13: we should cache the discovery document and
  # reuse it if it is fresh enough here; see
  # https://code.google.com/p/google-api-ruby-client/#APIs_Discovery_Service
  # for an example of the `register_discovery_document`; basically, cache
  # the "discovery document" hash to disk, and feed it through that.
  #
  # Right now we take the hit of a full HTTP fetch for every discovery which
  # is going to be heavier and slower than we ultimately want in production.
  client.discovered_api(name, version)
end

#execute(method, parameters = {}, body = nil) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/puppet/google_api.rb', line 65

def execute(method, parameters = {}, body = nil)
  # We have to do our own handling, as the execute! method -- which throws
  # great errors most of the time -- doesn't have anything to support 401
  # specially, and worse, doesn't have suitable hooks to allow us to stash
  # away our auth state if and only if it changed.
  args = {
    :api_method  => method,
    :parameters  => parameters,
    :body_object => body
  }
  result = client.execute(args)
  if result.status == 401     # reauthenticate and retry
    authenticate!
    execute(method, parameters)
  elsif result.status != 200
    # @todo danielp 2013-09-17: I am thinking that maybe a 404 result should
    # return either an empty array (for convenience in punning) or nil,
    # since that is a more "normal" failure than any of the alternatives...
    raise "#{method} failed #{result.status}: #{result.error_message || 'unknown error'}"
  end

  # We return the data content; that includes support for fetching further
  # pages, which we handle here, returning an array of one or more bodies to
  # the caller.
  if result.data.respond_to?('next_page_token')
    # We might have multiple pages of results, collect them all, and return
    # them in an array of multiple items.  Since they potentially have
    # specialized item storage formats by type, we can't generically do
    # anything to vivify the final object format.
    page = result.data
    results = []
    while page do
      results << page
      page = page.next_page_token ? page.next_page : nil
    end
    results
  else
    # Just return the single result, in an array, to match the API with the
    # paged data above.
    #
    # @todo danielp 2013-09-16: it isn't clear this is needed, since we
    # already need specialized knowledge in the caller, but ...
    [result.data]
  end
end