2
2
from __future__ import division
3
3
from __future__ import absolute_import
4
4
import logging
5
+ import json
6
+ import sys
5
7
6
8
from .base import BaseAction
7
9
from .. import exceptions
8
10
9
11
logger = logging .getLogger (__name__ )
10
12
11
13
14
+ class Exporter (object ):
15
+ def __init__ (self , context ):
16
+ self .context = context
17
+
18
+ def start (self ):
19
+ pass
20
+
21
+ def start_stack (self , stack ):
22
+ pass
23
+
24
+ def end_stack (self , stack ):
25
+ pass
26
+
27
+ def write_output (self , key , value ):
28
+ pass
29
+
30
+ def finish (self ):
31
+ pass
32
+
33
+
34
+ class JsonExporter (Exporter ):
35
+ def start (self ):
36
+ self .current_outputs = {}
37
+ self .stacks = {}
38
+
39
+ def start_stack (self , stack ):
40
+ self .current_outputs = {}
41
+
42
+ def end_stack (self , stack ):
43
+ self .stacks [stack .name ] = {
44
+ "outputs" : self .current_outputs ,
45
+ "fqn" : stack .fqn
46
+ }
47
+ self .current_outputs = {}
48
+
49
+ def write_output (self , key , value ):
50
+ self .current_outputs [key ] = value
51
+
52
+ def finish (self ):
53
+ json_data = json .dumps ({'stacks' : self .stacks }, indent = 4 )
54
+ sys .stdout .write (json_data )
55
+ sys .stdout .write ('\n ' )
56
+ sys .stdout .flush ()
57
+
58
+
59
+ class PlainExporter (Exporter ):
60
+ def start (self ):
61
+ self .current_stack = None
62
+
63
+ def start_stack (self , stack ):
64
+ self .current_stack = stack .name
65
+
66
+ def end_stack (self , stack ):
67
+ self .current_stack = None
68
+
69
+ def write_output (self , key , value ):
70
+ line = '{}.{}={}\n ' .format (self .current_stack , key , value )
71
+ sys .stdout .write (line )
72
+
73
+ def finish (self ):
74
+ sys .stdout .flush ()
75
+
76
+
77
+ class LogExporter (Exporter ):
78
+ def start (self ):
79
+ logger .info ('Outputs for stacks: %s' , self .context .get_fqn ())
80
+
81
+ def start_stack (self , stack ):
82
+ logger .info ('%s:' , stack .fqn )
83
+
84
+ def write_output (self , key , value ):
85
+ logger .info ('\t {}: {}' .format (key , value ))
86
+
87
+
88
+ EXPORTER_CLASSES = {
89
+ 'json' : JsonExporter ,
90
+ 'log' : LogExporter ,
91
+ 'plain' : PlainExporter
92
+ }
93
+
94
+ OUTPUT_FORMATS = list (EXPORTER_CLASSES .keys ())
95
+
96
+
12
97
class Action (BaseAction ):
13
98
"""Get information on CloudFormation stacks.
14
99
15
100
Displays the outputs for the set of CloudFormation stacks.
16
101
17
102
"""
18
103
19
- def run (self , * args , ** kwargs ):
20
- logger .info ('Outputs for stacks: %s' , self .context .get_fqn ())
104
+ @classmethod
105
+ def build_exporter (cls , name ):
106
+ try :
107
+ exporter_cls = EXPORTER_CLASSES [name ]
108
+ except KeyError :
109
+ logger .error ('Unknown output format "{}"' .format (name ))
110
+ raise
111
+
112
+ try :
113
+ return exporter_cls ()
114
+ except Exception :
115
+ logger .exception ('Failed to create exporter instance' )
116
+ raise
117
+
118
+ def run (self , output_format = 'log' , * args , ** kwargs ):
21
119
if not self .context .get_stacks ():
22
120
logger .warn ('WARNING: No stacks detected (error in config?)' )
121
+ return
122
+
123
+ exporter = self .build_exporter (output_format )
124
+ exporter .start (self .context )
125
+
23
126
for stack in self .context .get_stacks ():
24
127
provider = self .build_provider (stack )
25
128
@@ -29,11 +132,13 @@ def run(self, *args, **kwargs):
29
132
logger .info ('Stack "%s" does not exist.' % (stack .fqn ,))
30
133
continue
31
134
32
- logger .info ('%s:' , stack .fqn )
135
+ exporter .start_stack (stack )
136
+
33
137
if 'Outputs' in provider_stack :
34
138
for output in provider_stack ['Outputs' ]:
35
- logger .info (
36
- '\t %s: %s' ,
37
- output ['OutputKey' ],
38
- output ['OutputValue' ]
39
- )
139
+ exporter .write_output (output ['OutputKey' ],
140
+ output ['OutputValue' ])
141
+
142
+ exporter .end_stack (stack )
143
+
144
+ exporter .finish ()
0 commit comments