2015-11-26 4 views
0

J'utilise Troposphere pour générer des piles CloudFormation et je souhaite passer l'attribut Elastic Load Balancer ConnectionSettings uniquement s'il est défini dans ma configuration, sinon je ne souhaite pas le spécifier.Comment passer un attribut d'objet Troposphere sous condition?

Si je le mets à None par défaut alors j'obtiens une erreur au sujet de la valeur n'étant pas du type prévu de troposphere.elasticloadbalancing.ConnectionSettings.

Je préfère essayer d'éviter de définir un paramètre par défaut explicite dans l'appel, car il peut remplacer d'autres paramètres.

Idealy, je voudrais être en mesure d'ajouter des attributs à un objet existant, .: par exemple

lb = template.add_resource(elb.LoadBalancer(
    ... 
)) 

if condition: 
    lb.add_attribute(ConnectionSettings = elb.ConnectionSettings(
    ... 
)) 

Yat-il un moyen d'y parvenir?

MISE À JOUR: je l'ai réalisé en utilisant une méthode Troposphere cachée, qui fonctionne mais je ne suis pas satisfait:

if condition: 
    lb.__setattr__('ConnectionSettings', elb.ConnectionSettings(
    .... 
)) 

Je suis toujours intéressé par une solution qui ne comporte pas l'aide d'un privé méthode de l'extérieur du module.

Répondre

1

La principale README élude juste en utilisant les noms d'attributs comme ceci:

from troposphere import Template 
import troposphere.elasticloadbalancing as elb 

template = Template() 
webelb = elb.LoadBalancer(
    'ElasticLoadBalancer', 
    Listeners=[ 
     elb.Listener(
      LoadBalancerPort="80", 
      InstancePort="80", 
      Protocol="HTTP", 
     ), 
    ], 
) 

if True: 
    webelb.ConnectionSettings = elb.ConnectionSettings(IdleTimeout=30) 
elasticLB = template.add_resource(webelb) 
print(template.to_json()) 
+0

Merci. Ça marche. J'ai seulement trouvé une référence à cette fonctionnalité dans le fichier README après une lecture très attentive (réglage de 'instance.ImageId'), peut-être que le doc peut le mettre en évidence un peu plus en évidence. –

0

Donc la grande question est - d'où vient la configuration de ConnectionSettings? Dans Cloudformation lui-même (et troposphère), il y a des conditions, des paramètres et la référence AWS :: NoValue. J'utilise ce assez fortement dans le bac de réception RDS modèles:

Voici le paramètre: https://github.com/remind101/stacker/blob/master/stacker/blueprints/rds/base.py#L126 est ici la condition: https://github.com/remind101/stacker/blob/master/stacker/blueprints/rds/base.py#L243 Et voici comment il est utilisé dans une ressource plus tard, le cas échéant - si le paramètre StorageType est vide, nous utilisons AWS: : NoValue, qui est un pseudo Ref pour ne pas avoir réellement défini quelque chose: (Désolé, impossible de poster plus de 2 liens - allez à la ligne 304 dans le même fichier pour voir de quoi je parle)

Si vous ' Cependant, si vous n'utilisez pas les paramètres, et que vous faites toutes vos conditions en python, vous pourriez faire quelque chose de similaire. Quelque chose comme:

connection_setting = condition and <actual connection setting code> or Ref("AWS::NoValue") 

L'autre option est de le faire entièrement en python, qui est essentiellement votre exemple. J'espère que cela aide, il y a beaucoup de façons de gérer cela, y compris la création de deux objets ELB différents (un avec les paramètres de connexion, un sans) et ensuite en choisir un avec le code python (si condition) ou les conditions de cloudformation.

+0

Merci. La condition vient d'un externe.fichier yaml qui est lu par le script Python. Je préfère garder le modèle simple et faire le plus de prise de décision possible dans le code Python. Je vais tester le repli sur 'Ref (" AWS :: NoValue ")' et voir comment ça se passe. –

+0

J'ai testé le réglage de la valeur 'IdleTimeout' sur' AWS :: NoValue' mais j'ai obtenu l'erreur 'Property IdleTimeout ne peut pas être vide.'. Cela ne semble donc pas fonctionner. –

+0

Vous souhaitez que l'attribut ConnectionSettings de l'ELB soit AWS :: NoValue, pas IdleTimeout, puisqu'il s'agit d'un attribut obligatoire d'un objet ConnectionSettings. – phobologic

0

Si la valeur est connue en Python (par exemple, il ne provenir d'un paramètre de CloudFormation), vous pouvez utiliser un dictionnaire pour ajouter des attributs facultatifs aux ressources dans un modèle troposphère:

from troposphere import Template 
import troposphere.elasticloadbalancing as elb 

template = Template() 

my_idle_timeout = 30 # replace this with your method for determining the value 

my_elb_params = {} 
if my_idle_timeout is not None: 
    my_elb_params['ConnectionSettings'] = elb.ConnectionSettings(
     IdleTimeout=my_idle_timeout, 
    ) 

my_elb = template.add_resource(elb.LoadBalancer(
    'ElasticLoadBalancer', 
    Listeners=[ 
     elb.Listener(
      LoadBalancerPort="80", 
      InstancePort="80", 
      Protocol="HTTP", 
     ), 
    ], 
    **my_elb_params, 
)) 

print(template.to_json()) 

Si la valeur provient d'un paramètre CloudFormation, vous devez créer un Condition pour tester la valeur du paramètre et utiliser Ref("AWS::NoValue") si aucune valeur n'a été fournie pour le paramètre, par exemple:

from troposphere import Template, Parameter, Equals, Ref, If 
import troposphere.elasticloadbalancing as elb 

template = Template() 

my_idle_timeout = template.add_parameter(Parameter(
    "ElbIdleTimeout", 
    Description="Idle timeout for the Elastic Load Balancer", 
    Type="Number", 
)) 

no_idle_timeout = "NoIdleTimeout" 
template.add_condition(
    no_idle_timeout, 
    Equals(Ref(my_idle_timeout), ""), 
) 

my_elb = template.add_resource(elb.LoadBalancer(
    'ElasticLoadBalancer', 
    Listeners=[ 
     elb.Listener(
      LoadBalancerPort="80", 
      InstancePort="80", 
      Protocol="HTTP", 
     ), 
    ], 
    ConnectionSettings=If(
     no_idle_timeout, 
     Ref("AWS::NoValue"), 
     elb.ConnectionSettings(
      IdleTimeout=Ref(my_idle_timeout), 
     ), 
    ), 
)) 

print(template.to_json()) 
+0

Voir la réponse acceptée. Il fait déjà exactement ce que j'étais après. Merci. –