import hc2002.plugin as plugin
import hc2002.config as config

plugin.register_for_resource(__name__, 'hc2002.resource.instance')

_prefixes = ('availability-zone:', 'image:', 'kernel:', 'key:',
        'load-balancers:', 'ramdisk:', 'security-groups:', 'spot-price:',
        'subnet:')

def apply(instance):
    def _resolve_symbol(value):
        visited = set()
        while isinstance(value, basestring) \
                and value.startswith(prefix):
            value = value.format(region=config.region, **instance)
            if value in instance \
                    and value not in visited:
                visited.add(value)
                value = instance[value]
        return value

    # Resolve symbols
    for prefix in _prefixes:
        key = prefix[:-1]
        if key not in instance:
            continue

        if isinstance(instance[key], basestring):
            instance[key] = _resolve_symbol(instance[key])
        elif isinstance(instance[key], list):
            instance[key] = map(_resolve_symbol, instance[key])

    # Drop resolvable symbols
    for key in instance.keys():
        if key.startswith(_prefixes):
            del instance[key]

import hc2002.plugin as plugin
import hc2002.config as config

plugin.register_for_resource(__name__, 'hc2002.resource.instance')

_prefixes = ('availability-zone:', 'image:', 'kernel:', 'key:',
        'load-balancers:', 'ramdisk:', 'security-groups:', 'spot-price:',
        'subnet:')

def apply(instance):
    def resolve_symbol(original_value):
        value = original_value
        visited = set()
        while isinstance(value, basestring) \
                and value.startswith(prefix):
            value = value.format(region=config.region, **instance)
            if value in instance \
                    and value not in visited:
                visited.add(value)
                value = instance[value]
            else:
                if original_value == value:
                    raise Exception("Unable to resolve '%s'" % value)
                else:
                    raise Exception(
                            "While resolving '%s': unable to resolve '%s'"
                                % (original_value, value))
        return value

    # Resolve symbols
    for prefix in _prefixes:
        key = prefix[:-1]
        if key not in instance:
            continue

        if isinstance(instance[key], basestring):
            instance[key] = resolve_symbol(instance[key])
        elif isinstance(instance[key], list):
            instance[key] = map(resolve_symbol, instance[key])

    # Drop resolvable symbols
    for key in instance.keys():
        if key.startswith(_prefixes):
            del instance[key]

Fix infinite loop with missing symbol definition
Fix infinite loop with missing symbol definition

The local function _resolve_symbol is renamed for improved tracebacks.

  import hc2002.plugin as plugin
  import hc2002.config as config
  
  plugin.register_for_resource(__name__, 'hc2002.resource.instance')
  
  _prefixes = ('availability-zone:', 'image:', 'kernel:', 'key:',
          'load-balancers:', 'ramdisk:', 'security-groups:', 'spot-price:',
          'subnet:')
  
  def apply(instance):
-     def _resolve_symbol(value):
+     def resolve_symbol(original_value):
+         value = original_value
          visited = set()
          while isinstance(value, basestring) \
                  and value.startswith(prefix):
              value = value.format(region=config.region, **instance)
              if value in instance \
                      and value not in visited:
                  visited.add(value)
                  value = instance[value]
+             else:
+                 if original_value == value:
+                     raise Exception("Unable to resolve '%s'" % value)
+                 else:
+                     raise Exception(
+                             "While resolving '%s': unable to resolve '%s'"
+                                 % (original_value, value))
          return value
  
      # Resolve symbols
      for prefix in _prefixes:
          key = prefix[:-1]
          if key not in instance:
              continue
  
          if isinstance(instance[key], basestring):
-             instance[key] = _resolve_symbol(instance[key])
+             instance[key] = resolve_symbol(instance[key])
          elif isinstance(instance[key], list):
-             instance[key] = map(_resolve_symbol, instance[key])
+             instance[key] = map(resolve_symbol, instance[key])
  
      # Drop resolvable symbols
      for key in instance.keys():
          if key.startswith(_prefixes):
              del instance[key]
  
Fix infinite loop with missing symbol definition
## Code Before:
import hc2002.plugin as plugin
import hc2002.config as config

plugin.register_for_resource(__name__, 'hc2002.resource.instance')

_prefixes = ('availability-zone:', 'image:', 'kernel:', 'key:',
        'load-balancers:', 'ramdisk:', 'security-groups:', 'spot-price:',
        'subnet:')

def apply(instance):
    def _resolve_symbol(value):
        visited = set()
        while isinstance(value, basestring) \
                and value.startswith(prefix):
            value = value.format(region=config.region, **instance)
            if value in instance \
                    and value not in visited:
                visited.add(value)
                value = instance[value]
        return value

    # Resolve symbols
    for prefix in _prefixes:
        key = prefix[:-1]
        if key not in instance:
            continue

        if isinstance(instance[key], basestring):
            instance[key] = _resolve_symbol(instance[key])
        elif isinstance(instance[key], list):
            instance[key] = map(_resolve_symbol, instance[key])

    # Drop resolvable symbols
    for key in instance.keys():
        if key.startswith(_prefixes):
            del instance[key]

## Instruction:
Fix infinite loop with missing symbol definition
## Code After:
import hc2002.plugin as plugin
import hc2002.config as config

plugin.register_for_resource(__name__, 'hc2002.resource.instance')

_prefixes = ('availability-zone:', 'image:', 'kernel:', 'key:',
        'load-balancers:', 'ramdisk:', 'security-groups:', 'spot-price:',
        'subnet:')

def apply(instance):
    def resolve_symbol(original_value):
        value = original_value
        visited = set()
        while isinstance(value, basestring) \
                and value.startswith(prefix):
            value = value.format(region=config.region, **instance)
            if value in instance \
                    and value not in visited:
                visited.add(value)
                value = instance[value]
            else:
                if original_value == value:
                    raise Exception("Unable to resolve '%s'" % value)
                else:
                    raise Exception(
                            "While resolving '%s': unable to resolve '%s'"
                                % (original_value, value))
        return value

    # Resolve symbols
    for prefix in _prefixes:
        key = prefix[:-1]
        if key not in instance:
            continue

        if isinstance(instance[key], basestring):
            instance[key] = resolve_symbol(instance[key])
        elif isinstance(instance[key], list):
            instance[key] = map(resolve_symbol, instance[key])

    # Drop resolvable symbols
    for key in instance.keys():
        if key.startswith(_prefixes):
            del instance[key]
