本文整理匯總了Golang中github.com/hashicorp/terraform/config.ResourceVariable.ResourceId方法的典型用法代碼示例。如果您正苦於以下問題:Golang ResourceVariable.ResourceId方法的具體用法?Golang ResourceVariable.ResourceId怎麽用?Golang ResourceVariable.ResourceId使用的例子?那麽, 這裏精選的方法代碼示例或許可以為您提供幫助。您也可以進一步了解該方法所在類github.com/hashicorp/terraform/config.ResourceVariable
的用法示例。
在下文中一共展示了ResourceVariable.ResourceId方法的15個代碼示例,這些例子默認根據受歡迎程度排序。您可以為喜歡或者感覺有用的代碼點讚,您的評價將有助於係統推薦出更棒的Golang代碼示例。
示例1: computeResourceVariable
func (c *Context) computeResourceVariable(
v *config.ResourceVariable) (string, error) {
id := v.ResourceId()
if v.Multi {
id = fmt.Sprintf("%s.%d", id, v.Index)
}
c.sl.RLock()
defer c.sl.RUnlock()
r, ok := c.state.Resources[id]
if !ok {
return "", fmt.Errorf(
"Resource '%s' not found for variable '%s'",
id,
v.FullKey())
}
attr, ok := r.Attributes[v.Field]
if !ok {
return "", fmt.Errorf(
"Resource '%s' does not have attribute '%s' "+
"for variable '%s'",
id,
v.Field,
v.FullKey())
}
return attr, nil
}
示例2: resourceVariableInfo
func (c *walkContext) resourceVariableInfo(
v *config.ResourceVariable) (*ModuleState, *config.Resource, error) {
// Get the module tree that contains our current path. This is
// either the current module (path is empty) or a child.
var modTree *module.Tree
childPath := c.Path[1:len(c.Path)]
if len(childPath) == 0 {
modTree = c.Context.module
} else {
modTree = c.Context.module.Child(childPath)
}
// Get the resource from the configuration so we can verify
// that the resource is in the configuration and so we can access
// the configuration if we need to.
var cr *config.Resource
for _, r := range modTree.Config().Resources {
if r.Id() == v.ResourceId() {
cr = r
break
}
}
if cr == nil {
return nil, nil, fmt.Errorf(
"Resource '%s' not found for variable '%s'",
v.ResourceId(),
v.FullKey())
}
// Get the relevant module
module := c.Context.state.ModuleByPath(c.Path)
return module, cr, nil
}
示例3: resourceVariableInfo
func (i *Interpolater) resourceVariableInfo(
scope *InterpolationScope,
v *config.ResourceVariable) (*ModuleState, *config.Resource, error) {
// Get the module tree that contains our current path. This is
// either the current module (path is empty) or a child.
modTree := i.Module
if len(scope.Path) > 1 {
modTree = i.Module.Child(scope.Path[1:])
}
// Get the resource from the configuration so we can verify
// that the resource is in the configuration and so we can access
// the configuration if we need to.
var cr *config.Resource
for _, r := range modTree.Config().Resources {
if r.Id() == v.ResourceId() {
cr = r
break
}
}
if cr == nil {
return nil, nil, fmt.Errorf(
"Resource '%s' not found for variable '%s'",
v.ResourceId(),
v.FullKey())
}
// Get the relevant module
module := i.State.ModuleByPath(scope.Path)
return module, cr, nil
}
示例4: computeResourceMultiVariable
func (c *Context) computeResourceMultiVariable(
v *config.ResourceVariable) (string, error) {
c.sl.RLock()
defer c.sl.RUnlock()
// Get the resource from the configuration so we can know how
// many of the resource there is.
var cr *config.Resource
for _, r := range c.config.Resources {
if r.Id() == v.ResourceId() {
cr = r
break
}
}
if cr == nil {
return "", fmt.Errorf(
"Resource '%s' not found for variable '%s'",
v.ResourceId(),
v.FullKey())
}
var values []string
for i := 0; i < cr.Count; i++ {
id := fmt.Sprintf("%s.%d", v.ResourceId(), i)
// If we're dealing with only a single resource, then the
// ID doesn't have a trailing index.
if cr.Count == 1 {
id = v.ResourceId()
}
r, ok := c.state.Resources[id]
if !ok {
continue
}
attr, ok := r.Attributes[v.Field]
if !ok {
continue
}
values = append(values, attr)
}
if len(values) == 0 {
return "", fmt.Errorf(
"Resource '%s' does not have attribute '%s' "+
"for variable '%s'",
v.ResourceId(),
v.Field,
v.FullKey())
}
return strings.Join(values, ","), nil
}
示例5: computeResourceVariable
func (c *Context) computeResourceVariable(
v *config.ResourceVariable) (string, error) {
id := v.ResourceId()
if v.Multi {
id = fmt.Sprintf("%s.%d", id, v.Index)
}
c.sl.RLock()
defer c.sl.RUnlock()
r, ok := c.state.Resources[id]
if !ok {
return "", fmt.Errorf(
"Resource '%s' not found for variable '%s'",
id,
v.FullKey())
}
attr, ok := r.Attributes[v.Field]
if ok {
return attr, nil
}
// We didn't find the exact field, so lets separate the dots
// and see if anything along the way is a computed set. i.e. if
// we have "foo.0.bar" as the field, check to see if "foo" is
// a computed list. If so, then the whole thing is computed.
parts := strings.Split(v.Field, ".")
if len(parts) > 1 {
for i := 1; i < len(parts); i++ {
key := fmt.Sprintf("%s.#", strings.Join(parts[:i], "."))
if attr, ok := r.Attributes[key]; ok {
return attr, nil
}
}
}
return "", fmt.Errorf(
"Resource '%s' does not have attribute '%s' "+
"for variable '%s'",
id,
v.Field,
v.FullKey())
}
示例6: resourceCountKeys
func (i *Interpolater) resourceCountKeys(
ms *ModuleState,
cr *config.Resource,
v *config.ResourceVariable) ([]string, error) {
id := v.ResourceId()
// If we're NOT applying, then we assume we can read the count
// from the state. Plan and so on may not have any state yet so
// we do a full interpolation.
if i.Operation != walkApply {
count, err := cr.Count()
if err != nil {
return nil, err
}
result := make([]string, count)
for i := 0; i < count; i++ {
result[i] = fmt.Sprintf("%s.%d", id, i)
}
return result, nil
}
// We need to determine the list of resource keys to get values from.
// This needs to be sorted so the order is deterministic. We used to
// use "cr.Count()" but that doesn't work if the count is interpolated
// and we can't guarantee that so we instead depend on the state.
var resourceKeys []string
for k, _ := range ms.Resources {
// If we don't have the right prefix then ignore it
if k != id && !strings.HasPrefix(k, id+".") {
continue
}
// Add it to the list
resourceKeys = append(resourceKeys, k)
}
sort.Strings(resourceKeys)
return resourceKeys, nil
}
示例7: computeResourceVariable
func (i *Interpolater) computeResourceVariable(
scope *InterpolationScope,
v *config.ResourceVariable) (string, error) {
id := v.ResourceId()
if v.Multi {
id = fmt.Sprintf("%s.%d", id, v.Index)
}
i.StateLock.RLock()
defer i.StateLock.RUnlock()
// Get the information about this resource variable, and verify
// that it exists and such.
module, _, err := i.resourceVariableInfo(scope, v)
if err != nil {
return "", err
}
// If we have no module in the state yet or count, return empty
if module == nil || len(module.Resources) == 0 {
return "", nil
}
// Get the resource out from the state. We know the state exists
// at this point and if there is a state, we expect there to be a
// resource with the given name.
r, ok := module.Resources[id]
if !ok && v.Multi && v.Index == 0 {
r, ok = module.Resources[v.ResourceId()]
}
if !ok {
r = nil
}
if r == nil {
goto MISSING
}
if r.Primary == nil {
goto MISSING
}
if attr, ok := r.Primary.Attributes[v.Field]; ok {
return attr, nil
}
// At apply time, we can't do the "maybe has it" check below
// that we need for plans since parent elements might be computed.
// Therefore, it is an error and we're missing the key.
//
// TODO: test by creating a state and configuration that is referencing
// a non-existent variable "foo.bar" where the state only has "foo"
// and verify plan works, but apply doesn't.
if i.Operation == walkApply {
goto MISSING
}
// We didn't find the exact field, so lets separate the dots
// and see if anything along the way is a computed set. i.e. if
// we have "foo.0.bar" as the field, check to see if "foo" is
// a computed list. If so, then the whole thing is computed.
if parts := strings.Split(v.Field, "."); len(parts) > 1 {
for i := 1; i < len(parts); i++ {
// Lists and sets make this
key := fmt.Sprintf("%s.#", strings.Join(parts[:i], "."))
if attr, ok := r.Primary.Attributes[key]; ok {
return attr, nil
}
// Maps make this
key = fmt.Sprintf("%s", strings.Join(parts[:i], "."))
if attr, ok := r.Primary.Attributes[key]; ok {
return attr, nil
}
}
}
MISSING:
// Validation for missing interpolations should happen at a higher
// semantic level. If we reached this point and don't have variables,
// just return the computed value.
if scope == nil && scope.Resource == nil {
return config.UnknownVariableValue, nil
}
// If the operation is refresh, it isn't an error for a value to
// be unknown. Instead, we return that the value is computed so
// that the graph can continue to refresh other nodes. It doesn't
// matter because the config isn't interpolated anyways.
if i.Operation == walkRefresh {
return config.UnknownVariableValue, nil
}
return "", fmt.Errorf(
"Resource '%s' does not have attribute '%s' "+
"for variable '%s'",
id,
v.Field,
v.FullKey())
}
示例8: computeResourceMultiVariable
func (i *Interpolater) computeResourceMultiVariable(
scope *InterpolationScope,
v *config.ResourceVariable) (string, error) {
i.StateLock.RLock()
defer i.StateLock.RUnlock()
// Get the information about this resource variable, and verify
// that it exists and such.
module, cr, err := i.resourceVariableInfo(scope, v)
if err != nil {
return "", err
}
// Get the count so we know how many to iterate over
count, err := cr.Count()
if err != nil {
return "", fmt.Errorf(
"Error reading %s count: %s",
v.ResourceId(),
err)
}
// If we have no module in the state yet or count, return empty
if module == nil || len(module.Resources) == 0 || count == 0 {
return "", nil
}
var values []string
for j := 0; j < count; j++ {
id := fmt.Sprintf("%s.%d", v.ResourceId(), j)
// If we're dealing with only a single resource, then the
// ID doesn't have a trailing index.
if count == 1 {
id = v.ResourceId()
}
r, ok := module.Resources[id]
if !ok {
continue
}
if r.Primary == nil {
continue
}
attr, ok := r.Primary.Attributes[v.Field]
if !ok {
// computed list attribute
_, ok := r.Primary.Attributes[v.Field+".#"]
if !ok {
continue
}
attr, err = i.interpolateListAttribute(v.Field, r.Primary.Attributes)
if err != nil {
return "", err
}
}
if config.IsStringList(attr) {
for _, s := range config.StringList(attr).Slice() {
values = append(values, s)
}
continue
}
// If any value is unknown, the whole thing is unknown
if attr == config.UnknownVariableValue {
return config.UnknownVariableValue, nil
}
values = append(values, attr)
}
if len(values) == 0 {
// If the operation is refresh, it isn't an error for a value to
// be unknown. Instead, we return that the value is computed so
// that the graph can continue to refresh other nodes. It doesn't
// matter because the config isn't interpolated anyways.
//
// For a Destroy, we're also fine with computed values, since our goal is
// only to get destroy nodes for existing resources.
//
// For an input walk, computed values are okay to return because we're only
// looking for missing variables to prompt the user for.
if i.Operation == walkRefresh || i.Operation == walkPlanDestroy || i.Operation == walkDestroy || i.Operation == walkInput {
return config.UnknownVariableValue, nil
}
return "", fmt.Errorf(
"Resource '%s' does not have attribute '%s' "+
"for variable '%s'",
v.ResourceId(),
v.Field,
v.FullKey())
}
return config.NewStringList(values).String(), nil
}
示例9: resourceCountMax
func (i *Interpolater) resourceCountMax(
ms *ModuleState,
cr *config.Resource,
v *config.ResourceVariable) (int, error) {
id := v.ResourceId()
// If we're NOT applying, then we assume we can read the count
// from the state. Plan and so on may not have any state yet so
// we do a full interpolation.
if i.Operation != walkApply {
count, err := cr.Count()
if err != nil {
return 0, err
}
return count, nil
}
// We need to determine the list of resource keys to get values from.
// This needs to be sorted so the order is deterministic. We used to
// use "cr.Count()" but that doesn't work if the count is interpolated
// and we can't guarantee that so we instead depend on the state.
max := -1
for k, _ := range ms.Resources {
// Get the index number for this resource
index := ""
if k == id {
// If the key is the id, then its just 0 (no explicit index)
index = "0"
} else if strings.HasPrefix(k, id+".") {
// Grab the index number out of the state
index = k[len(id+"."):]
if idx := strings.IndexRune(index, '.'); idx >= 0 {
index = index[:idx]
}
}
// If there was no index then this resource didn't match
// the one we're looking for, exit.
if index == "" {
continue
}
// Turn the index into an int
raw, err := strconv.ParseInt(index, 0, 0)
if err != nil {
return 0, fmt.Errorf(
"%s: error parsing index %q as int: %s",
id, index, err)
}
// Keep track of this index if its the max
if new := int(raw); new > max {
max = new
}
}
// If we never found any matching resources in the state, we
// have zero.
if max == -1 {
return 0, nil
}
// The result value is "max+1" because we're returning the
// max COUNT, not the max INDEX, and we zero-index.
return max + 1, nil
}
示例10: computeResourceMultiVariable
func (i *Interpolater) computeResourceMultiVariable(
scope *InterpolationScope,
v *config.ResourceVariable) (*ast.Variable, error) {
i.StateLock.RLock()
defer i.StateLock.RUnlock()
unknownVariable := unknownVariable()
// Get the information about this resource variable, and verify
// that it exists and such.
module, cr, err := i.resourceVariableInfo(scope, v)
if err != nil {
return nil, err
}
// Get the keys for all the resources that are created for this resource
countMax, err := i.resourceCountMax(module, cr, v)
if err != nil {
return nil, err
}
// If count is zero, we return an empty list
if countMax == 0 {
return &ast.Variable{Type: ast.TypeList, Value: []ast.Variable{}}, nil
}
// If we have no module in the state yet or count, return unknown
if module == nil || len(module.Resources) == 0 {
return &unknownVariable, nil
}
var values []interface{}
for idx := 0; idx < countMax; idx++ {
id := fmt.Sprintf("%s.%d", v.ResourceId(), idx)
// ID doesn't have a trailing index. We try both here, but if a value
// without a trailing index is found we prefer that. This choice
// is for legacy reasons: older versions of TF preferred it.
if id == v.ResourceId()+".0" {
potential := v.ResourceId()
if _, ok := module.Resources[potential]; ok {
id = potential
}
}
r, ok := module.Resources[id]
if !ok {
continue
}
if r.Primary == nil {
continue
}
if singleAttr, ok := r.Primary.Attributes[v.Field]; ok {
if singleAttr == config.UnknownVariableValue {
return &unknownVariable, nil
}
values = append(values, singleAttr)
continue
}
// computed list or map attribute
_, isList := r.Primary.Attributes[v.Field+".#"]
_, isMap := r.Primary.Attributes[v.Field+".%"]
if !(isList || isMap) {
continue
}
multiAttr, err := i.interpolateComplexTypeAttribute(v.Field, r.Primary.Attributes)
if err != nil {
return nil, err
}
if multiAttr == unknownVariable {
return &unknownVariable, nil
}
values = append(values, multiAttr)
}
if len(values) == 0 {
// If the operation is refresh, it isn't an error for a value to
// be unknown. Instead, we return that the value is computed so
// that the graph can continue to refresh other nodes. It doesn't
// matter because the config isn't interpolated anyways.
//
// For a Destroy, we're also fine with computed values, since our goal is
// only to get destroy nodes for existing resources.
//
// For an input walk, computed values are okay to return because we're only
// looking for missing variables to prompt the user for.
if i.Operation == walkRefresh || i.Operation == walkPlanDestroy || i.Operation == walkDestroy || i.Operation == walkInput {
return &unknownVariable, nil
}
return nil, fmt.Errorf(
"Resource '%s' does not have attribute '%s' "+
"for variable '%s'",
v.ResourceId(),
//.........這裏部分代碼省略.........
示例11: computeResourceMultiVariable
func (c *walkContext) computeResourceMultiVariable(
v *config.ResourceVariable) (string, error) {
c.Context.sl.RLock()
defer c.Context.sl.RUnlock()
// Get the information about this resource variable, and verify
// that it exists and such.
module, cr, err := c.resourceVariableInfo(v)
if err != nil {
return "", err
}
// Get the count so we know how many to iterate over
count, err := cr.Count()
if err != nil {
return "", fmt.Errorf(
"Error reading %s count: %s",
v.ResourceId(),
err)
}
// If we have no module in the state yet or count, return empty
if module == nil || len(module.Resources) == 0 || count == 0 {
return "", nil
}
var values []string
for i := 0; i < count; i++ {
id := fmt.Sprintf("%s.%d", v.ResourceId(), i)
// If we're dealing with only a single resource, then the
// ID doesn't have a trailing index.
if count == 1 {
id = v.ResourceId()
}
r, ok := module.Resources[id]
if !ok {
continue
}
if r.Primary == nil {
continue
}
attr, ok := r.Primary.Attributes[v.Field]
if !ok {
continue
}
values = append(values, attr)
}
if len(values) == 0 {
return "", fmt.Errorf(
"Resource '%s' does not have attribute '%s' "+
"for variable '%s'",
v.ResourceId(),
v.Field,
v.FullKey())
}
return strings.Join(values, config.InterpSplitDelim), nil
}
示例12: computeResourceMultiVariable
func (i *Interpolater) computeResourceMultiVariable(
scope *InterpolationScope,
v *config.ResourceVariable) (*ast.Variable, error) {
i.StateLock.RLock()
defer i.StateLock.RUnlock()
unknownVariable := unknownVariable()
// Get the information about this resource variable, and verify
// that it exists and such.
module, cr, err := i.resourceVariableInfo(scope, v)
if err != nil {
return nil, err
}
// Get the count so we know how many to iterate over
count, err := cr.Count()
if err != nil {
return nil, fmt.Errorf(
"Error reading %s count: %s",
v.ResourceId(),
err)
}
// If count is zero, we return an empty list
if count == 0 {
return &ast.Variable{Type: ast.TypeList, Value: []ast.Variable{}}, nil
}
// If we have no module in the state yet or count, return unknown
if module == nil || len(module.Resources) == 0 {
return &unknownVariable, nil
}
var values []interface{}
for j := 0; j < count; j++ {
id := fmt.Sprintf("%s.%d", v.ResourceId(), j)
// If we're dealing with only a single resource, then the
// ID doesn't have a trailing index.
if count == 1 {
id = v.ResourceId()
}
r, ok := module.Resources[id]
if !ok {
continue
}
if r.Primary == nil {
continue
}
if singleAttr, ok := r.Primary.Attributes[v.Field]; ok {
if singleAttr == config.UnknownVariableValue {
return &unknownVariable, nil
}
values = append(values, singleAttr)
continue
}
// computed list or map attribute
_, isList := r.Primary.Attributes[v.Field+".#"]
_, isMap := r.Primary.Attributes[v.Field+".%"]
if !(isList || isMap) {
continue
}
multiAttr, err := i.interpolateComplexTypeAttribute(v.Field, r.Primary.Attributes)
if err != nil {
return nil, err
}
if multiAttr == unknownVariable {
return &ast.Variable{Type: ast.TypeString, Value: ""}, nil
}
values = append(values, multiAttr)
}
if len(values) == 0 {
// If the operation is refresh, it isn't an error for a value to
// be unknown. Instead, we return that the value is computed so
// that the graph can continue to refresh other nodes. It doesn't
// matter because the config isn't interpolated anyways.
//
// For a Destroy, we're also fine with computed values, since our goal is
// only to get destroy nodes for existing resources.
//
// For an input walk, computed values are okay to return because we're only
// looking for missing variables to prompt the user for.
if i.Operation == walkRefresh || i.Operation == walkPlanDestroy || i.Operation == walkDestroy || i.Operation == walkInput {
return &unknownVariable, nil
}
return nil, fmt.Errorf(
"Resource '%s' does not have attribute '%s' "+
"for variable '%s'",
v.ResourceId(),
v.Field,
//.........這裏部分代碼省略.........
示例13: computeResourceMultiVariable
func (i *Interpolater) computeResourceMultiVariable(
scope *InterpolationScope,
v *config.ResourceVariable) (string, error) {
i.StateLock.RLock()
defer i.StateLock.RUnlock()
// Get the information about this resource variable, and verify
// that it exists and such.
module, cr, err := i.resourceVariableInfo(scope, v)
if err != nil {
return "", err
}
// Get the count so we know how many to iterate over
count, err := cr.Count()
if err != nil {
return "", fmt.Errorf(
"Error reading %s count: %s",
v.ResourceId(),
err)
}
// If we have no module in the state yet or count, return empty
if module == nil || len(module.Resources) == 0 || count == 0 {
return "", nil
}
var values []string
for i := 0; i < count; i++ {
id := fmt.Sprintf("%s.%d", v.ResourceId(), i)
// If we're dealing with only a single resource, then the
// ID doesn't have a trailing index.
if count == 1 {
id = v.ResourceId()
}
r, ok := module.Resources[id]
if !ok {
continue
}
if r.Primary == nil {
continue
}
attr, ok := r.Primary.Attributes[v.Field]
if !ok {
continue
}
values = append(values, attr)
}
if len(values) == 0 {
// If the operation is refresh, it isn't an error for a value to
// be unknown. Instead, we return that the value is computed so
// that the graph can continue to refresh other nodes. It doesn't
// matter because the config isn't interpolated anyways.
if i.Operation == walkRefresh {
return config.UnknownVariableValue, nil
}
return "", fmt.Errorf(
"Resource '%s' does not have attribute '%s' "+
"for variable '%s'",
v.ResourceId(),
v.Field,
v.FullKey())
}
return strings.Join(values, config.InterpSplitDelim), nil
}
示例14: computeResourceVariable
func (i *Interpolater) computeResourceVariable(
scope *InterpolationScope,
v *config.ResourceVariable) (*ast.Variable, error) {
id := v.ResourceId()
if v.Multi {
id = fmt.Sprintf("%s.%d", id, v.Index)
}
i.StateLock.RLock()
defer i.StateLock.RUnlock()
unknownVariable := unknownVariable()
// These variables must be declared early because of the use of GOTO
var isList bool
var isMap bool
// Get the information about this resource variable, and verify
// that it exists and such.
module, cr, err := i.resourceVariableInfo(scope, v)
if err != nil {
return nil, err
}
// If we're requesting "count" its a special variable that we grab
// directly from the config itself.
if v.Field == "count" {
var count int
if cr != nil {
count, err = cr.Count()
} else {
count, err = i.resourceCountMax(module, cr, v)
}
if err != nil {
return nil, fmt.Errorf(
"Error reading %s count: %s",
v.ResourceId(),
err)
}
return &ast.Variable{Type: ast.TypeInt, Value: count}, nil
}
// Get the resource out from the state. We know the state exists
// at this point and if there is a state, we expect there to be a
// resource with the given name.
var r *ResourceState
if module != nil && len(module.Resources) > 0 {
var ok bool
r, ok = module.Resources[id]
if !ok && v.Multi && v.Index == 0 {
r, ok = module.Resources[v.ResourceId()]
}
if !ok {
r = nil
}
}
if r == nil || r.Primary == nil {
if i.Operation == walkApply || i.Operation == walkPlan {
return nil, fmt.Errorf(
"Resource '%s' not found for variable '%s'",
v.ResourceId(),
v.FullKey())
}
// If we have no module in the state yet or count, return empty.
// NOTE(@mitchellh): I actually don't know why this is here. During
// a refactor I kept this here to maintain the same behavior, but
// I'm not sure why its here.
if module == nil || len(module.Resources) == 0 {
return nil, nil
}
goto MISSING
}
if attr, ok := r.Primary.Attributes[v.Field]; ok {
v, err := hil.InterfaceToVariable(attr)
return &v, err
}
// computed list or map attribute
_, isList = r.Primary.Attributes[v.Field+".#"]
_, isMap = r.Primary.Attributes[v.Field+".%"]
if isList || isMap {
variable, err := i.interpolateComplexTypeAttribute(v.Field, r.Primary.Attributes)
return &variable, err
}
// At apply time, we can't do the "maybe has it" check below
// that we need for plans since parent elements might be computed.
// Therefore, it is an error and we're missing the key.
//
// TODO: test by creating a state and configuration that is referencing
// a non-existent variable "foo.bar" where the state only has "foo"
// and verify plan works, but apply doesn't.
if i.Operation == walkApply || i.Operation == walkDestroy {
goto MISSING
}
//.........這裏部分代碼省略.........
示例15: computeResourceVariable
func (c *walkContext) computeResourceVariable(
v *config.ResourceVariable) (string, error) {
id := v.ResourceId()
if v.Multi {
id = fmt.Sprintf("%s.%d", id, v.Index)
}
c.Context.sl.RLock()
defer c.Context.sl.RUnlock()
// Get the information about this resource variable, and verify
// that it exists and such.
module, _, err := c.resourceVariableInfo(v)
if err != nil {
return "", err
}
// If we have no module in the state yet or count, return empty
if module == nil || len(module.Resources) == 0 {
return "", nil
}
// Get the resource out from the state. We know the state exists
// at this point and if there is a state, we expect there to be a
// resource with the given name.
r, ok := module.Resources[id]
if !ok && v.Multi && v.Index == 0 {
r, ok = module.Resources[v.ResourceId()]
}
if !ok {
r = nil
}
if r == nil {
return "", fmt.Errorf(
"Resource '%s' not found for variable '%s'",
id,
v.FullKey())
}
if r.Primary == nil {
goto MISSING
}
if attr, ok := r.Primary.Attributes[v.Field]; ok {
return attr, nil
}
// At apply time, we can't do the "maybe has it" check below
// that we need for plans since parent elements might be computed.
// Therefore, it is an error and we're missing the key.
//
// TODO: test by creating a state and configuration that is referencing
// a non-existent variable "foo.bar" where the state only has "foo"
// and verify plan works, but apply doesn't.
if c.Operation == walkApply {
goto MISSING
}
// We didn't find the exact field, so lets separate the dots
// and see if anything along the way is a computed set. i.e. if
// we have "foo.0.bar" as the field, check to see if "foo" is
// a computed list. If so, then the whole thing is computed.
if parts := strings.Split(v.Field, "."); len(parts) > 1 {
for i := 1; i < len(parts); i++ {
// Lists and sets make this
key := fmt.Sprintf("%s.#", strings.Join(parts[:i], "."))
if attr, ok := r.Primary.Attributes[key]; ok {
return attr, nil
}
// Maps make this
key = fmt.Sprintf("%s", strings.Join(parts[:i], "."))
if attr, ok := r.Primary.Attributes[key]; ok {
return attr, nil
}
}
}
MISSING:
return "", fmt.Errorf(
"Resource '%s' does not have attribute '%s' "+
"for variable '%s'",
id,
v.Field,
v.FullKey())
}