config: Count can be a string (for interpolation)
This commit is contained in:
parent
fb1c224e12
commit
8e2315599f
|
@ -56,7 +56,7 @@ type ProviderConfig struct {
|
|||
type Resource struct {
|
||||
Name string
|
||||
Type string
|
||||
Count int
|
||||
Count *RawConfig
|
||||
RawConfig *RawConfig
|
||||
Provisioners []*Provisioner
|
||||
DependsOn []string
|
||||
|
@ -244,12 +244,6 @@ func (c *Config) Validate() error {
|
|||
|
||||
// Validate resources
|
||||
for n, r := range resources {
|
||||
if r.Count < 1 {
|
||||
errs = append(errs, fmt.Errorf(
|
||||
"%s: count must be greater than or equal to 1",
|
||||
n))
|
||||
}
|
||||
|
||||
for _, d := range r.DependsOn {
|
||||
if _, ok := resources[d]; !ok {
|
||||
errs = append(errs, fmt.Errorf(
|
||||
|
@ -267,8 +261,7 @@ func (c *Config) Validate() error {
|
|||
}
|
||||
|
||||
id := fmt.Sprintf("%s.%s", rv.Type, rv.Name)
|
||||
r, ok := resources[id]
|
||||
if !ok {
|
||||
if _, ok := resources[id]; !ok {
|
||||
errs = append(errs, fmt.Errorf(
|
||||
"%s: unknown resource '%s' referenced in variable %s",
|
||||
source,
|
||||
|
@ -276,18 +269,6 @@ func (c *Config) Validate() error {
|
|||
rv.FullKey()))
|
||||
continue
|
||||
}
|
||||
|
||||
// If it is a multi reference and resource has a single
|
||||
// count, it is an error.
|
||||
if r.Count > 1 && !rv.Multi {
|
||||
errs = append(errs, fmt.Errorf(
|
||||
"%s: variable '%s' must specify index for multi-count "+
|
||||
"resource %s",
|
||||
source,
|
||||
rv.FullKey(),
|
||||
id))
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -327,6 +308,9 @@ func (c *Config) InterpolatedVariables() map[string][]InterpolatedVariable {
|
|||
|
||||
for _, rc := range c.Resources {
|
||||
source := fmt.Sprintf("resource '%s'", rc.Id())
|
||||
for _, v := range rc.Count.Variables {
|
||||
result[source] = append(result[source], v)
|
||||
}
|
||||
for _, v := range rc.RawConfig.Variables {
|
||||
result[source] = append(result[source], v)
|
||||
}
|
||||
|
@ -400,7 +384,7 @@ func (r *Resource) mergerMerge(m merger) merger {
|
|||
result.Type = r2.Type
|
||||
result.RawConfig = result.RawConfig.merge(r2.RawConfig)
|
||||
|
||||
if r2.Count > 0 {
|
||||
if r2.Count.Value() != "1" {
|
||||
result.Count = r2.Count
|
||||
}
|
||||
|
||||
|
|
|
@ -190,10 +190,10 @@ func resourcesStr(rs []*Resource) string {
|
|||
for _, i := range order {
|
||||
r := rs[i]
|
||||
result += fmt.Sprintf(
|
||||
"%s[%s] (x%d)\n",
|
||||
"%s[%s] (x%s)\n",
|
||||
r.Type,
|
||||
r.Name,
|
||||
r.Count)
|
||||
r.Count.Value())
|
||||
|
||||
ks := make([]string, 0, len(r.RawConfig.Raw))
|
||||
for k, _ := range r.RawConfig.Raw {
|
||||
|
|
|
@ -23,27 +23,6 @@ func TestConfigValidate_badDependsOn(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestConfigValidate_badMultiResource(t *testing.T) {
|
||||
c := testConfig(t, "validate-bad-multi-resource")
|
||||
if err := c.Validate(); err == nil {
|
||||
t.Fatal("should not be valid")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigValidate_countBelowZero(t *testing.T) {
|
||||
c := testConfig(t, "validate-count-below-zero")
|
||||
if err := c.Validate(); err == nil {
|
||||
t.Fatal("should not be valid")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigValidate_countZero(t *testing.T) {
|
||||
c := testConfig(t, "validate-count-zero")
|
||||
if err := c.Validate(); err == nil {
|
||||
t.Fatal("should not be valid")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigValidate_dupModule(t *testing.T) {
|
||||
c := testConfig(t, "validate-dup-module")
|
||||
if err := c.Validate(); err == nil {
|
||||
|
|
|
@ -406,7 +406,7 @@ func loadResourcesHcl(os *hclobj.Object) ([]*Resource, error) {
|
|||
}
|
||||
|
||||
// If we have a count, then figure it out
|
||||
var count int = 1
|
||||
var count string = "1"
|
||||
if o := obj.Get("count", false); o != nil {
|
||||
err = hcl.DecodeObject(&count, o)
|
||||
if err != nil {
|
||||
|
@ -417,6 +417,13 @@ func loadResourcesHcl(os *hclobj.Object) ([]*Resource, error) {
|
|||
err)
|
||||
}
|
||||
}
|
||||
countConfig, err := NewRawConfig(map[string]interface{}{
|
||||
"count": count,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
countConfig.Key = "count"
|
||||
|
||||
// If we have depends fields, then add those in
|
||||
var dependsOn []string
|
||||
|
@ -475,7 +482,7 @@ func loadResourcesHcl(os *hclobj.Object) ([]*Resource, error) {
|
|||
result = append(result, &Resource{
|
||||
Name: k,
|
||||
Type: t.Key,
|
||||
Count: count,
|
||||
Count: countConfig,
|
||||
RawConfig: rawConfig,
|
||||
Provisioners: provisioners,
|
||||
DependsOn: dependsOn,
|
||||
|
|
|
@ -24,6 +24,7 @@ const UnknownVariableValue = "74D93920-ED26-11E3-AC10-0800200C9A66"
|
|||
// RawConfig supports a query-like interface to request
|
||||
// information from deep within the structure.
|
||||
type RawConfig struct {
|
||||
Key string
|
||||
Raw map[string]interface{}
|
||||
Interpolations []Interpolation
|
||||
Variables map[string]InterpolatedVariable
|
||||
|
@ -43,6 +44,18 @@ func NewRawConfig(raw map[string]interface{}) (*RawConfig, error) {
|
|||
return result, nil
|
||||
}
|
||||
|
||||
// Value returns the value of the configuration if this configuration
|
||||
// has a Key set. If this does not have a Key set, nil will be returned.
|
||||
func (r *RawConfig) Value() interface{} {
|
||||
if c := r.Config(); c != nil {
|
||||
if v, ok := c[r.Key]; ok {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
return r.Raw[r.Key]
|
||||
}
|
||||
|
||||
// Config returns the entire configuration with the variables
|
||||
// interpolated from any call to Interpolate.
|
||||
//
|
||||
|
|
|
@ -125,6 +125,36 @@ func TestRawConfig_unknown(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestRawConfigValue(t *testing.T) {
|
||||
raw := map[string]interface{}{
|
||||
"foo": "${var.bar}",
|
||||
}
|
||||
|
||||
rc, err := NewRawConfig(raw)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
rc.Key = ""
|
||||
if rc.Value() != nil {
|
||||
t.Fatalf("bad: %#v", rc.Value())
|
||||
}
|
||||
|
||||
rc.Key = "foo"
|
||||
if rc.Value() != "${var.bar}" {
|
||||
t.Fatalf("err: %#v", rc.Value())
|
||||
}
|
||||
|
||||
vars := map[string]string{"var.bar": "baz"}
|
||||
if err := rc.Interpolate(vars); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
if rc.Value() != "baz" {
|
||||
t.Fatalf("bad: %#v", rc.Value())
|
||||
}
|
||||
}
|
||||
|
||||
func TestRawConfig_implGob(t *testing.T) {
|
||||
var _ gob.GobDecoder = new(RawConfig)
|
||||
var _ gob.GobEncoder = new(RawConfig)
|
||||
|
|
Loading…
Reference in New Issue