aws-edges 0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +644 -0
- data/README.md +163 -0
- data/Rakefile +0 -0
- data/SHA256 +1 -0
- data/aws-edges.gemspec +17 -0
- data/bin/aws-edges +113 -0
- data/examples/config.yml +34 -0
- data/examples/iam.yml +23 -0
- data/lib/aws-edges.rb +19 -0
- data/lib/aws-edges/config.rb +166 -0
- data/lib/aws-edges/ec2.rb +53 -0
- data/lib/aws-edges/graph.rb +190 -0
- data/lib/aws-edges/iam.rb +91 -0
- data/lib/aws-edges/rds.rb +32 -0
- data/lib/aws-edges/redshift.rb +40 -0
- data/lib/aws-edges/subnet.rb +21 -0
- data/lib/aws-edges/version.rb +5 -0
- data/lib/aws-edges/vpc.rb +19 -0
- metadata +102 -0
data/README.md
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
# aws-edges
|
2
|
+
|
3
|
+
## Overview
|
4
|
+
|
5
|
+
**aws-edges** allows you to created high level graphviz digraphs of your AWS components. Currently this does not cover everything returned from the AWS Ruby SDK, only select components so far.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
```
|
10
|
+
$ gem install aws-edges
|
11
|
+
```
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
```
|
16
|
+
$ ./aws-edges -h
|
17
|
+
Usage: aws-edges [options]
|
18
|
+
-c, --config [CONFIG_FILE] Config file
|
19
|
+
-f, --config-format [yaml|json] Config file format (yaml or json)
|
20
|
+
-a [ACCESS_KEY_ID], AWS Access Key ID
|
21
|
+
--access-key-id
|
22
|
+
-s [SECRET_ACCESS_KEY], AWS Secret Access Key
|
23
|
+
--secret-key-id
|
24
|
+
-r, --region [REGION] AWS Region (ie: us-east-1)
|
25
|
+
-C, --list-colors Prints out a list of supported colors
|
26
|
+
-S, --list-shapes Prints out a list of supported shapes
|
27
|
+
-?, --help Shows this message
|
28
|
+
```
|
29
|
+
|
30
|
+
## Configuration Example
|
31
|
+
|
32
|
+
There are some examples located in the 'examples' directory. Below is one of them. The *sources* section tells the *aws-edges* script what to pull from AWS. And the rest is pretty self explanatory.
|
33
|
+
|
34
|
+
The basic structure is show below. The `name` key provides the output name of the graph generated. Which will generate both a *.dot* and *.png* file by default.
|
35
|
+
|
36
|
+
```
|
37
|
+
---
|
38
|
+
name: "my graph name"
|
39
|
+
rotate: true
|
40
|
+
sources:
|
41
|
+
- "ec2"
|
42
|
+
- "subnet"
|
43
|
+
edges:
|
44
|
+
-
|
45
|
+
from: "ec2_hypervisor"
|
46
|
+
from_color: "orange"
|
47
|
+
from_shape: "invhouse"
|
48
|
+
to: "ec2_virtualization_type"
|
49
|
+
to_color: "coral"
|
50
|
+
to_shape: "diamond"
|
51
|
+
-
|
52
|
+
from: "ec2_virtualization_type"
|
53
|
+
to: "ec2_instance_id"
|
54
|
+
-
|
55
|
+
from: "ec2_instance_id"
|
56
|
+
from_color: "dodgerblue"
|
57
|
+
to: "ec2_subnet_id"
|
58
|
+
to_color: "darkturquoise"
|
59
|
+
-
|
60
|
+
from: "subnet_cidr_block"
|
61
|
+
to: "subnet_availability_zone"
|
62
|
+
to_color: "crimson"
|
63
|
+
cluster:
|
64
|
+
label: "Subnet Legend"
|
65
|
+
edges:
|
66
|
+
-
|
67
|
+
from: "subnet_subnet_id"
|
68
|
+
to: "subnet_cidr_block"
|
69
|
+
to_color: "firebrick"
|
70
|
+
```
|
71
|
+
### Specifying output format
|
72
|
+
|
73
|
+
If you like to save the graph in a different format other than the default `png`. You can specify the `save_as: "pdf"` or some other image format such as tiff.
|
74
|
+
|
75
|
+
### Mapping a 'many' node
|
76
|
+
|
77
|
+
What is a 'many' node? Simply put, it is a object containing many entries or an Hash of an Array of Hashes.
|
78
|
+
|
79
|
+
The syntax for mapping a 'many' node is `"redshift_cluster_nodes-private_ip_address"`. The `-` character indicating that `redshift_cluster_nodes` is an Array and you want all the `private_ip_address` objects/property.
|
80
|
+
|
81
|
+
### Grouping edges
|
82
|
+
|
83
|
+
Sometime you would like to visually group a set or sets of edges together so they appear in a container. This can help distinguish the relation between edge objects. You will need to group your objects using the `cluster` key and can label it using something like; `label: "My VPCs"`. Below is an example config snippet:
|
84
|
+
|
85
|
+
```
|
86
|
+
---
|
87
|
+
name: "example"
|
88
|
+
rotate: true
|
89
|
+
sources:
|
90
|
+
- "vpc"
|
91
|
+
cluster:
|
92
|
+
label: "Virtual Private Clouds"
|
93
|
+
edges:
|
94
|
+
-
|
95
|
+
to: "vpc_cidr_block"
|
96
|
+
from: "vpc_vpc_id"
|
97
|
+
```
|
98
|
+
|
99
|
+
### Changing the layout
|
100
|
+
|
101
|
+
By default graphs are generated in a horizontal top down structure. If you like a vertical left to right representation you will need to set the `rotate: true` property in your config like so:
|
102
|
+
|
103
|
+
```
|
104
|
+
$ cat myconfig.yml
|
105
|
+
---
|
106
|
+
name: "example"
|
107
|
+
rotate: true
|
108
|
+
sources:
|
109
|
+
- "vpc"
|
110
|
+
- "ec2"
|
111
|
+
- "subnet"
|
112
|
+
```
|
113
|
+
|
114
|
+
### Adding edge colors
|
115
|
+
|
116
|
+
In order to make it easier to identify groups of like edges, coloring (fill) support has been added. Being that this utilizes the `graph` gem it supports all of the colors supported by it.
|
117
|
+
|
118
|
+
[Visit Graphviz Colors to see what they look like](http://www.graphviz.org/content/color-names)
|
119
|
+
|
120
|
+
To see what colors are available run the following command:
|
121
|
+
|
122
|
+
```
|
123
|
+
$ aws-edges -C
|
124
|
+
```
|
125
|
+
|
126
|
+
or
|
127
|
+
|
128
|
+
```
|
129
|
+
$ aws-edges --list-colors
|
130
|
+
```
|
131
|
+
|
132
|
+
To use colors, in your config simply add either `to_color: "orange"` or `from_color: "brown"` to the `edges` section of the config. (See example above)
|
133
|
+
|
134
|
+
### Adding edges shapes
|
135
|
+
|
136
|
+
In order to make it easier to identify *like* edges, shape support has been added. As with colors, it supports the shapes available to the `graph` gem on which the gem requires.
|
137
|
+
|
138
|
+
[Visit Graphviz Shapes to see what the look like](http://www.graphviz.org/content/node-shapes)
|
139
|
+
|
140
|
+
To list the supported shapes, run the following command:
|
141
|
+
|
142
|
+
```
|
143
|
+
$ aws-edges -S
|
144
|
+
```
|
145
|
+
|
146
|
+
or
|
147
|
+
|
148
|
+
```
|
149
|
+
$ aws-edges --list-shapes
|
150
|
+
```
|
151
|
+
|
152
|
+
To use shapes, in your config simply add either `to_shape: "triangle"` or `from_shape: "egg"` to the `edges` section of the config. (See example above)
|
153
|
+
|
154
|
+
## Hacking and Contributing
|
155
|
+
|
156
|
+
Fork it and start hacking. Below is a brief summary of the layout of the code.
|
157
|
+
|
158
|
+
Inside 'lib/aws-edges' are the classes used. These are kind of categorized by the AWS Ruby SDK "describe*" methods and client types. For example, *subnet.rb* only parses the EC2 *describe-subnets* output. Each class file contains an *initialize* method and a *supported_fields* public method.
|
159
|
+
|
160
|
+
The 'config.rb' is used to parse the configuration file (which can be either yaml or json). It uses the *supported_fields* method to validate what is entered in the config. It also contains a *valid_keys*, *valid_sources*, *valid_prefixes*.
|
161
|
+
|
162
|
+
'graph.rb' is what creates the graphs.
|
163
|
+
|
data/Rakefile
ADDED
File without changes
|
data/SHA256
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
9076d60c640f2c8a55ca30f030897529861201eb9454fc8de39c8ef16d2e1281 aws-edges-0.7.gem
|
data/aws-edges.gemspec
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
|
2
|
+
require 'aws-edges/version'
|
3
|
+
|
4
|
+
Gem::Specification.new 'aws-edges', AWSEdges::VERSION do |s|
|
5
|
+
s.license = 'GPL-3.0'
|
6
|
+
s.date = '2016-04-07'
|
7
|
+
s.summary = 'Simple AWS architecture charts'
|
8
|
+
s.description = 'AWS Edges is used to chart out your AWS environments'
|
9
|
+
s.files = `git ls-files`.split("\n") - %w[]
|
10
|
+
s.author = 'Rick Briganti'
|
11
|
+
s.email = 'jeviolle@newaliases.org'
|
12
|
+
s.homepage = 'http://github.com/jeviolle/aws-edges'
|
13
|
+
s.add_runtime_dependency 'aws-sdk', '~> 1.34', '>=1.34.0'
|
14
|
+
s.add_runtime_dependency 'graph', '~> 2.6', '>=2.6.0'
|
15
|
+
s.bindir = 'bin'
|
16
|
+
s.executables << 'aws-edges'
|
17
|
+
end
|
data/bin/aws-edges
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
|
4
|
+
$LOAD_PATH.push(File.absolute_path(File.dirname(__FILE__)) + '/../lib')
|
5
|
+
|
6
|
+
require 'aws-sdk'
|
7
|
+
require 'aws-edges'
|
8
|
+
require 'optparse'
|
9
|
+
require 'pp'
|
10
|
+
|
11
|
+
options = {}
|
12
|
+
OptionParser.new do |opts|
|
13
|
+
opts.on('-c','--config [CONFIG_FILE]', 'Config file') do |v|
|
14
|
+
options[:config] = v
|
15
|
+
end
|
16
|
+
opts.on('-a','--access-key-id [ACCESS_KEY_ID]', 'AWS Access Key ID') do |v|
|
17
|
+
options[:access_key_id] = v
|
18
|
+
end
|
19
|
+
opts.on('-s','--secret-key-id [SECRET_ACCESS_KEY]', 'AWS Secret Access Key') do |v|
|
20
|
+
options[:secret_access_key] = v
|
21
|
+
end
|
22
|
+
opts.on('-r','--region [REGION]', 'AWS Region (ie: us-east-1)') do |v|
|
23
|
+
options[:region] = v
|
24
|
+
end
|
25
|
+
opts.on('-C','--list-colors', 'Prints out a list of supported colors') do |v|
|
26
|
+
options[:colors] = v
|
27
|
+
end
|
28
|
+
opts.on('-S','--list-shapes', 'Prints out a list of supported shapes') do |v|
|
29
|
+
options[:shapes] = v
|
30
|
+
end
|
31
|
+
opts.on('-?','--help','Shows this message') do
|
32
|
+
puts opts
|
33
|
+
exit 255
|
34
|
+
end
|
35
|
+
end.parse!
|
36
|
+
|
37
|
+
class Array
|
38
|
+
def longest_word
|
39
|
+
group_by(&:size).max.last
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def display_supported(type)
|
44
|
+
display_types = []
|
45
|
+
|
46
|
+
case type
|
47
|
+
when "colors"
|
48
|
+
puts
|
49
|
+
puts "http://graphviz.org/content/color-names"
|
50
|
+
display_types = digraph.class::BOLD_COLORS + digraph.class::LIGHT_COLORS
|
51
|
+
when "shapes"
|
52
|
+
puts
|
53
|
+
puts "http://graphviz.org/content/node-shapes"
|
54
|
+
display_types = digraph.class::SHAPES
|
55
|
+
end
|
56
|
+
|
57
|
+
maxlen = display_types.longest_word[0].length
|
58
|
+
puts
|
59
|
+
puts "Supported #{type.capitalize}"
|
60
|
+
puts "----------------"
|
61
|
+
display_types.each_with_index do |obj, idx|
|
62
|
+
if idx.to_i.even?
|
63
|
+
print obj
|
64
|
+
(maxlen - obj.length).times{print " "}
|
65
|
+
print "\t"
|
66
|
+
end
|
67
|
+
puts "#{obj}" if idx.to_i.odd?
|
68
|
+
end
|
69
|
+
puts
|
70
|
+
end
|
71
|
+
|
72
|
+
if options[:colors] and options[:shapes]
|
73
|
+
%w/colors shapes/.each{|i| display_supported i}
|
74
|
+
exit 255
|
75
|
+
elsif options[:colors]
|
76
|
+
display_supported "colors"
|
77
|
+
exit 255
|
78
|
+
elsif options[:shapes]
|
79
|
+
display_supported "shapes"
|
80
|
+
exit 255
|
81
|
+
end
|
82
|
+
|
83
|
+
unless options[:access_key_id] and options[:secret_access_key] and options[:region] and options[:config]
|
84
|
+
puts "[ERROR] Missing required option, please run with '--help' for more info"
|
85
|
+
exit 1
|
86
|
+
end
|
87
|
+
|
88
|
+
AWS.config({
|
89
|
+
:access_key_id => options[:access_key_id],
|
90
|
+
:secret_access_key => options[:secret_access_key],
|
91
|
+
:region => options[:region]
|
92
|
+
})
|
93
|
+
|
94
|
+
# parse config
|
95
|
+
config = AWSEdges::Config.new
|
96
|
+
config_data = config.parse(options[:config])
|
97
|
+
|
98
|
+
aws_sources = config_data.delete('sources')
|
99
|
+
aws_data = {
|
100
|
+
:vpc => {}, :subnet => {}, :ec2 => {},
|
101
|
+
:rds => {}, :redshift => {}, :iam => {}
|
102
|
+
}
|
103
|
+
# run aws clients to describe and retrieve data
|
104
|
+
aws_data[:iam] = AWSEdges::IAM.new(AWS::IAM::Client.new).nodes if aws_sources.include?("iam")
|
105
|
+
aws_data[:vpc] = AWSEdges::VPC.new(AWS::EC2::Client.new.describe_vpcs.data).nodes if aws_sources.include?("vpc")
|
106
|
+
aws_data[:subnet] = AWSEdges::Subnet.new(AWS::EC2::Client.new.describe_subnets.data).nodes if aws_sources.include?("subnet")
|
107
|
+
aws_data[:ec2] = AWSEdges::EC2.new(AWS::EC2::Client.new.describe_instances.data).nodes if aws_sources.include?("ec2")
|
108
|
+
aws_data[:rds] = AWSEdges::RDS.new(AWS::RDS::Client.new.describe_db_instances.data).nodes if aws_sources.include?("rds")
|
109
|
+
aws_data[:redshift] = AWSEdges::Redshift.new(AWS::Redshift::Client.new.describe_clusters.data).nodes if aws_sources.include?("redshift")
|
110
|
+
|
111
|
+
# graph a graph based on the config and inputs
|
112
|
+
grapher = AWSEdges::Graph.new(config_data, aws_data)
|
113
|
+
grapher.create_graph()
|
data/examples/config.yml
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
---
|
2
|
+
name: "my graph name"
|
3
|
+
rotate: true
|
4
|
+
sources:
|
5
|
+
- "ec2"
|
6
|
+
- "subnet"
|
7
|
+
edges:
|
8
|
+
-
|
9
|
+
from: "ec2_hypervisor"
|
10
|
+
from_color: "orange"
|
11
|
+
from_shape: "invhouse"
|
12
|
+
to: "ec2_virtualization_type"
|
13
|
+
to_color: "coral"
|
14
|
+
to_shape: "diamond"
|
15
|
+
-
|
16
|
+
from: "ec2_virtualization_type"
|
17
|
+
to: "ec2_instance_id"
|
18
|
+
-
|
19
|
+
from: "ec2_instance_id"
|
20
|
+
from_color: "dodgerblue"
|
21
|
+
to: "ec2_subnet_id"
|
22
|
+
to_color: "darkturquoise"
|
23
|
+
-
|
24
|
+
from: "subnet_cidr_block"
|
25
|
+
to: "subnet_availability_zone"
|
26
|
+
to_color: "crimson"
|
27
|
+
cluster:
|
28
|
+
label: "Subnet Legend"
|
29
|
+
edges:
|
30
|
+
-
|
31
|
+
from: "subnet_subnet_id"
|
32
|
+
to: "subnet_cidr_block"
|
33
|
+
to_color: "firebrick"
|
34
|
+
|
data/examples/iam.yml
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
---
|
2
|
+
name: "iam_structure"
|
3
|
+
rotate: True
|
4
|
+
sources:
|
5
|
+
- "iam"
|
6
|
+
edges:
|
7
|
+
-
|
8
|
+
from_color: "lightseagreen"
|
9
|
+
from: "iam_user_name"
|
10
|
+
to_shape: "note"
|
11
|
+
to_color: "peru"
|
12
|
+
to: "iam_user_policies-policy_name"
|
13
|
+
-
|
14
|
+
from_color: "lightseagreen"
|
15
|
+
from: "iam_users-user_name"
|
16
|
+
to: "iam_group_name"
|
17
|
+
-
|
18
|
+
from_shape: "folder"
|
19
|
+
from_color: "orange"
|
20
|
+
from: "iam_group_name"
|
21
|
+
to: "iam_group_policies-policy_name"
|
22
|
+
to_color: "peru"
|
23
|
+
to_shape: "note"
|
data/lib/aws-edges.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'yaml'
|
3
|
+
require 'graph'
|
4
|
+
require 'aws-edges/vpc.rb'
|
5
|
+
require 'aws-edges/subnet.rb'
|
6
|
+
require 'aws-edges/iam.rb'
|
7
|
+
require 'aws-edges/ec2.rb'
|
8
|
+
require 'aws-edges/rds.rb'
|
9
|
+
require 'aws-edges/redshift.rb'
|
10
|
+
require 'aws-edges/version.rb'
|
11
|
+
require 'aws-edges/config.rb'
|
12
|
+
require 'aws-edges/graph.rb'
|
13
|
+
|
14
|
+
##
|
15
|
+
# AWS Edges creates a simple chart of your
|
16
|
+
# current AWS environment.
|
17
|
+
#
|
18
|
+
module AWSEdges
|
19
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
module AWSEdges
|
2
|
+
class Config
|
3
|
+
@@valid_keys = ["name", "sources", "cluster", "label", "edges",
|
4
|
+
"from", "from_shape", "from_color",
|
5
|
+
"to", "to_shape", "to_color" ,"rotate", "save_as"]
|
6
|
+
@@valid_sources = ["VPC","EC2","RDS","Redshift","Subnet","IAM"]
|
7
|
+
@@valid_prefixes = @@valid_sources
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@node_types = @@valid_sources.map{|s|
|
11
|
+
eval "AWSEdges::#{s}.supported_fields.map{|f| s.downcase + '_' + f}"
|
12
|
+
}.flatten
|
13
|
+
end
|
14
|
+
|
15
|
+
def msg_and_exit(msg)
|
16
|
+
puts msg
|
17
|
+
exit 1
|
18
|
+
end
|
19
|
+
|
20
|
+
##
|
21
|
+
# Validate the source section of the config file
|
22
|
+
#
|
23
|
+
def validate_sources(sources)
|
24
|
+
msg_and_exit("No sources specified in the config") if sources.nil?
|
25
|
+
sources.each do |source|
|
26
|
+
unless @@valid_sources.map{|i| i.downcase}.include?(source)
|
27
|
+
msg_and_exit("Invalid source detected in config: #{source}")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# Verify that a graph name is specified in the config
|
34
|
+
#
|
35
|
+
def validate_name(graph_name)
|
36
|
+
msg_and_exit("No graph name specified in the config") if graph_name.nil?
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Confirm that from and to edges are specified properly and are
|
41
|
+
# not a many-to-many relationship
|
42
|
+
def validate_nodes(hashed_data)
|
43
|
+
nodes = []
|
44
|
+
hashed_data.each do |k,v|
|
45
|
+
if k == "edges"
|
46
|
+
v.each{|e|
|
47
|
+
if e["from"].include?('-') and e["to"].include?('-')
|
48
|
+
msg_and_exit("Error: from many to many edges detected in config:\n (#{e['from']}) -> (#{e['to']})")
|
49
|
+
end
|
50
|
+
nodes.push e["from"]
|
51
|
+
nodes.push e["to"]
|
52
|
+
}
|
53
|
+
end
|
54
|
+
nodes.push(validate_nodes(v)) if v.class == Hash
|
55
|
+
end
|
56
|
+
nodes.flatten.uniq.each do |u|
|
57
|
+
unless @node_types.include?(u)
|
58
|
+
msg_and_exit("Invalid edge node specified: #{u}")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
##
|
64
|
+
# Internal method for testing a color
|
65
|
+
private def test_color(color)
|
66
|
+
colors = digraph.class::BOLD_COLORS + digraph.class::LIGHT_COLORS
|
67
|
+
msg_and_exit("Invalid color specified: #{color}") unless colors.include?(color)
|
68
|
+
end
|
69
|
+
|
70
|
+
##
|
71
|
+
# Verify that the colors defined are supported by the
|
72
|
+
# underlying Graph gem
|
73
|
+
def validate_colors(hashed_data)
|
74
|
+
hashed_data.each do |k,v|
|
75
|
+
if k == "edges"
|
76
|
+
v.each{|e|
|
77
|
+
if e["from_color"]
|
78
|
+
test_color(e["from_color"])
|
79
|
+
end
|
80
|
+
|
81
|
+
if e["to_color"]
|
82
|
+
test_color(e["to_color"])
|
83
|
+
end
|
84
|
+
}
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
##
|
90
|
+
# Internal method for testing a shape
|
91
|
+
private def test_shape(shape)
|
92
|
+
shapes = digraph.class::SHAPES
|
93
|
+
msg_and_exit("Invalid shape specified: #{shape}") unless shapes.include?(shape)
|
94
|
+
end
|
95
|
+
|
96
|
+
##
|
97
|
+
# Verify that the shapes defined are supported by the
|
98
|
+
# underlying Graph gem
|
99
|
+
def validate_shapes(hashed_data)
|
100
|
+
hashed_data.each do |k,v|
|
101
|
+
if k == "edges"
|
102
|
+
v.each{|e|
|
103
|
+
if e["from_shape"]
|
104
|
+
test_shape(e["from_shape"])
|
105
|
+
end
|
106
|
+
|
107
|
+
if e["to_shape"]
|
108
|
+
test_shape(e["to_shape"])
|
109
|
+
end
|
110
|
+
}
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
##
|
116
|
+
# Validate that the 'keys' are valid in the config
|
117
|
+
def validate_keys(hashed_data)
|
118
|
+
keys = []
|
119
|
+
hashed_data.each do |k,v|
|
120
|
+
unless k == "edges"
|
121
|
+
keys.push(k)
|
122
|
+
keys.push(validate_keys(v)) if v.class == Hash
|
123
|
+
else
|
124
|
+
v.each{|e|
|
125
|
+
keys.push(validate_keys(e))
|
126
|
+
}
|
127
|
+
end
|
128
|
+
end
|
129
|
+
keys.flatten.uniq.each do |u|
|
130
|
+
unless @@valid_keys.include?(u)
|
131
|
+
msg_and_exit("Invalid key found in config: #{u}")
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
##
|
137
|
+
# Attempt to parse the json/yaml config and run through
|
138
|
+
# validation
|
139
|
+
def parse(config_file)
|
140
|
+
begin
|
141
|
+
contents = File.read(config_file)
|
142
|
+
rescue Exception => e
|
143
|
+
msg_and_exit("Failed to read config: #{e.message}")
|
144
|
+
end
|
145
|
+
|
146
|
+
begin
|
147
|
+
config = YAML.load(contents)
|
148
|
+
rescue Exception => e
|
149
|
+
config = JSON.parse(contents)
|
150
|
+
rescue Exception => e
|
151
|
+
msg_and_exit("Failed to parse config: #{e.message}")
|
152
|
+
end
|
153
|
+
|
154
|
+
# run through validation checks
|
155
|
+
validate_keys(config)
|
156
|
+
validate_colors(config)
|
157
|
+
validate_shapes(config)
|
158
|
+
validate_sources(config['sources'])
|
159
|
+
validate_nodes(config)
|
160
|
+
validate_name(config['name'])
|
161
|
+
|
162
|
+
return config
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
end
|