SHARE
TWEET

Untitled

a guest Jun 15th, 2017 115 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import sys
  2. from functools import partial
  3.  
  4. import ruamel.yaml
  5.  
  6.  
  7. class AwsFnBase(ruamel.yaml.YAMLObject):
  8.     yaml_loader = ruamel.yaml.RoundTripLoader
  9.     yaml_dumper = ruamel.yaml.RoundTripDumper
  10.     def __init__(self, data, style):
  11.         self._data = data
  12.         self.style = style
  13.  
  14.     @property
  15.     def data(self):
  16.         # override this for custom behavior
  17.         return self._data
  18.  
  19.     @classmethod
  20.     def from_yaml(cls, loader, node, data_type=None):
  21.         data_type = data_type or cls.data_type
  22.         if data_type == 'scalar':
  23.             yield cls(loader.construct_scalar(node), style=node.style)
  24.         elif data_type == 'seq':
  25.             data = ruamel.yaml.comments.CommentedSeq()
  26.             data._yaml_set_line_col(node.start_mark.line, node.start_mark.column)
  27.             if node.flow_style is True:
  28.                 data.fa.set_flow_style()
  29.             elif node.flow_style is False:
  30.                 data.fa.set_block_style()
  31.             if node.comment:
  32.                 data._yaml_add_comment(node.comment)
  33.             yield cls(data, style=node.flow_style)
  34.             data.extend(loader.construct_sequence(node, data, deep=True))
  35.  
  36.     @classmethod
  37.     def to_yaml(cls, dumper, data, data_type=None):
  38.         data_type = data_type or cls.data_type
  39.         if data_type == 'scalar':
  40.             # FIXME: to get it to to put quotes around the scalar, i think we need to modify emitter.py:L585
  41.             # to allow a style in which we don't write quotes
  42.             return dumper.represent_scalar(cls.yaml_tag, data.data, style=data.style or ' ')
  43.         elif data_type == 'seq':
  44.             return dumper.represent_sequence(cls.yaml_tag, data.data, flow_style=data.style or None)
  45.  
  46.  
  47. class Base64(AwsFnBase):
  48.     yaml_tag = u'!Base64'
  49.     data_type = 'scalar'
  50.     @property
  51.     def value(self):
  52.         return self._data
  53.  
  54. class FindInMap(AwsFnBase):
  55.     yaml_tag = u'!FindInMap'
  56.     data_type = 'seq'
  57.     @property
  58.     def map_name(self):
  59.         return self._data[0]
  60.     @property
  61.     def top_level_key(self):
  62.         return self._data[1]
  63.     @property
  64.     def second_level_key(self):
  65.         return self._data[2]
  66.  
  67. class GetAtt(AwsFnBase):
  68.     yaml_tag = u'!GetAtt'
  69.     data_type = 'scalar'
  70.     @property
  71.     def logical_id(self):
  72.         return self._data.split('.')[0]
  73.     @property
  74.     def attribute(self):
  75.         return self._data.split('.')[1]
  76.  
  77. class GetAZs(AwsFnBase):
  78.     yaml_tag = u'!GetAZs'
  79.     data_type = 'scalar'
  80.     @property
  81.     def region(self):
  82.         return self._data
  83.  
  84. class ImportValue(AwsFnBase):
  85.     yaml_tag = u'!ImportValue'
  86.     data_type = 'scalar'
  87.     @property
  88.     def data(self):
  89.         return self._data
  90.  
  91. class Join(AwsFnBase):
  92.     yaml_tag = u'!Join'
  93.     data_type = 'seq'
  94.     @property
  95.     def delimiter(self):
  96.         return self._data[0]
  97.     @property
  98.     def values(self):
  99.         return self._data[1]
  100.  
  101. class Select(AwsFnBase):
  102.     yaml_tag = u'!Select'
  103.     data_type = 'seq'
  104.     @property
  105.     def index(self):
  106.         return self._data[0]
  107.     @property
  108.     def values(self):
  109.         return self._data[1]
  110.  
  111. class Split(AwsFnBase):
  112.     yaml_tag = u'!Split'
  113.     data_type = 'seq'
  114.     @property
  115.     def delimiter(self):
  116.         return self._data[0]
  117.     @property
  118.     def source(self):
  119.         return self._data[1]
  120.  
  121. class Sub(AwsFnBase):
  122.     yaml_tag = u'!Sub'
  123.     @property
  124.     def source(self):
  125.         return self._data[0]
  126.     @property
  127.     def values(self):
  128.         if len(self._data) > 1:
  129.             return self._data[1]
  130.         return None
  131.     @classmethod
  132.     def from_yaml(cls, loader, node):
  133.         try:
  134.             data = super(Sub, cls).from_yaml(loader, node, data_type='seq')
  135.         except yaml.constructor.ConstructorError:
  136.             data = super(Sub, cls).from_yaml(loader, node, data_type='scalar')
  137.         return data
  138.     @classmethod
  139.     def to_yaml(cls, dumper, data):
  140.         if data.values is None:
  141.             return super(Sub, cls).to_yaml(dumper, data, data_type='scalar')
  142.         else:
  143.             return super(Sub, cls).to_yaml(dumper, data, data_type='seq')
  144.  
  145. class Ref(AwsFnBase):
  146.     yaml_tag = u'!Ref'
  147.     data_type = 'scalar'
  148.     @property
  149.     def logical_id(self):
  150.         return self._data
  151.  
  152. class Condition(AwsFnBase):
  153.     yaml_tag = u'!Condition'
  154.     data_type = 'scalar'
  155.     @property
  156.     def condition(self):
  157.         return self._data
  158.  
  159. class And(AwsFnBase):
  160.     yaml_tag = u'!And'
  161.     data_type = 'seq'
  162.     @property
  163.     def conditions(self):
  164.         return self._data
  165.  
  166. class Equals(AwsFnBase):
  167.     yaml_tag = u'!Equals'
  168.     data_type = 'seq'
  169.     @property
  170.     def value1(self):
  171.         return self._data[0]
  172.     @property
  173.     def value2(self):
  174.         return self._data[1]
  175.  
  176. class If(AwsFnBase):
  177.     yaml_tag = u'!If'
  178.     data_type = 'seq'
  179.     @property
  180.     def condition(self):
  181.         return self._data[0]
  182.     @property
  183.     def if_true(self):
  184.         return self._data[1]
  185.     @property
  186.     def if_false(self):
  187.         return self._data[2]
  188.  
  189. class Not(AwsFnBase):
  190.     yaml_tag = u'!Not'
  191.     data_type = 'seq'
  192.     @property
  193.     def condition(self):
  194.         return self._data[0]
  195.  
  196. class Or(AwsFnBase):
  197.     yaml_tag = u'!Or'
  198.     data_type = 'seq'
  199.     @property
  200.     def conditions(self):
  201.         return self._data
  202.  
  203. # note, whitespaces around the brackets & braces have been normalized so they
  204. # wouldn't produce false mismatches.  otherwise, ruamel does normalize the
  205. # spacing
  206. document = """
  207. TestBase64:
  208.   Long:
  209.     Fn::Base64: valueToEncode
  210.   Short: !Base64 valueToEncode
  211. TestFindInMap:
  212.   Long1:
  213.     Fn::FindInMap: [MapName, TopLevelKey, SecondLevelKey]
  214.   Long2:
  215.     Fn::FindInMap:
  216.       - MapName
  217.       - TopLevelKey
  218.       - SecondLevelKey
  219.   Short1: !FindInMap [Mapname, TopLevelKey, SecondLevelKey]
  220.   Short2: !FindInMap
  221.     - MapName
  222.     - TopLevelKey
  223.     - SecondLevelKey
  224. TestGetAtt:
  225.   Long1:
  226.     Fn::GetAtt: [logicalName, attributeName]
  227.   Long2:
  228.     Fn::GetAtt:
  229.       - logicalName
  230.       - attributeName
  231.   Short: !GetAtt logicalName.attributeName
  232. TestGetAZs:
  233.   Long:
  234.     Fn::GetAZs: region
  235.   Short: !GetAZs region
  236. TestImportValue:
  237.   Long:
  238.     Fn::ImportValue: sharedValueToImport
  239.   Short: !ImportValue sharedValueToImport
  240. TestJoin:
  241.   Long1:
  242.       Fn::Join: [delimiter, [comma, delimited, list, of, values]]
  243.   Long2:
  244.       Fn::Join:
  245.         - delimiter
  246.         - [comma, delimited, list, of, values]
  247.   Long3:
  248.       Fn::Join:
  249.         - delimiter
  250.         - - comma
  251.           - delimited
  252.           - list
  253.           - of
  254.           - values
  255.   Short1: !Join [delimiter, [comma, delimited, list, of, values]]
  256.   Short2: !Join
  257.     - delimiter
  258.     - [comma, delimited, list, of, values]
  259.   Short3: !Join
  260.     - delimiter
  261.     - - comma
  262.       - delimited
  263.       - list
  264.       - of
  265.       - values
  266. TestSelect:
  267.   Long1:
  268.       Fn::Select: [index, [list, of, objects]]
  269.   Long2:
  270.       Fn::Select:
  271.         - index
  272.         - [list, of, objects]
  273.   Long3:
  274.       Fn::Select:
  275.         - index
  276.         - - list
  277.           - of
  278.           - objects
  279.   Short1: !Select [index, [list, of, objects]]
  280.   Short2: !Select
  281.     - index
  282.     - [list, of, objects]
  283.   Short3: !Select
  284.     - index
  285.     - - list
  286.       - of
  287.       - objects
  288. TestSplit:
  289.   Long1:
  290.       Fn::Split: [delimiter, source]
  291.   Long2:
  292.       Fn::Split:
  293.         - delimiter
  294.         - source
  295.   Short1: !Split [delimiter, source]
  296.   Short2: !Split
  297.     - delimiter
  298.     - source
  299. TestSub:
  300.   Long1:
  301.     Fn::Sub: [source, {Key1: Value1, Key2: Value2}]
  302.   Long2:
  303.     Fn::Sub:
  304.       - source
  305.       - {Key1: Value1, Key2: Value2}
  306.   Long3:
  307.     Fn::Sub:
  308.       - source
  309.       - Key1: Value1
  310.         Key2: Value2
  311.   Long4:
  312.     Fn::Sub: source
  313.   Short1: !Sub [source, {Key1: Value1, Key2: Value2}]
  314.   Short2: !Sub
  315.       - source
  316.       - {Key1: Value1, Key2: Value2}
  317.   Short3: !Sub
  318.       - source
  319.       - Key1: Value1
  320.         Key2: Value2
  321.   Short4: Sub! source
  322. TestRef:
  323.   Long:
  324.     Ref: logicalName
  325.   Short: !Ref logicalName
  326. TestCondition:
  327.   Short: !Condition Foo
  328. TestAnd:
  329.   Long:
  330.     Fn::And: [conditon1, condition2]
  331.   Short: !And [condition, condition2]
  332.   Examples:
  333.     MyAndConition: !And
  334.       - !Equals [sg-mysgsgroup, !Ref ASecurityGroup]
  335.       - !Condition SomeOtherCondition
  336. TestEquals:
  337.   Long:
  338.     Fn::Equals: [value1, value2]
  339.   Short: !Equals [value1, value2]
  340.   Examples:
  341.     UseProdCondition:
  342.       !Equals [!Ref EnvironmentType, prod]
  343. TestIf:
  344.   Long:
  345.     Fn::If: [condition_name, value_if_true, value_if_false]
  346.   Short: !If [condition_name, value_if_true, value_if_false]
  347.   Examples:
  348.     SecurityGroups:
  349.       - !If [CreateNewSecurityGroup, !Ref NewSecurityGroup, !Ref ExistingSecurityGroup]
  350.     SecurityGroupId:
  351.       Description: Group ID of the security group used.
  352.       Value: !If [CreateNewSecurityGroup, !Ref NewSecurityGroup, !Ref ExistingSecurityGroup]
  353.     MyDB:
  354.       Type: "AWS::RDS::DBInstance"
  355.       Properties:
  356.         AllocatedStorage: 5
  357.         DBInstanceClass: db.m1.small
  358.         Engine: MySQL
  359.         EngineVersion: 5.5
  360.         MasterUsername: !Ref DBUser
  361.         MasterUserPassword: !Ref DBPassword
  362.         DBParameterGroupName: !Ref MyRDSParamGroup
  363.         DBSnapshotIdentifier:
  364.           !If [UseDBSnapshot, !Ref DBSnapshotName, !Ref "AWS::NoValue"]
  365.     UpdatePolicy:
  366.       AutoScalingRollingUpdate:
  367.         !If
  368.           - RollingUpdates
  369.           -
  370.             MaxBatchSize: 2
  371.             MinInstancesInService: 2
  372.             PauseTime: PT0M30S
  373.           - !Ref "AWS::NoValue"
  374. TestNot:
  375.   Long:
  376.     Fn::Not: [condition]
  377.   Short: !Not [condition]
  378.   Examples:
  379.     MyNotCondition:
  380.       !Not [!Equals [!Ref EnvironmentType, prod]]
  381. TestOr:
  382.   Long:
  383.     Fn::Or: [conditon1, condition2]
  384.   Short: !Or [condition, condition2]
  385.   Examples:
  386.     MyOrConition:
  387.       !Or [!Equals [sg-mysgsgroup, !Ref ASecurityGroup], !Condition SomeOtherCondition]
  388. """
  389.  
  390. open('expected.yml', 'w').write(document)
  391. result = ruamel.yaml.dump(ruamel.yaml.load(document, Loader=ruamel.yaml.RoundTripLoader, preserve_quotes=True), Dumper=ruamel.yaml.RoundTripDumper)
  392. open('actual.yml', 'w').write(result)
  393.  
  394. print "vimdiff -c 'set diffopt+=iwhite' expected.yml actual.yml"
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top