Динамическое создание n экземпляров ec2 с помощью Troposphere

Я только вхожу в EC2, CloudFormation (и Troposphere) и т. Д. Я пытаюсь начать с простой Selenium Grid, которая будет работать каждую ночь. Прямо сейчас мы используем 12 узлов селена (каждый на своем собственном экземпляре EC2), когда это необходимо. Стаки собираются только на пару часов за раз. Весьма вероятно, что нам понадобится больше в будущем, поэтому вместо того, чтобы устанавливать количество узлов статически, я пытаюсь настроить его так, чтобы Дженкинс мог динамически увеличивать количество узлов.

Прямо сейчас у меня есть простой цикл for, который, похоже, должен работать нормально - особенно после просмотра нескольких примеров:

for i in range(numNodes):
    instance = ec2.Instance("Node{}".format(str(i)))
    instance.ImageId = Ref(Image)
    instance.UserData = Base64(Join("", userData))
    instance.InstanceType = Ref(NodeSize)
    instance.KeyName = Ref(SSHKey)
    instance.SecurityGroups = [Ref("NodeSecurityGroup")]
    instance.IamInstanceProfile = "SeleniumNode"
    template.add_resource(instance)

Полная трассировка стека:

        Traceback (most recent call last):
  File "C:/dev/source/admin/scripts/troposphere/seleniumGrid.py", line 171, in <module>
    print(template.to_json())
  File "C:\Users\Sathed\AppData\Local\Programs\Python\Python35-32\lib\site-packages\troposphere\__init__.py", line 543, in to_json
    sort_keys=sort_keys, separators=separators)
  File "C:\Users\Sathed\AppData\Local\Programs\Python\Python35-32\lib\json\__init__.py", line 237, in dumps
    **kw).encode(obj)
  File "C:\Users\Sathed\AppData\Local\Programs\Python\Python35-32\lib\json\encoder.py", line 200, in encode
    chunks = list(chunks)
  File "C:\Users\Sathed\AppData\Local\Programs\Python\Python35-32\lib\json\encoder.py", line 429, in _iterencode
    yield from _iterencode_dict(o, _current_indent_level)
  File "C:\Users\Sathed\AppData\Local\Programs\Python\Python35-32\lib\json\encoder.py", line 403, in _iterencode_dict
    yield from chunks
  File "C:\Users\Sathed\AppData\Local\Programs\Python\Python35-32\lib\json\encoder.py", line 403, in _iterencode_dict
    yield from chunks
  File "C:\Users\Sathed\AppData\Local\Programs\Python\Python35-32\lib\json\encoder.py", line 436, in _iterencode
    o = _default(o)
  File "C:\Users\Sathed\AppData\Local\Programs\Python\Python35-32\lib\site-packages\troposphere\__init__.py", line 440, in default
    return obj.JSONrepr()
  File "C:\Users\Sathed\AppData\Local\Programs\Python\Python35-32\lib\site-packages\troposphere\__init__.py", line 223, in JSONrepr
    "Resource %s required in type %s" % (k, rtype))
ValueError: Resource ImageId required in type AWS::EC2::Instance

Параметр My Image выглядит так:

Image = template.add_parameter(Parameter(
"Image",
    Type="AWS::EC2::Image::Id",  # I even tried setting this to "String"
    Description="AMI To use for all windows grid instances.",
    Default="ami-c06b24a0"  
))

Я даже пробовал передать все в конструктор.

for i in range(numNodes):
    instance = ec2.Instance("Node{}".format(str(i)),
                            ImageId=Ref(Image),
                            UserData=Base64(Join("", userData)),
                            InstanceType=Ref(NodeSize),
                            KeyName=Ref(SSHKey),
                            SecurityGroups=[Ref("NodeSecurityGroup")],
                            DependsOn=["NodeSecurityGroup", "WindowsHub"],
                            IamInstanceProfile="SeleniumNode")
    template.add_resource(instance)

Но я все еще получаю ту же ошибку. Я уверен, что это что-то глупое, но это стало довольно раздражающим. Есть предположения?

Кроме того, я получаю сообщение об ошибке при попытке распечатать шаблон JSON.

print(template.to_json())

Тропосфера 1.8.2

Python 3.5.2


person Sathed    schedule 18.10.2016    source источник


Ответы (2)


специалист по обслуживанию тропосферы здесь. В какой момент вы получаете ValueError? Можете ли вы поделиться полной трассировкой стека?

Одна вещь, которая, вероятно, не исправит это, но я подумал, что хочу указать, заключается в том, что вам не нужно указывать каждый отдельный атрибут экземпляра после создания объекта. Вместо этого вы обычно используете этот код:

for i in range(numNodes):
    instance = ec2.Instance(
        "Node{}".format(str(i)),
        ImageId=Ref(Image)
        UserData=Base64(Join("", userData)),
        InstanceType=Ref(NodeSize),
        KeyName=Ref(SSHKey),
        SecurityGroups=[Ref("NodeSecurityGroup")],
        IamInstanceProfile="SeleniumNode",
    )
    template.add_resource(instance)

Вы даже можете сократить его до:

for i in range(numNodes):
    instance = template.add_resource(
        ec2.Instance(
            "Node{}".format(str(i)),
            ImageId=Ref(Image)
            UserData=Base64(Join("", userData)),
            InstanceType=Ref(NodeSize),
            KeyName=Ref(SSHKey),
            SecurityGroups=[Ref("NodeSecurityGroup")],
            IamInstanceProfile="SeleniumNode",
        )
    )

В любом случае, это не похоже на вашу проблему - так что, если бы вы могли поделиться полной трассировкой стека для ошибки, которая могла бы помочь, а также версию python и тропосферы, которую вы используете.

person phobologic    schedule 19.10.2016
comment
Я действительно пытался сократить его и передать конструктору, но все равно получаю ту же ошибку. - person Sathed; 19.10.2016
comment
Извините, нажать "возврат" слишком рано. Я обновил вопрос, указав информацию, которую вы просили. - person Sathed; 19.10.2016

Что ж, я собирался удалить вопрос, как только понял, что я тупица ... Но это маленькое сообщение об удалении «ответов на вопросы» ради всего человечества, yadda yadda yadda, заставило меня почувствовать себя виноватым. Надеюсь, кто-то еще сможет извлечь уроки из моих ошибок.

Что до ответа ...

Оказывается, с Troposphere все в порядке (я предполагал, что это моя вина). Я полностью забыл о Selenium Hub, который является его собственным экземпляром, но НЕ настраивается динамически в зависимости от количества необходимых узлов. Я только частично добавил ресурсы для хаба. Вы угадали - я забыл указать ImageId kwarg. Как только я добавил это (и несколько других kwarg), все заработало безупречно.

Привет @phobologic и всем остальным сопровождающим Troposphere. Благодаря вам я могу превратить объект JSON из 2500+ строк в скрипт Python на 175 строк, который НАМНОГО проще в обслуживании!

person Sathed    schedule 19.10.2016
comment
Ой, здорово, рад, что ты это понял. Мне действительно интересно, может ли быть способ сделать так, чтобы это исключение указывало на заголовок объекта (при условии, что он есть), который вызывает проблему, который, безусловно, помог бы вам в этом. Я посмотрю, и спасибо за добрые слова :) - person phobologic; 20.10.2016
comment
Кстати, я пошел дальше и создал PR, который должен упростить устранение неполадок такого рода: github.com / cloudtools / troposphere / pull / 597 - person phobologic; 20.10.2016