lib/google/compute/client.rb in knife-google-1.2.0 vs lib/google/compute/client.rb in knife-google-1.3.1

- old
+ new

@@ -30,32 +30,37 @@ def initialize(authorization, project, credential_file) api_client = Google::APIClient.new(:application_name => 'knife-google', :application_version => Knife::Google::VERSION) api_client.authorization = authorization api_client.auto_refresh_token = true @project = project - @credential_file = credential_file - @dispatcher = APIDispatcher.new(:project=>project,:api_client=>api_client) + if !credential_file + @credential_file = File.expand_path(DEFAULT_FILE) + else + @credential_file = File.expand_path(credential_file) + end + @dispatcher = APIDispatcher.new(:project=>project, :api_client=>api_client, :credential_file=>@credential_file) end def self.from_json(filename = nil) filename ||= File.expand_path(DEFAULT_FILE) begin - credential_data = MultiJson.load(File.read(filename)) + credential_data = MultiJson.load(File.read(filename)) rescue $stdout.print "Error reading CREDENTIAL_FILE, please run 'knife google setup'\n" exit 1 end authorization = Signet::OAuth2::Client.new(credential_data) self.new(authorization, credential_data['project'], filename) end def self.setup - $stdout.print "Enter project ID (not name or number): " + credential_file ||= File.expand_path(DEFAULT_FILE) + $stdout.print "Enter Project ID (ex: my-gce-project): " project = $stdin.gets.chomp - $stdout.print "Enter client id: " + $stdout.print "Enter Client ID (ex: 123abc4.apps.googleusercontent.com): " client_id = $stdin.gets.chomp - $stdout.print "Enter client secret: " + $stdout.print "Enter Client secret: " client_secret = $stdin.gets.chomp authorization_uri = "https://accounts.google.com/o/oauth2/auth" token_credential_uri ="https://accounts.google.com/o/oauth2/token" scope = ["https://www.googleapis.com/auth/compute", "https://www.googleapis.com/auth/compute.readonly", @@ -80,34 +85,37 @@ begin api_client.authorization.fetch_access_token! rescue Faraday::Error::ConnectionFailed => e raise ConnectionFail, - "The SSL certificates validation may not configured for this system. Please refer README to configured SSL certificates validation"\ - if e.message.include? "SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed" - else - access_token = api_client.authorization.access_token - refresh_token = api_client.authorization.refresh_token - id_token = api_client.authorization.id_token - expires_in = api_client.authorization.expires_in - issued_at = api_client.authorization.issued_at.to_s - if !@credential_file - filepath = File.expand_path(DEFAULT_FILE) - else - filepath = File.expand_path(@credential_file) - end - File.open(filepath,'w+') do |f| - f.write(MultiJson.dump({"authorization_uri" => authorization_uri, - "token_credential_uri"=>"https://accounts.google.com/o/oauth2/token", - "scope"=>scope,"redirect_uri"=>redirect_uri, "client_id"=>client_id, - "client_secret"=>client_secret, "access_token"=>access_token, - "expires_in"=>expires_in,"refresh_token"=> refresh_token, "id_token"=>id_token, - "issued_at"=>issued_at,"project"=>project }, :pretty=>true)) - end + "The SSL certificates validation may not configured for this system. Please refer README to configured SSL certificates validation" end + save_credentials(project, api_client, credential_file) end + def self.save_credentials(project, api_client, credential_file) + scope = api_client.authorization.scope + client_id = api_client.authorization.client_id + client_secret = api_client.authorization.client_secret + redirect_uri = api_client.authorization.redirect_uri + authorization_uri = "https://accounts.google.com/o/oauth2/auth" + access_token = api_client.authorization.access_token + refresh_token = api_client.authorization.refresh_token + id_token = api_client.authorization.id_token + expires_in = api_client.authorization.expires_in + issued_at = api_client.authorization.issued_at.to_s + + File.open(credential_file,'w+') do |f| + f.write(MultiJson.dump({"authorization_uri" => authorization_uri, + "token_credential_uri"=>"https://accounts.google.com/o/oauth2/token", + "scope"=>scope,"redirect_uri"=>redirect_uri, "client_id"=>client_id, + "client_secret"=>client_secret, "access_token"=>access_token, + "expires_in"=>expires_in,"refresh_token"=> refresh_token, "id_token"=>id_token, + "issued_at"=>issued_at,"project"=>project }, :pretty=>true)) + end + end + def projects ResourceCollection.new(:resource_class => Google::Compute::Project, :dispatcher => @dispatcher) end def disks @@ -157,15 +165,16 @@ def snapshots CreatableResourceCollection.new(:resource_class => Google::Compute::Snapshot, :dispatcher=>@dispatcher) end class APIDispatcher - attr_reader :project, :api_client + attr_reader :project, :api_client, :credential_file def initialize(opts) @project= opts[:project] @api_client = opts[:api_client] + @credential_file = opts[:credential_file] end def compute @compute ||= @api_client.discovered_api('compute','v1') end @@ -184,9 +193,15 @@ error_code = response["error"]["code"] if error_code == 404 raise ResourceNotFound, result.response.body elsif error_code == 400 raise BadRequest, result.response.body + elsif error_code == 401 + # ok, our credentials aren't working, we need + # to get a new refresh token and retry + @api_client.authorization.fetch_access_token! + Client.save_credentials(@project, @api_client, @credential_file) + return dispatch(opts) else raise BadRequest, result.response.body end end return MultiJson.load(result.response.body) unless result.response.body.nil?