func (c *ResourceConfig) IsSet(k string) bool {
	if c == nil {
		return false
	}
	if c.IsComputed(k) {
		return true
	}
	if _, ok := c.Get(k); ok {
		return true
	}
	return false
}
IsSet checks if the key in the configuration is set. A key is set if
it has a value or the value is being computed (is unknown currently).

This function should be used rather than checking the keys of the
raw configuration itself, since a key may be omitted from the raw
configuration if it is being computed.
package terraform
import (
	"fmt"
	"reflect"
	"sort"
	"strconv"
	"strings"
	"github.com/hashicorp/terraform/config"
	"github.com/mitchellh/copystructure"
	"github.com/mitchellh/reflectwalk"
)
type ResourceProvisionerConfig struct {
	Type        string
	Provisioner ResourceProvisioner
	Config      *ResourceConfig
	RawConfig   *config.RawConfig
	ConnInfo    *config.RawConfig
}
type Resource struct {
	Name       string
	Type       string
	CountIndex int
	Id           string
	Info         *InstanceInfo
	Config       *ResourceConfig
	Dependencies []string
	Diff         *InstanceDiff
	Provider     ResourceProvider
	State        *InstanceState
	Provisioners []*ResourceProvisionerConfig
	Flags        ResourceFlag
}
type ResourceFlag byte
type InstanceInfo struct {
	Id string
	ModulePath []string
	Type string
	uniqueExtra string
}
func (i *InstanceInfo) HumanId() string {
	if i == nil {
		return "<nil>"
	}
	if len(i.ModulePath) <= 1 {
		return i.Id
	}
	return fmt.Sprintf(
		"module.%s.%s",
		strings.Join(i.ModulePath[1:], "."),
		i.Id)
}
func (i *InstanceInfo) uniqueId() string {
	prefix := i.HumanId()
	if v := i.uniqueExtra; v != "" {
		prefix += " " + v
	}
	return prefix
}
type ResourceConfig struct {
	ComputedKeys []string
	Raw          map[string]interface{}
	Config       map[string]interface{}
	raw *config.RawConfig
}
func NewResourceConfig(c *config.RawConfig) *ResourceConfig {
	result := &ResourceConfig{raw: c}
	result.interpolateForce()
	return result
}
func (c *ResourceConfig) DeepCopy() *ResourceConfig {
	if c == nil {
		return nil
	}
	copy, err := copystructure.Config{Lock: true}.Copy(c)
	if err != nil {
		panic(err)
	}
	result := copy.(*ResourceConfig)
	result.raw = c.raw.Copy()
	return result
}
func (c *ResourceConfig) Equal(c2 *ResourceConfig) bool {
	if c == nil || c2 == nil {
		return c == c2
	}
	sort.Strings(c.ComputedKeys)
	sort.Strings(c2.ComputedKeys)
	check := [][2]interface{}{
		{c.ComputedKeys, c2.ComputedKeys},
		{c.Raw, c2.Raw},
		{c.Config, c2.Config},
	}
	for _, pair := range check {
		if !reflect.DeepEqual(pair[0], pair[1]) {
			return false
		}
	}
	return true
}
func (c *ResourceConfig) CheckSet(keys []string) []error {
	var errs []error
	for _, k := range keys {
		if !c.IsSet(k) {
			errs = append(errs, fmt.Errorf("%s must be set", k))
		}
	}
	return errs
}
func (c *ResourceConfig) Get(k string) (interface{}, bool) {
	source := c.Config
	if c.IsComputed(k) {
		source = c.Raw
	}
	return c.get(k, source)
}
func (c *ResourceConfig) GetRaw(k string) (interface{}, bool) {
	return c.get(k, c.Raw)
}
func (c *ResourceConfig) IsComputed(k string) bool {
	v, ok := c.get(k, c.Config)
	if !ok {
		return false
	}
	if v == nil {
		return false
	}
	var w unknownCheckWalker
	if err := reflectwalk.Walk(v, &w); err != nil {
		panic(err)
	}
	return w.Unknown
}