Class: Terraspace::Terraform::Api::Http

Inherits:
Object
  • Object
show all
Extended by:
Memoist
Includes:
Util::Logging
Defined in:
lib/terraspace/terraform/api/http.rb

Constant Summary collapse

API =
ENV['TERRAFORM_API'] || 'https://app.terraform.io/api/v2'

Instance Method Summary collapse

Methods included from Util::Logging

#logger

Instance Method Details

#build_request(klass, url, data = {}) ⇒ Object



35
36
37
38
39
40
41
42
43
44
# File 'lib/terraspace/terraform/api/http.rb', line 35

def build_request(klass, url, data={})
  req = klass.new(url) # url includes query string and uri.path does not, must used url
  set_headers!(req)
  if [Net::HTTP::Delete, Net::HTTP::Patch, Net::HTTP::Post, Net::HTTP::Put].include?(klass)
    text = JSON.dump(data)
    req.body = text
    req.content_length = text.bytesize
  end
  req
end

#delete(path, data = {}) ⇒ Object



22
23
24
# File 'lib/terraspace/terraform/api/http.rb', line 22

def delete(path, data={})
  request(Net::HTTP::Delete, path, data)
end

#get(path) ⇒ Object



10
11
12
# File 'lib/terraspace/terraform/api/http.rb', line 10

def get(path)
  request(Net::HTTP::Get, path)
end

#http(url) ⇒ Object



51
52
53
54
55
56
57
# File 'lib/terraspace/terraform/api/http.rb', line 51

def http(url)
  uri = URI(url)
  http = Net::HTTP.new(uri.host, uri.port)
  http.open_timeout = http.read_timeout = 30
  http.use_ssl = true if uri.scheme == 'https'
  http
end

#load_json(res) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
# File 'lib/terraspace/terraform/api/http.rb', line 65

def load_json(res)
  if res.code == "200"
    JSON.load(res.body)
  else
    if ENV['TERRASPACE_DEBUG_API']
      puts "Error: Non-successful http response status code: #{res.code}"
      puts "headers: #{res.each_header.to_h.inspect}"
    end
    nil
  end
end

#patch(path, data = {}) ⇒ Object



18
19
20
# File 'lib/terraspace/terraform/api/http.rb', line 18

def patch(path, data={})
  request(Net::HTTP::Patch, path, data)
end

#post(path, data = {}) ⇒ Object



14
15
16
# File 'lib/terraspace/terraform/api/http.rb', line 14

def post(path, data={})
  request(Net::HTTP::Post, path, data)
end

#request(klass, path, data = {}) ⇒ Object

Always translate raw json response to ruby Hash



27
28
29
30
31
32
33
# File 'lib/terraspace/terraform/api/http.rb', line 27

def request(klass, path, data={})
  url = url(path)
  http = http(url)
  req = build_request(klass, url, data)
  resp = http.request(req) # send request
  load_json(resp)
end

#set_headers!(req) ⇒ Object



46
47
48
49
# File 'lib/terraspace/terraform/api/http.rb', line 46

def set_headers!(req)
  req['Authorization'] = "Bearer #{token}"
  req['Content-Type'] = "application/vnd.api+json"
end

#tokenObject



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
# File 'lib/terraspace/terraform/api/http.rb', line 77

def token
  token ||= ENV['TERRAFORM_TOKEN']
  return token if token

  creds_path = "#{ENV['HOME']}/.terraform.d/credentials.tfrc.json"
  if File.exist?(creds_path)
    data = JSON.load(IO.read(creds_path))
    token = data.dig('credentials', 'app.terraform.io', 'token')
  end

  # Note only way to get here is to bypass init. Example:
  #
  #     terraspace up demo --no-init
  #
  unless token
    logger.error "ERROR: Unable to not find a Terraform token. A Terraform token is needed for Terraspace to call the Terraform API.".color(:red)
    logger.error <<~EOL
      Here are some ways to provide the Terraform token:

          1. By running: terraform login
          2. With an env variable: export TERRAFORM_TOKEN=xxx

      Please configure a Terraform token and try again.
    EOL
    exit 1
  end
  token
end

#url(path) ⇒ Object

API does not include the /. IE: app.terraform.io/api/v2



61
62
63
# File 'lib/terraspace/terraform/api/http.rb', line 61

def url(path)
  "#{API}/#{path}"
end