aws-edges 0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|