<commit_before>package terraformer

import (
	"bytes"
	"koding/kites/terraformer/kodingcontext"

	"github.com/hashicorp/terraform/terraform"
	"github.com/koding/kite"
	"github.com/koding/logging"
	"github.com/koding/metrics"
)

var (
	Name    = "terraformer"
	Version = "0.0.1"
)

type Terraformer struct {
	Log logging.Logger

	Metrics *metrics.DogStatsD

	// Enable debug mode
	Debug bool

	Context *kodingcontext.Context
}

type TerraformRequest struct {
	Content   string
	Variables map[string]string
}

func New() *Terraformer {
	return &Terraformer{}
}

func (t *Terraformer) Apply(r *kite.Request) (interface{}, error) {
	c := t.Context.Clone()
	defer c.Close()

	plan, err := t.plan(c, r)
	if err != nil {
		return nil, err
	}

	copts := c.TerraformContextOptsWithPlan(plan)
	ctx := terraform.NewContext(copts)
	state, err := ctx.Apply()
	if err != nil {
		return nil, err
	}

	return state, nil
}

func (t *Terraformer) Destroy(r *kite.Request) (interface{}, error) {
	c := t.Context.Clone()
	defer c.Close()

	return nil, nil
}

func (t *Terraformer) Plan(r *kite.Request) (interface{}, error) {
	c := t.Context.Clone()
	defer c.Close()

	plan, err := t.plan(c, r)
	if err != nil {
		return nil, err
	}

	return plan, nil
}

func (t *Terraformer) plan(c *kodingcontext.Context, r *kite.Request) (*terraform.Plan, error) {
	args := TerraformRequest{}
	if err := r.Args.One().Unmarshal(&args); err != nil {
		return nil, err
	}

	c.Variables = args.Variables

	plan, err := c.Plan(bytes.NewBufferString(args.Content))
	if err != nil {
		return nil, err
	}

	return plan, nil
}<commit_msg>Terraform: implement destroy function<commit_after>package terraformer

import (
	"bytes"
	"koding/kites/terraformer/kodingcontext"

	"github.com/hashicorp/terraform/terraform"
	"github.com/koding/kite"
	"github.com/koding/logging"
	"github.com/koding/metrics"
)

var (
	Name    = "terraformer"
	Version = "0.0.1"
)

type Terraformer struct {
	Log logging.Logger

	Metrics *metrics.DogStatsD

	// Enable debug mode
	Debug bool

	Context *kodingcontext.Context
}

type TerraformRequest struct {
	Content   string
	Variables map[string]string
}

func New() *Terraformer {
	return &Terraformer{}
}

func (t *Terraformer) Apply(r *kite.Request) (interface{}, error) {
	c := t.Context.Clone()
	defer c.Close()

	ctx, err := t.context(c, r, false)
	if err != nil {
		return nil, err
	}

	state, err := ctx.Apply()
	if err != nil {
		return nil, err
	}

	return state, nil
}

func (t *Terraformer) Destroy(r *kite.Request) (interface{}, error) {
	c := t.Context.Clone()
	defer c.Close()

	//
	// plan first with destroy option
	//
	plan, err := t.plan(c, r, true)
	if err != nil {
		return nil, err
	}

	//
	// create terraform context options from plan
	//
	copts := c.TerraformContextOptsWithPlan(plan)

	copts.Destroy = true // this is the key point

	// create terraform context with its options
	ctx := terraform.NewContext(copts)

	//
	// apply the change
	//
	state, err := ctx.Apply()
	if err != nil {
		return nil, err
	}

	return state, nil
}

func (t *Terraformer) Plan(r *kite.Request) (interface{}, error) {
	c := t.Context.Clone()
	defer c.Close()

	plan, err := t.plan(c, r, false)
	if err != nil {
		return nil, err
	}

	return plan, nil
}

func (t *Terraformer) context(
	c *kodingcontext.Context,
	r *kite.Request,
	destroy bool,
) (*terraform.Context, error) {
	// get the plan
	plan, err := t.plan(c, r, destroy)
	if err != nil {
		return nil, err
	}

	// create terraform context options from plan
	copts := c.TerraformContextOptsWithPlan(plan)

	// create terraform context with its options
	ctx := terraform.NewContext(copts)

	return ctx, nil
}

func (t *Terraformer) plan(
	c *kodingcontext.Context,
	r *kite.Request,
	destroy bool,
) (*terraform.Plan, error) {
	args := TerraformRequest{}
	if err := r.Args.One().Unmarshal(&args); err != nil {
		return nil, err
	}

	c.Variables = args.Variables

	plan, err := c.Plan(
		bytes.NewBufferString(args.Content),
		destroy,
	)
	if err != nil {
		return nil, err
	}

	return plan, nil
}
{'fraction_non_alphanumeric': 0.14289245982694684, 'fraction_numerical': 0.0014833127317676143, 'mean_word_length': 3.5977272727272727, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6878501', 'n_tokens_mistral': 1549, 'n_tokens_neox': 1523, 'n_words': 398}