class GeoEngineer::Environment

An Environment is a group of projects, resources and attributes, build to create a terraform file. The goal of GeoEngineer is to build an environment that can be created.

An environment has resources, has arbitrary attributes, validations and lifecycle hooks

Attributes

name[R]

Public Class Methods

new(name, &block) click to toggle source
# File lib/geoengineer/environment.rb, line 56
def initialize(name, &block)
  @name = name
  @outputs = []
  @providers = []
  self.send("#{name}?=", true) # e.g. staging?
  instance_exec(self, &block) if block_given?
end

Public Instance Methods

all_resources() click to toggle source
# File lib/geoengineer/environment.rb, line 97
def all_resources
  [resources, all_template_resources, all_project_resources].flatten
end
codified_resources(type) click to toggle source

This method looks into AWS for resources that are not yet codified

# File lib/geoengineer/environment.rb, line 194
def codified_resources(type)
  # managed resources have a remote resource
  res = self.resources_of_type(type).select { |r| !r.remote_resource.nil? }
  res.sort_by(&:terraform_name)
end
depends_on(res) click to toggle source
# File lib/geoengineer/environment.rb, line 115
def depends_on(res)
  all_attributes = [res.attributes.values]
  all_attributes
    .concat(res.subresources.map { |sr| sr.attributes.values })
    .map { |attr| extract_dependencies(attr) }
    .flatten
    .compact
    .uniq
end
extract_dependencies(x) click to toggle source

DOT Methods Given an attribute it tries to identify a dependency and return it

# File lib/geoengineer/environment.rb, line 103
def extract_dependencies(x)
  return x.map { |y| extract_dependencies(y) }.flatten if x.is_a? Array
  return [x] if x.is_a?(GeoEngineer::Resource)

  if x.is_a?(String)
    res = find_resource_by_ref(x)
    return [res] if res
  end

  []
end
find_provider(id_alias) click to toggle source
# File lib/geoengineer/environment.rb, line 87
def find_provider(id_alias)
  @providers.find { |p| p.terraform_id == id_alias }
end
json_resources() click to toggle source
# File lib/geoengineer/environment.rb, line 165
def json_resources
  all_resources.each_with_object({}) do |r, c|
    c[r.type] ||= {}
    c[r.type][r.id] = r.to_terraform_json
    c
  end
end
output(id, value, &block) click to toggle source
# File lib/geoengineer/environment.rb, line 91
def output(id, value, &block)
  output = GeoEngineer::Output.new(id, value, &block)
  @outputs << output
  output
end
project(org, name, &block) click to toggle source
# File lib/geoengineer/environment.rb, line 64
def project(org, name, &block)
  project = create_project(org, name, &block)
  supported_environments = [project.environments].flatten
  # do not add the project if the project is not supported by this environment
  return NullObject.new unless supported_environments.include?(@name)

  project
end
provider(id, &block) click to toggle source
# File lib/geoengineer/environment.rb, line 81
def provider(id, &block)
  provider = GeoEngineer::Provider.new(id, &block)
  @providers << provider
  provider
end
resource(type, id, &block) click to toggle source
# File lib/geoengineer/environment.rb, line 73
def resource(type, id, &block)
  return find_resource(type, id) unless block_given?

  resource = create_resource(type, id, &block)
  resource.environment = self
  resource
end
to_dot() click to toggle source
# File lib/geoengineer/environment.rb, line 125
def to_dot
  str = ["digraph {", projects.values.map(&:to_dot)]
  all_resources.each do |res|
    str << depends_on(res).map { |r| "  #{res.to_ref.inspect} -> #{r.to_ref.inspect}" }
  end
  str << " }"
  str.join("\n")
end
to_terraform() click to toggle source

Terraform Methods

# File lib/geoengineer/environment.rb, line 135
def to_terraform
  # Force preventing the destruction of any resource unless explicitly set
  # Hopefully this will stop accidentally the environment
  unless self.allow_destroy
    all_resources.each { |r|
      r.lifecycle {} unless r.lifecycle
      r.lifecycle.prevent_destroy = true
    }
  end

  tf_resources = all_resources.map(&:to_terraform)
  tf_resources += @providers.compact.map(&:to_terraform)
  tf_resources += @outputs.compact.map(&:to_terraform)
  tf_resources.join("\n\n")
end
to_terraform_json() click to toggle source
# File lib/geoengineer/environment.rb, line 151
def to_terraform_json
  unless self.allow_destroy
    all_resources.each { |r|
      r.lifecycle {} unless r.lifecycle
      r.lifecycle.prevent_destroy = true
    }
  end

  h = { resource: json_resources }
  h[:output] = @outputs.map(&:to_terraform_json) unless @outputs.empty?
  h[:provider] = @providers.map(&:to_terraform_json) unless @providers.empty?
  h
end
to_terraform_state() click to toggle source
# File lib/geoengineer/environment.rb, line 173
def to_terraform_state
  reses = all_resources.select(&:_terraform_id) # _terraform_id must not be nil

  reses = Parallel.map(reses, { in_threads: Parallel.processor_count }) do |r|
    { "#{r.type}.#{r.id}" => r.to_terraform_state() }
  end.reduce({}, :merge)

  {
    version: 1,
    serial: 1,
    modules: [
      {
        path: [:root],
        outputs: {},
        resources: reses
      }
    ]
  }
end
uncodified_resources(type) click to toggle source
# File lib/geoengineer/environment.rb, line 200
def uncodified_resources(type)
  # unmanaged resources have a remote resource without local_resource
  clazz = self.class.get_resource_class_from_type(type)
  res = clazz.fetch_remote_resources(nil).select { |r| r.local_resource.nil? }
  res.sort_by(&:terraform_name)
end