dewiring 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +15 -0
  2. data/bin/wire +7 -0
  3. data/bin/wire-network-container.sh +547 -0
  4. data/lib/test_fig.rb +46 -0
  5. data/lib/wire/cli/cli_commands.rb +88 -0
  6. data/lib/wire/cli/main_cli.rb +129 -0
  7. data/lib/wire/cli.rb +8 -0
  8. data/lib/wire/commands/base_command.rb +139 -0
  9. data/lib/wire/commands/down_command.rb +69 -0
  10. data/lib/wire/commands/down_command_handler.rb +199 -0
  11. data/lib/wire/commands/init_command.rb +89 -0
  12. data/lib/wire/commands/init_interactive.rb +75 -0
  13. data/lib/wire/commands/spec_command.rb +240 -0
  14. data/lib/wire/commands/spec_templates.rb +134 -0
  15. data/lib/wire/commands/up_command.rb +69 -0
  16. data/lib/wire/commands/up_command_handler.rb +193 -0
  17. data/lib/wire/commands/updown_command_base.rb +80 -0
  18. data/lib/wire/commands/validate_command.rb +64 -0
  19. data/lib/wire/commands/verify_command.rb +196 -0
  20. data/lib/wire/commands/verify_command_handler.rb +134 -0
  21. data/lib/wire/commands.rb +19 -0
  22. data/lib/wire/common.rb +42 -0
  23. data/lib/wire/execution/local_exec.rb +110 -0
  24. data/lib/wire/execution.rb +7 -0
  25. data/lib/wire/model/appgroup_validation.rb +45 -0
  26. data/lib/wire/model/loader.rb +49 -0
  27. data/lib/wire/model/network_validation.rb +111 -0
  28. data/lib/wire/model/project.rb +64 -0
  29. data/lib/wire/model/state.rb +154 -0
  30. data/lib/wire/model/validation.rb +66 -0
  31. data/lib/wire/model/verification.rb +37 -0
  32. data/lib/wire/model.rb +13 -0
  33. data/lib/wire/resource/bridge.rb +76 -0
  34. data/lib/wire/resource/dhcp_range_config.rb +135 -0
  35. data/lib/wire/resource/fig_adapter.rb +127 -0
  36. data/lib/wire/resource/ip_binary.rb +141 -0
  37. data/lib/wire/resource/ipaddr_ext.rb +38 -0
  38. data/lib/wire/resource/ipaddr_on_intf.rb +108 -0
  39. data/lib/wire/resource/network_injection.rb +138 -0
  40. data/lib/wire/resource/resource.rb +52 -0
  41. data/lib/wire/resource.rb +14 -0
  42. data/lib/wire/version.rb +14 -0
  43. data/lib/wire.rb +24 -0
  44. metadata +117 -0
@@ -0,0 +1,80 @@
1
+ # encoding: utf-8
2
+
3
+ # The MIT License (MIT)
4
+ # Copyright (c) 2014 Andreas Schmidt, andreas@de-wiring.net
5
+ #
6
+
7
+ # Wire module
8
+ module Wire
9
+ # Base class for up/down commands
10
+ class UpDownCommand < BaseCommand
11
+ # generic method, calls run_on_project_zones for
12
+ # all zones in model
13
+ def run_on_project
14
+ zones = @project.get_element('zones')
15
+
16
+ # iterates all zones, descend into zone
17
+ # for further checks, mark all those bad
18
+ # zones, decide upon boolean return flag
19
+ (run_on_project_zones(zones)
20
+ .each do |_zone_name, zone_data|
21
+ # error occured in run_on_zone call. Lets mark this
22
+ zone_data.store :status, :failed
23
+
24
+ end.size > 0)
25
+ end
26
+
27
+ # run on all given +zones+
28
+ # Returns [Hash] of zones that failed.
29
+ def run_on_project_zones(zones)
30
+ zones.select do |zone_name, _|
31
+ $log.debug("Processing zone #{zone_name} ...")
32
+ run_on_zone(zone_name) == false
33
+ end
34
+ end
35
+
36
+ # if dhcp is part of given +network_data+, use
37
+ # +handler+ to process it.
38
+ # +zone_name+:: Name of zone
39
+ # +network_name+:: Name of network
40
+ def default_handle_dhcp(zone_name, network_name, network_data, handler)
41
+ dhcp_data = network_data[:dhcp]
42
+ return true unless dhcp_data
43
+
44
+ $log.debug 'Processing dhcp/dnsmasq ...'
45
+ handler.handle_dhcp(zone_name,
46
+ network_name, network_data,
47
+ dhcp_data[:start], dhcp_data[:end])
48
+ end
49
+
50
+ # if host ip is enabled for given network (+network_name+, +network_data+)
51
+ # use +handler+ to process it
52
+ def default_handle_hostip(network_name, network_data, handler)
53
+ hostip = network_data[:hostip]
54
+ return true unless hostip
55
+
56
+ $log.debug "Processing host ip on network #{network_name} ..."
57
+
58
+ # if the hostip is not in cidr, take netmask
59
+ # from network entry, add to hostip
60
+ hostip = ensure_hostip_netmask(hostip, network_data)
61
+
62
+ # forward to handler
63
+ handler.handle_hostip(network_name, hostip)
64
+ end
65
+
66
+ # returns networks from given +networks+ array that
67
+ # belong to +zone_name+
68
+ # params:
69
+ # +networks+: array of all networks
70
+ # +zone_name+: name of desired zone
71
+ # returns:
72
+ # # => [Array] of networks for given zone
73
+ def self.get_networks_for_zone(networks, zone_name)
74
+ # select networks in given zone only
75
+ networks.select do |_, network_data|
76
+ network_data[:zone] == zone_name
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,64 @@
1
+ # encoding: utf-8
2
+
3
+ # The MIT License (MIT)
4
+ # Copyright (c) 2014 Andreas Schmidt, andreas@de-wiring.net
5
+ #
6
+
7
+ # Wire module
8
+ module Wire
9
+ # Validate Command reads yaml, parses model elements
10
+ # and runs a number of consistency checks
11
+ class ValidateCommand < BaseCommand
12
+ # array of +errors+
13
+ attr_accessor :errors
14
+
15
+ # array of validations
16
+ attr_accessor :validations
17
+
18
+ # initializes an empty error list
19
+ def initialize
20
+ @errors = []
21
+ @validations = [NetworksValidation, AppGroupValidation]
22
+ end
23
+
24
+ # runs validation on given project
25
+ # returns
26
+ # => list of +errors+
27
+ def run_on_project
28
+ @errors = []
29
+
30
+ # run validations against it
31
+ # TODO: Move validation classes to class level definition
32
+ @validations.each do |val_clazz|
33
+ (@errors << run_validation(@project, val_clazz)).flatten!
34
+ end
35
+
36
+ if @errors.size == 0
37
+ outputs 'VALIDATE', 'OK, model is consistent.', :ok
38
+ else
39
+ outputs 'VALIDATE', 'ERROR, detected inconsistencies:', :error
40
+ @errors.each do |val_error|
41
+ outputs 'VALIDATE', val_error.to_s, :error
42
+ end
43
+ end
44
+
45
+ @errors
46
+ end
47
+
48
+ # run a validation of given +validation_class+ against
49
+ # the model
50
+ #
51
+ # params:
52
+ # +project+:: project model object, to validate
53
+ # +validation_class+:: class object of validation, i.e. NetworksValidation
54
+ #
55
+ # returns:
56
+ # list of errors from validation object
57
+ def run_validation(project, validation_class)
58
+ $log.debug "Running validation class #{validation_class}"
59
+ val_object = validation_class.new(project)
60
+ val_object.run_validations
61
+ val_object.errors
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,196 @@
1
+ # encoding: utf-8
2
+
3
+ # The MIT License (MIT)
4
+ # Copyright (c) 2014 Andreas Schmidt, andreas@de-wiring.net
5
+ #
6
+
7
+ # Wire module
8
+ module Wire
9
+ # Verify Command reads yaml, parses model elements
10
+ # and checks if given elements are present on the system
11
+ # rubocop:disable ClassLength
12
+ class VerifyCommand < BaseCommand
13
+ # +project+:: to operate upon
14
+ # +findings+:: is an array of potential errors that occured
15
+ # during verification run
16
+ attr_accessor :project, :findings
17
+ # allow to get access to handler object
18
+ attr_reader :handler
19
+
20
+ # set up with empty findings arraay
21
+ def initialize
22
+ @findings = []
23
+ @handler = VerifyCommandHandler.new
24
+ end
25
+
26
+ # add a finding to the findings array
27
+ # params:
28
+ # +msg+:: what went wrong
29
+ # +type+:: element type, i.e. Network
30
+ # +element_name+:: element_name
31
+ # +element_data+:: map of details, from model
32
+ def mark(msg, type, element_name, element_data)
33
+ @findings <<
34
+ VerificationError.new(msg, type,
35
+ element_name, element_data)
36
+ end
37
+
38
+ # run verification on whole project
39
+ # iterates all zones, descend into zone
40
+ # verification
41
+ # returns:
42
+ # - [bool] true = verification ok
43
+ def run_on_project
44
+ zones = @project.get_element('zones')
45
+
46
+ # iterates all zones, descend into zone
47
+ # for further checks, mark all those bad
48
+ # zones, decide upon boolean return flag
49
+ (run_on_project_zones(zones)
50
+ .each do |zone_name, zone_data|
51
+ # error occured in run_on_zone call. Lets mark this
52
+ zone_data.store :status, :failed
53
+ mark("Not all elements of zone \'#{zone_name}\' are valid.",
54
+ :zone, zone_name, zone_data)
55
+ end.size > 0)
56
+ end
57
+
58
+ # run verification on given +zones+
59
+ def run_on_project_zones(zones)
60
+ zones.select do |zone_name, _|
61
+ $log.debug("Verifying zone #{zone_name} ...")
62
+ b_zone_res = run_on_zone(zone_name)
63
+
64
+ if b_zone_res
65
+ outputs 'VERIFY', "Zone \'#{zone_name}\' verified successfully", :ok
66
+ else
67
+ outputs 'VERIFY', "Zone \'#{zone_name}\' NOT verified successfully", :err
68
+ end
69
+
70
+ b_zone_res == false
71
+ end
72
+ end
73
+
74
+ # run verification for given +zone_name+:
75
+ # - check if bridges exist for all networks in
76
+ # this zone
77
+ def run_on_zone(zone_name)
78
+ networks = @project.get_element('networks')
79
+
80
+ b_verify_ok = true
81
+
82
+ # select networks in current zone only
83
+ networks_in_zone = networks.select do |_, network_data|
84
+ network_data[:zone] == zone_name
85
+ end
86
+ # verify these networks
87
+ b_verify_ok = false unless verify_networks(networks_in_zone, zone_name)
88
+
89
+ # select appgroups in this zone and verify them
90
+ appgroups_in_zone = objects_in_zone('appgroups', zone_name)
91
+ b_verify_ok = false unless verify_appgroups(appgroups_in_zone, zone_name)
92
+
93
+ b_verify_ok
94
+ end
95
+
96
+ # given an array of network elements (+networks_in_zone+), this
97
+ # method runs the verification on each network.
98
+ # It checks the availability of a bridge and
99
+ # the optional host ip on that bridge.
100
+ # Params:
101
+ # +networks_in_zone+:: Array of network data elements in desired zone
102
+ # +zone_name+:: Name of zone
103
+ def verify_networks(networks_in_zone, zone_name)
104
+ b_verify_ok = true
105
+ networks_in_zone.each do |network_name, network_data|
106
+ $log.debug("Verifying network \'#{network_name}\'")
107
+
108
+ bridge_name = network_name
109
+
110
+ $log.debug 'checking bridge ...'
111
+ # we should have a bridge with that name.
112
+ if @handler.handle_bridge(bridge_name) == false
113
+ network_data.store :status, :failed
114
+ b_verify_ok = false
115
+ mark("Bridge \'#{bridge_name}\' does not exist.",
116
+ :network, network_name, network_data)
117
+ else
118
+ network_data.store :status, :ok
119
+
120
+ hostip = network_data[:hostip]
121
+ # if we have a host ip, then that bridge should have
122
+ # this ip
123
+ if hostip
124
+ $log.debug 'checking host-ip ...'
125
+
126
+ # if the hostip is not in cidr, take netmask
127
+ # from network entry, add to hostip
128
+ hostip = ensure_hostip_netmask(hostip, network_data)
129
+
130
+ if @handler.handle_hostip(bridge_name, hostip) == false
131
+ network_data.store :status, :failed
132
+ b_verify_ok = false
133
+ mark("Host ip \'#{hostip}\' not up on bridge \'#{bridge_name}\'.",
134
+ :network, network_name, network_data)
135
+ else
136
+ network_data.store :status, :ok
137
+ end
138
+ end
139
+
140
+ # if we have dhcp, check this
141
+ dhcp_data = network_data[:dhcp]
142
+ if dhcp_data
143
+ $log.debug 'checking dhcp ...'
144
+ if @handler.handle_dhcp(zone_name, network_name, network_data,
145
+ dhcp_data[:start],
146
+ dhcp_data[:end]) == false
147
+ network_data.store :status, :failed
148
+ b_verify_ok = false
149
+ mark("dnsmasq/dhcp not configured on network \'#{bridge_name}\'.",
150
+ :network, network_name, network_data)
151
+ else
152
+ network_data.store :status, :ok
153
+ end
154
+ end
155
+ end
156
+ end
157
+ b_verify_ok
158
+ end
159
+
160
+ # Given a +zone_name+ and an array of +appgroups+ entries
161
+ # this methods verifies if these appgroups are up and running
162
+ # It also checks container's network attachments
163
+ def verify_appgroups(appgroups, zone_name)
164
+ b_verify_ok = true
165
+
166
+ appgroups.each do |appgroup_name, appgroup_data|
167
+ $log.debug("Verifying appgroup \'#{appgroup_name}\'")
168
+
169
+ if @handler.handle_appgroup(zone_name, appgroup_name,
170
+ appgroup_data, @project.target_dir) == false
171
+ appgroup_data.store :status, :failed
172
+ b_verify_ok = false
173
+ mark("Appgroup \'#{appgroup_name}\' does not run correctly.",
174
+ :appgroup, appgroup_name, appgroup_data)
175
+ else
176
+ appgroup_data.store :status, :ok
177
+ end
178
+
179
+ next unless b_verify_ok
180
+
181
+ zone_networks = objects_in_zone('networks', zone_name)
182
+ if @handler.handle_network_attachments(zone_name, zone_networks,
183
+ appgroup_name, appgroup_data,
184
+ @project.target_dir) == false
185
+ appgroup_data.store :status, :failed
186
+ b_verify_ok = false
187
+ mark("Appgroup \'#{appgroup_name}\' has missing network attachments",
188
+ :appgroup, appgroup_name, appgroup_data)
189
+ else
190
+ appgroup_data.store :status, :ok
191
+ end
192
+ end
193
+ b_verify_ok
194
+ end
195
+ end
196
+ end
@@ -0,0 +1,134 @@
1
+ # encoding: utf-8
2
+
3
+ # The MIT License (MIT)
4
+ # Copyright (c) 2014 Andreas Schmidt, andreas@de-wiring.net
5
+ #
6
+
7
+ # Wire module
8
+ module Wire
9
+ # handle_xxx methods for VerifyCommand
10
+ class VerifyCommandHandler < BaseCommand
11
+ # runs verification for a bridge resource identified by
12
+ # +bridge_name+
13
+ # Returns
14
+ # - [Bool] true if bridge exists
15
+ def handle_bridge(bridge_name)
16
+ bridge_resource = Wire::Resource::ResourceFactory.instance.create(:ovsbridge, bridge_name)
17
+ if bridge_resource.exist?
18
+ outputs 'VERIFY', "Bridge \'#{bridge_name}\' exists.", :ok
19
+ state.update(:bridge, bridge_name, :up)
20
+ return true
21
+ else
22
+ outputs 'VERIFY', "Bridge \'#{bridge_name}\' does not exist.", :err
23
+ state.update(:bridge, bridge_name, :down)
24
+ return false
25
+ end
26
+ end
27
+
28
+ # runs verification for a ip resource identified by
29
+ # +bridge_name+ and +host_ip+
30
+ # Returns
31
+ # - [Bool] true if hostip if up on bridge
32
+ def handle_hostip(bridge_name, hostip)
33
+ hostip_resource = Wire::Resource::ResourceFactory
34
+ .instance.create(:bridgeip, hostip, bridge_name)
35
+ if hostip_resource.up?
36
+ outputs 'VERIFY', "IP \'#{hostip}\' on bridge \'#{bridge_name}\' exists.", :ok
37
+ state.update(:hostip, hostip, :up)
38
+ return true
39
+ else
40
+ outputs 'VERIFY', "IP \'#{hostip}\' on bridge \'#{bridge_name}\' does not exist.", :err
41
+ state.update(:hostip, hostip, :down)
42
+ return false
43
+ end
44
+ end
45
+
46
+ # runs verification for dnsmasqs dhcp resource
47
+ # Returns
48
+ # - [Bool] true if dhcp setup is valid
49
+ def handle_dhcp(zone_name, network_name, network_entry, address_start, address_end)
50
+ resource = Wire::Resource::ResourceFactory
51
+ .instance.create(:dhcpconfig, "wire__#{zone_name}", network_name,
52
+ network_entry, address_start, address_end)
53
+ if resource.up?
54
+ outputs 'VERIFY', "dnsmasq/dhcp config on network \'#{network_name}\' is valid.", :ok
55
+ state.update(:dnsmasq, network_name, :up)
56
+ return true
57
+ else
58
+ outputs 'VERIFY', "dnsmasq/dhcp config on network \'#{network_name}\' is not valid.", :err
59
+ state.update(:dnsmasq, network_name, :down)
60
+ return false
61
+ end
62
+ end
63
+
64
+ # runs verification for appgroups
65
+ # Returns
66
+ # - [Bool] true if appgroup setup is ok
67
+ def handle_appgroup(_zone_name, appgroup_name, appgroup_entry, target_dir)
68
+ # get path
69
+ controller_entry = appgroup_entry[:controller]
70
+
71
+ if controller_entry[:type] == 'fig'
72
+ fig_path = File.join(File.expand_path(target_dir), controller_entry[:file])
73
+
74
+ resource = Wire::Resource::ResourceFactory
75
+ .instance.create(:figadapter, "#{appgroup_name}", fig_path)
76
+ if resource.up?
77
+ outputs 'VERIFY', "appgroup \'#{appgroup_name}\' is running.", :ok
78
+ state.update(:appgroup, appgroup_name, :up)
79
+ return true
80
+ else
81
+ outputs 'VERIFY', "appgroup \'#{appgroup_name}\' is not running.", :err
82
+ state.update(:appgroup, appgroup_name, :down)
83
+ return false
84
+ end
85
+ end
86
+
87
+ $log.error "Appgroup not handled, unknown controller type #{controller_entry[:type]}"
88
+ false
89
+ end
90
+
91
+ # runs verification for container network attachment
92
+ # Params:
93
+ # ++_zone_name++: Name of zone
94
+ # ++networks++: Array of networks names, what to attach
95
+ # ++appgroup_name++: Name of appgroup
96
+ # ++appgroup_entry++: appgroup hash
97
+ # ++target_dir++: project target dir
98
+ # Returns
99
+ # - [Bool] true if appgroup setup is ok
100
+ def handle_network_attachments(_zone_name, networks, appgroup_name,
101
+ appgroup_entry, target_dir)
102
+ # query container ids of containers running here
103
+ # get path
104
+ controller_entry = appgroup_entry[:controller]
105
+
106
+ container_ids = []
107
+
108
+ if controller_entry[:type] == 'fig'
109
+ fig_path = File.join(File.expand_path(target_dir), controller_entry[:file])
110
+
111
+ resource = Wire::Resource::ResourceFactory
112
+ .instance.create(:figadapter, "#{appgroup_name}", fig_path)
113
+
114
+ container_ids = resource.up_ids || []
115
+ $log.debug "Got #{container_ids.size} container id(s) from adapter"
116
+ end
117
+
118
+ #
119
+ resource = Wire::Resource::ResourceFactory
120
+ .instance.create(:networkinjection, appgroup_name, networks.keys, container_ids)
121
+ if resource.up?
122
+ outputs 'VERIFY', "appgroup \'#{appgroup_name}\' has network(s) " \
123
+ "\'#{networks.keys.join(',')}\' attached.", :ok
124
+ state.update(:appgroup, appgroup_name, :up)
125
+ return true
126
+ else
127
+ outputs 'VERIFY', "appgroup \'#{appgroup_name}\' does not have " \
128
+ "all networks \'#{networks.keys.join(',')}\' attached.", :err
129
+ state.update(:appgroup, appgroup_name, :down)
130
+ return false
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ # The MIT License (MIT)
4
+ # Copyright (c) 2014 Andreas Schmidt, andreas@de-wiring.net
5
+ #
6
+
7
+ require_relative 'commands/base_command.rb'
8
+ require_relative 'commands/init_command.rb'
9
+ require_relative 'commands/init_interactive.rb'
10
+ require_relative 'commands/validate_command.rb'
11
+ require_relative 'commands/verify_command.rb'
12
+ require_relative 'commands/verify_command_handler.rb'
13
+ require_relative 'commands/spec_command.rb'
14
+ require_relative 'commands/spec_templates.rb'
15
+ require_relative 'commands/updown_command_base.rb'
16
+ require_relative 'commands/up_command.rb'
17
+ require_relative 'commands/up_command_handler.rb'
18
+ require_relative 'commands/down_command.rb'
19
+ require_relative 'commands/down_command_handler.rb'
@@ -0,0 +1,42 @@
1
+ # encoding: utf-8
2
+
3
+ # The MIT License (MIT)
4
+ # Copyright (c) 2014 Andreas Schmidt, andreas@de-wiring.net
5
+ #
6
+
7
+ require 'thor'
8
+
9
+ require 'rainbow'
10
+ require 'rainbow/ext/string'
11
+
12
+ require 'yaml'
13
+ require 'pp'
14
+ require 'English'
15
+ require 'erb'
16
+ require 'tempfile'
17
+
18
+ # set up log object
19
+ require 'logger'
20
+
21
+ $log = Logger.new STDOUT
22
+ # parametrize
23
+ $log.formatter = proc do |severity, _, _, msg|
24
+ "#{severity} #{msg}\n"
25
+ end
26
+ $log.level = Logger::INFO
27
+
28
+ # define exit codes
29
+ module Wire
30
+ # central place for exit codes, given by +id+
31
+ # Params
32
+ # +id+ i.e. :init_bad_input
33
+ # Returns
34
+ # exitcode as [int]
35
+ def self.cli_exitcode(id)
36
+ codes = {
37
+ :init_bad_input => 10,
38
+ :init_dir_error => 20
39
+ }
40
+ codes[id]
41
+ end
42
+ end
@@ -0,0 +1,110 @@
1
+ # encoding: utf-8
2
+
3
+ # The MIT License (MIT)
4
+ # Copyright (c) 2014 Andreas Schmidt, andreas@de-wiring.net
5
+ #
6
+
7
+ require 'singleton'
8
+
9
+ # Wire module
10
+ module Wire
11
+ # Execution module for executing commands
12
+ module Execution
13
+ # return singleton object
14
+ def self.global_execution_options
15
+ ExecutionOptions.singleton
16
+ end
17
+
18
+ # Global execution options, such as noop mode etc.
19
+ class ExecutionOptions
20
+ include Singleton
21
+
22
+ # set default execution options
23
+ def initialize
24
+ @options = { :b_noop => false }
25
+ end
26
+
27
+ # returns
28
+ # - [Boolean] true if no_op mode
29
+ def noop?
30
+ @options[:b_noop]
31
+ end
32
+ end
33
+
34
+ # Able to execute commands locally
35
+ # supports sudo and shell wrapping
36
+ class LocalExecution
37
+ # +exitstatus+ the exit status of a command that we ran
38
+ # +stdout+ stdout from command as [String]
39
+ # +stderr+ stderr from command as [String]
40
+ attr_accessor :exitstatus, :stdout, :stderr
41
+
42
+ # params:
43
+ # - command: binary to execute
44
+ # - args: optional cmd line arguments (exec array)
45
+ # - options:
46
+ # - b_shell: if true, run as /bin/sh -c '<command> [args]'
47
+ # - b_sudo: insert sudo if true
48
+ def initialize(command, args = nil, options =
49
+ { :b_shell => true, :b_sudo => true })
50
+ @command = command
51
+ @args = array_or_nil_as_str(args)
52
+ @options = options
53
+ end
54
+
55
+ # block-style. Creates a LocalExecution object with
56
+ # given parameters, yields it into a given block.
57
+ # Params:
58
+ # +command+ Command string, usually the binary
59
+ # +args+ argument array
60
+ # +options+ option map (b_shell, b_sudo flags)
61
+ # Yields
62
+ # - LocalExecution object
63
+ def self.with(command, args = nil, options =
64
+ { :b_shell => true, :b_sudo => true })
65
+ obj = LocalExecution.new command, args, options
66
+ yield obj
67
+ end
68
+
69
+ # constructs the single command line string from
70
+ # given parameters.
71
+ # Returns
72
+ # - Command line as [String]
73
+ def construct_command
74
+ cmd_arr = []
75
+ command_args = "#{@command} #{@args}".strip
76
+ sudo_str = (@options[:b_sudo] ? 'sudo ' : '')
77
+ if @options[:b_shell]
78
+ cmd_arr << '/bin/sh'
79
+ cmd_arr << '-c'
80
+
81
+ cmd_arr << "'#{sudo_str}#{command_args}'"
82
+ else
83
+ cmd_arr << "#{sudo_str}#{command_args}"
84
+ end
85
+
86
+ cmd_arr.join(' ').strip
87
+ end
88
+
89
+ # runs the command
90
+ # sets instance variables
91
+ # stdout, stderr, exitstatus
92
+ def run
93
+ cmd = construct_command
94
+
95
+ $log.debug "Executing #{cmd}"
96
+ @stdout = `#{cmd}`
97
+ @stderr = nil
98
+ @exitstatus = $CHILD_STATUS.exitstatus
99
+ end
100
+
101
+ private
102
+
103
+ # converts given +array_or_nil+ object to identity
104
+ # if array or an empty array if nil
105
+ def array_or_nil_as_str(array_or_nil)
106
+ (array_or_nil || []).join(' ')
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,7 @@
1
+ # encoding: utf-8
2
+
3
+ # The MIT License (MIT)
4
+ # Copyright (c) 2014 Andreas Schmidt, andreas@de-wiring.net
5
+ #
6
+
7
+ require_relative 'execution/local_exec.rb'
@@ -0,0 +1,45 @@
1
+ # encoding: utf-8
2
+
3
+ # The MIT License (MIT)
4
+ # Copyright (c) 2014 Andreas Schmidt, andreas@de-wiring.net
5
+ #
6
+
7
+ # Wire module
8
+ module Wire
9
+ # Run validations on appgroup model part
10
+ class AppGroupValidation < ValidationBase
11
+ # run validation steps on appgroup elements
12
+ # returns
13
+ # - nil, results in errors of ValidationBase
14
+ def run_validations
15
+ return unless @project.element?('appgroups')
16
+
17
+ appgroups_attached_to_zones?
18
+ controllers_valid?
19
+ end
20
+
21
+ # ensures that all application groups are attached to a zone
22
+ def appgroups_attached_to_zones?
23
+ objects_attached_to_zones? 'appgroups'
24
+ end
25
+
26
+ # ensures that all application groups have a known controller
27
+ def controllers_valid?
28
+ @project.get_element('appgroups').each do |appgroup_name, appgroup_data|
29
+ controller_data = appgroup_data[:controller]
30
+ type = 'appgroup'
31
+ name = appgroup_name
32
+ if !controller_data
33
+ mark('Appgroup is not attached to a zone', type, name)
34
+ else
35
+ type = controller_data[:type]
36
+ mark('Appgroup controller does not have a type', type, name) unless type && type.size > 0
37
+
38
+ known_types = %w(fig)
39
+ mark('Appgroup controller has an unkown type (#{type})',
40
+ type, name) unless known_types.include?(type)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end