config: can parse outputs
This commit is contained in:
parent
b444f5a171
commit
cc2bb950a1
|
@ -15,6 +15,7 @@ type Config struct {
|
||||||
ProviderConfigs map[string]*ProviderConfig
|
ProviderConfigs map[string]*ProviderConfig
|
||||||
Resources []*Resource
|
Resources []*Resource
|
||||||
Variables map[string]*Variable
|
Variables map[string]*Variable
|
||||||
|
Outputs map[string]*Output
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProviderConfig is the configuration for a resource provider.
|
// ProviderConfig is the configuration for a resource provider.
|
||||||
|
@ -42,6 +43,13 @@ type Variable struct {
|
||||||
defaultSet bool
|
defaultSet bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Output is an output defined within the configuration. An output is
|
||||||
|
// resulting data that is highlighted by Terraform when finished.
|
||||||
|
type Output struct {
|
||||||
|
Name string
|
||||||
|
RawConfig *RawConfig
|
||||||
|
}
|
||||||
|
|
||||||
// An InterpolatedVariable is a variable that is embedded within a string
|
// An InterpolatedVariable is a variable that is embedded within a string
|
||||||
// in the configuration, such as "hello ${world}" (world in this case is
|
// in the configuration, such as "hello ${world}" (world in this case is
|
||||||
// an interpolated variable).
|
// an interpolated variable).
|
||||||
|
|
|
@ -78,6 +78,16 @@ func (t *libuclConfigurable) Config() (*Config, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Build the outputs
|
||||||
|
if outputs := t.Object.Get("output"); outputs != nil {
|
||||||
|
var err error
|
||||||
|
config.Outputs, err = loadOutputsLibucl(outputs)
|
||||||
|
outputs.Close()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return config, nil
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,6 +155,52 @@ func loadFileLibucl(root string) (configurable, []string, error) {
|
||||||
return result, importPaths, nil
|
return result, importPaths, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadOutputsLibucl recurses into the given libucl object and turns
|
||||||
|
// it into a mapping of outputs.
|
||||||
|
func loadOutputsLibucl(o *libucl.Object) (map[string]*Output, error) {
|
||||||
|
objects := make(map[string]*libucl.Object)
|
||||||
|
|
||||||
|
// Iterate over all the "output" blocks and get the keys along with
|
||||||
|
// their raw configuration objects. We'll parse those later.
|
||||||
|
iter := o.Iterate(false)
|
||||||
|
for o1 := iter.Next(); o1 != nil; o1 = iter.Next() {
|
||||||
|
iter2 := o1.Iterate(true)
|
||||||
|
for o2 := iter2.Next(); o2 != nil; o2 = iter2.Next() {
|
||||||
|
objects[o2.Key()] = o2
|
||||||
|
defer o2.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
o1.Close()
|
||||||
|
iter2.Close()
|
||||||
|
}
|
||||||
|
iter.Close()
|
||||||
|
|
||||||
|
// Go through each object and turn it into an actual result.
|
||||||
|
result := make(map[string]*Output)
|
||||||
|
for n, o := range objects {
|
||||||
|
var config map[string]interface{}
|
||||||
|
|
||||||
|
if err := o.Decode(&config); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rawConfig, err := NewRawConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"Error reading config for output %s: %s",
|
||||||
|
n,
|
||||||
|
err)
|
||||||
|
}
|
||||||
|
|
||||||
|
result[n] = &Output{
|
||||||
|
Name: n,
|
||||||
|
RawConfig: rawConfig,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
// LoadProvidersLibucl recurses into the given libucl object and turns
|
// LoadProvidersLibucl recurses into the given libucl object and turns
|
||||||
// it into a mapping of provider configs.
|
// it into a mapping of provider configs.
|
||||||
func loadProvidersLibucl(o *libucl.Object) (map[string]*ProviderConfig, error) {
|
func loadProvidersLibucl(o *libucl.Object) (map[string]*ProviderConfig, error) {
|
||||||
|
|
|
@ -39,6 +39,11 @@ func TestLoadBasic(t *testing.T) {
|
||||||
if actual != strings.TrimSpace(basicResourcesStr) {
|
if actual != strings.TrimSpace(basicResourcesStr) {
|
||||||
t.Fatalf("bad:\n%s", actual)
|
t.Fatalf("bad:\n%s", actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
actual = outputsStr(c.Outputs)
|
||||||
|
if actual != strings.TrimSpace(basicOutputsStr) {
|
||||||
|
t.Fatalf("bad:\n%s", actual)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLoadBasic_import(t *testing.T) {
|
func TestLoadBasic_import(t *testing.T) {
|
||||||
|
@ -92,6 +97,40 @@ func TestLoad_variables(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func outputsStr(os map[string]*Output) string {
|
||||||
|
ns := make([]string, 0, len(os))
|
||||||
|
for n, _ := range os {
|
||||||
|
ns = append(ns, n)
|
||||||
|
}
|
||||||
|
sort.Strings(ns)
|
||||||
|
|
||||||
|
result := ""
|
||||||
|
for _, n := range ns {
|
||||||
|
o := os[n]
|
||||||
|
|
||||||
|
result += fmt.Sprintf("%s\n", n)
|
||||||
|
|
||||||
|
if len(o.RawConfig.Variables) > 0 {
|
||||||
|
result += fmt.Sprintf(" vars\n")
|
||||||
|
for _, rawV := range o.RawConfig.Variables {
|
||||||
|
kind := "unknown"
|
||||||
|
str := rawV.FullKey()
|
||||||
|
|
||||||
|
switch rawV.(type) {
|
||||||
|
case *ResourceVariable:
|
||||||
|
kind = "resource"
|
||||||
|
case *UserVariable:
|
||||||
|
kind = "user"
|
||||||
|
}
|
||||||
|
|
||||||
|
result += fmt.Sprintf(" %s: %s\n", kind, str)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.TrimSpace(result)
|
||||||
|
}
|
||||||
|
|
||||||
// This helper turns a provider configs field into a deterministic
|
// This helper turns a provider configs field into a deterministic
|
||||||
// string value for comparison in tests.
|
// string value for comparison in tests.
|
||||||
func providerConfigsStr(pcs map[string]*ProviderConfig) string {
|
func providerConfigsStr(pcs map[string]*ProviderConfig) string {
|
||||||
|
@ -219,6 +258,12 @@ func variablesStr(vs map[string]*Variable) string {
|
||||||
return strings.TrimSpace(result)
|
return strings.TrimSpace(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const basicOutputsStr = `
|
||||||
|
web_ip
|
||||||
|
vars
|
||||||
|
resource: aws_instance.web.private_ip
|
||||||
|
`
|
||||||
|
|
||||||
const basicProvidersStr = `
|
const basicProvidersStr = `
|
||||||
aws
|
aws
|
||||||
access_key
|
access_key
|
||||||
|
|
|
@ -32,3 +32,7 @@ resource aws_instance "web" {
|
||||||
resource "aws_instance" "db" {
|
resource "aws_instance" "db" {
|
||||||
security_groups = "${aws_security_group.firewall.*.id}"
|
security_groups = "${aws_security_group.firewall.*.id}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
output "web_ip" {
|
||||||
|
value = "${aws_instance.web.private_ip}"
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue