lib/pangea/processor.rb



require 'terraform-synthesizer'
require 'pangea/renderer'
require 'pangea/config'
require 'pangea/utils'
require 'aws-sdk-s3'

module Pangea
  # ingests files and builds a context
  # for rendering Pangea programming
  module Processor
    class << self
      def register_action(action)
        permitted_actions = %i[plan apply show destroy]
        @action = action if permitted_actions.map(&:to_s).include?(action.to_s)
      end

      def process(content)
        instance_eval(content)
      end

      def synthesizer
        @synthesizer ||= TerraformSynthesizer.new
      end

      def config
        @config ||= Pangea::Utils.symbolize(
          Pangea::Config.config
        )
      end

      def namespace
        @namespace ||= ENV.fetch('PANGEA_NAMESPACE')
      end

      def s3
        @s3 = Aws::S3::Client.new
      end

      def bin
        'tofu'
      end

      def namespace_config
        sns = ''
        config[:namespaces].each_key do |ns|
          sns = config[:namespaces][ns] if ns.to_s.eql?(namespace.to_s)
        end
        @namespace_config ||= sns
      end

      def template(name, &block)
        prefix = "#{namespace}/#{name}"
        pangea_home = %(#{Dir.home}/.pangea/#{namespace})
        local_cache = File.join(pangea_home, prefix)
        `mkdir -p #{local_cache}` unless Dir.exist?(local_cache)
        synthesizer.synthesize(&block)
        sns = namespace_config
        unless synthesizer.synthesis[:terraform]
          synthesizer.synthesize do
            terraform do
              backend(
                s3: {
                  key: prefix,
                  dynamodb_table: sns[:state][:config][:lock].to_s,
                  bucket: sns[:state][:config][:bucket].to_s,
                  region: sns[:state][:config][:region].to_s,
                  encrypt: true
                }
              )
            end
          end
        end
        File.write(
          File.join(
            local_cache, 'main.tf.json'
          ), JSON[synthesizer.synthesis]
        )

        system("cd #{local_cache} && #{bin} init -input=false") unless File.exist?(
          File.join(
            local_cache,
            '.terraform.lock.hcl'
          )
        )

        if @action.to_s == 'apply'
          system "cd #{local_cache} && #{bin} apply -auto-approve"
        elsif @action.to_s == 'plan'
          system "cd #{local_cache} && #{bin} plan"
        elsif @action.to_s == 'destroy'
          system "cd #{local_cache} && #{bin} destroy -auto-approve"
        end

        template = Pangea::Utils.symbolize(
          JSON[File.read(
            File.join(local_cache, 'main.tf.json')
          )]
        )
        puts JSON.pretty_generate(template) if @action.to_s.eql?('show')
        { template: template }
      end
    end
  end
end