cloudflock-qt 0.7.2

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 40697a3970659343568a5908dba4f69e9fbd8478
4
+ data.tar.gz: bb34bf94706b9419f410d4fdc27b17b0a39a31f6
5
+ SHA512:
6
+ metadata.gz: a5e82a619a4e95fe5c8b695217ef5a3d3fd7d810839ae39645fbb3e1d616533db494f55d7f88ad6a77b4887797427f2ee0f903db02507e2cffe8fbc620783c46
7
+ data.tar.gz: a647877f2cc388b44d7c32037729479c01a1aa514e467818d173462a9268c2f72fddaa5148de89cc324cc4854e7d1059b8363d7bc5b18c3b1ffccc4839c3d54e
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'cloudflock-qt/app'
4
+
5
+ $0 = 'qtflock'
6
+
7
+ app = Qt::Application.new(ARGV)
8
+ CloudFlockQt::App.new
9
+ app.exec
@@ -0,0 +1,13 @@
1
+ # Required to work around bug in Windows binary gem.
2
+ # Issue: https://github.com/ryanmelt/qtbindings/issues/69
3
+ require 'thread'
4
+ require 'Qt'
5
+ require 'cloudflock/app'
6
+ require 'cloudflock/task/server-profile'
7
+
8
+ # Public: Namespace for any application built around the CloudFlock API with a
9
+ # Qt interface.
10
+ module CloudFlockQt
11
+ # Public: Version number of the current gem.
12
+ VERSION = '0.7.2'
13
+ end
@@ -0,0 +1,214 @@
1
+ require 'cloudflock-qt'
2
+ require 'cloudflock-qt/error'
3
+ require 'cloudflock-qt/results'
4
+
5
+ module CloudFlockQt
6
+ # Public: Class to be used for the main window.
7
+ class App < Qt::MainWindow
8
+ include CloudFlock::App::Common
9
+ include CloudFlock::Remote
10
+ # Public: Width of the main form window in pixels.
11
+ WINDOW_WIDTH = 300
12
+ # Public: Height of the main form window in pixels.
13
+ WINDOW_HEIGHT = 220
14
+ # Public: Title of the main form window.
15
+ WINDOW_TITLE = "QtFlock Profile #{CloudFlockQt::VERSION}"
16
+
17
+ # Public: Height of each row in the form in pixels
18
+ FORM_LINE_HEIGHT = 30
19
+
20
+ # Public: Raised when information provided to log in to a host is
21
+ # incomplete.
22
+ class HostNotConfigured < StandardError; end
23
+
24
+ # Public: Set up application state and create the main application window,
25
+ # populating it with the form to take target host details.
26
+ def initialize
27
+ super
28
+
29
+ init_instance_variables
30
+ init_ui
31
+ end
32
+
33
+ private
34
+
35
+ # Internal: Set the default values for instance variables.
36
+ #
37
+ # Returns nothing.
38
+ def init_instance_variables
39
+ @hostname = ''
40
+ @username = 'root'
41
+ @password = ''
42
+ @root_password = ''
43
+ @port = '22'
44
+ @sudo = false
45
+
46
+ @lines = 0
47
+ end
48
+
49
+ # Internal: Set up the main window and add the form UI for target host
50
+ # definition.
51
+ #
52
+ # Returns nothing.
53
+ def init_ui
54
+ set_window_title WINDOW_TITLE
55
+ resize WINDOW_WIDTH, WINDOW_HEIGHT
56
+
57
+ file = menu_bar.add_menu('&File')
58
+ add_menu_item('E&xit', file, :quit)
59
+
60
+ build_main_form
61
+
62
+ show
63
+ end
64
+
65
+ # Internal: Build the form to collect data on the host to profile.
66
+ #
67
+ # Returns nothing.
68
+ def build_main_form
69
+ add_form_line_text('Hostname: ', :@hostname)
70
+ add_form_line_text('Username: ', :@username)
71
+ add_form_pass_text('Password: ', :@password)
72
+ add_form_pass_text('Root Password: ', :@root_password)
73
+ add_form_line_text('Port: ', :@port)
74
+
75
+ add_form_line_toggle('Use Sudo', :@sudo)
76
+ add_submit_button('Run Profile') { run_profile }
77
+ end
78
+
79
+ # Internal: Add an entry to a menu (e.g. 'File'), and assign an action to
80
+ # it.
81
+ #
82
+ # item_text - String containing the text to be displayed. An '&' character
83
+ # preceding a character will cause that character to be a
84
+ # hotkey for the item.
85
+ # menu - Qt::Menu to contain the new entry.
86
+ # action - Action to be taken upon triggering the menu item.
87
+ #
88
+ # Returns nothing.
89
+ def add_menu_item(item_text, menu, action)
90
+ item = Qt::Action.new item_text, self
91
+ menu.add_action item
92
+ connect(item, SIGNAL(:triggered), Qt::Application.instance, SLOT(action))
93
+ end
94
+
95
+ # Internal: Create a text input field and corrsponding label.
96
+ #
97
+ # item_text - String with which to populate a text label.
98
+ # varname - Symbol containing the name of the instance variable with
99
+ # which to associate the form entry.
100
+ #
101
+ # Returns the Qt::LineEdit object.
102
+ def add_form_line_text(item_text, varname)
103
+ @lines += 1
104
+
105
+ label = Qt::Label.new self
106
+ label.set_text item_text
107
+ label.adjust_size
108
+ label.move(5, FORM_LINE_HEIGHT * @lines)
109
+
110
+ input = Qt::LineEdit.new self
111
+ input.set_geometry 105, FORM_LINE_HEIGHT * @lines - 10, 190, FORM_LINE_HEIGHT
112
+ input.connect(SIGNAL('textChanged(QString)')) do |string|
113
+ instance_variable_set(varname, string)
114
+ end
115
+ input.set_text instance_variable_get(varname)
116
+
117
+ input
118
+ end
119
+
120
+ # Internal: Wrap add_form_line_text, ensuring the the text display mode is
121
+ # appropriate for passwords.
122
+ #
123
+ # item_text - String with which to populate a text label.
124
+ # varname - Symbol containing the name of the instance variable with
125
+ # which to associate the form entry.
126
+ #
127
+ # Returns nothing.
128
+ def add_form_pass_text(item_text, varname)
129
+ add_form_line_text(item_text, varname).echoMode = Qt::LineEdit::Password
130
+ end
131
+
132
+ # Internal: Create a toggle button input field.
133
+ #
134
+ # item_text - String which will be displayed on the toggle button.
135
+ # varname - Symbol containing the name of the instance variable with
136
+ # which to associate the form entry.
137
+ # block - Optional block to attach to clicking the toggle.
138
+ #
139
+ # Returns nothing.
140
+ def add_form_line_toggle(item_text, varname, &block)
141
+ @lines += 1
142
+
143
+ toggle = Qt::PushButton.new item_text, self
144
+ toggle.set_checkable true
145
+ toggle.set_geometry 5, FORM_LINE_HEIGHT * @lines - 5, 80, 30
146
+ if block.nil?
147
+ toggle.connect(SIGNAL(:clicked)) do
148
+ instance_variable_set(varname, toggle.is_checked)
149
+ end
150
+ else
151
+ toggle.connect(SIGNAL(:clicked), &block)
152
+ end
153
+ end
154
+
155
+ # Internal: Create a submit button.
156
+ #
157
+ # item_text - String which will be displayed on the toggle button.
158
+ # varname - Symbol containing the name of the instance variable with
159
+ # which to associate the form entry.
160
+ # block - Optional block to attach to clicking the toggle.
161
+ #
162
+ # Returns nothing.
163
+ def add_submit_button(item_text, &block)
164
+ submit = Qt::PushButton.new item_text, self
165
+ submit.set_geometry 175, FORM_LINE_HEIGHT * @lines - 5, 120, 30
166
+ submit.connect(SIGNAL(:clicked), &block)
167
+ end
168
+
169
+ # Internal: Check that all necessary data is present, alerting the user if
170
+ # not. If everything appears present, attempt to profile the host.
171
+ #
172
+ # Returns nothing.
173
+ def run_profile
174
+ source_host = { hostname: @hostname, username: @username, port: @port,
175
+ password: @password, sudo: @sudo, ssh_key: '' }
176
+ check_source(source_host)
177
+
178
+ source_ssh = SSH.new(source_host)
179
+ profile = CloudFlock::Task::ServerProfile.new(source_ssh)
180
+
181
+ CloudFlockQt::ResultsWindow.new(profile)
182
+ rescue HostNotConfigured => e
183
+ CloudFlockQt::ErrorWindow.new(e.message)
184
+ rescue CloudFlock::Remote::SSH::InvalidHostname
185
+ CloudFlockQt::ErrorWindow.new("Unable to resolve '#{@hostname}'")
186
+ rescue Net::SSH::AuthenticationFailed
187
+ CloudFlockQt::ErrorWindow.new("Unable to log in as '#{@username}'")
188
+ rescue CloudFlock::Remote::SSH::SSHCannotConnect
189
+ CloudFlockQt::ErrorWindow.new("Cannot connect to #{@hostname}:#{@port}")
190
+ end
191
+
192
+ # Internal: Verify that all entries necessary for logging in to a remote
193
+ # host are present.
194
+ #
195
+ # Raises HostNotConfigured if any necessary information is not present.
196
+ #
197
+ # Returns nothing.
198
+ def check_source(host)
199
+ [:hostname, :username, :port].each do |option|
200
+ if host[option].to_s.empty?
201
+ raise(HostNotConfigured, "Missing #{option.to_s.capitalize}")
202
+ end
203
+ end
204
+ host[:sudo] = false if host[:username] == 'root'
205
+
206
+ # If non-root and using su, the root password is needed
207
+ if host[:username] == 'root' || host[:sudo]
208
+ host[:root_password] = host[:password]
209
+ else
210
+ raise HostNotConfigured if host[:root_password].to_s.empty?
211
+ end
212
+ end
213
+ end
214
+ end
@@ -0,0 +1,19 @@
1
+ require 'cloudflock-qt'
2
+
3
+ module CloudFlockQt
4
+ # Public: Class to be used for error notifications.
5
+ class ErrorWindow < Qt::ErrorMessage
6
+ # Public: Width of the results window in pixels.
7
+ WINDOW_WIDTH = 300
8
+ # Public: Height of the results window in pixels.
9
+ WINDOW_HEIGHT = 150
10
+
11
+ # Public: Create and populate the window with results from profiling a
12
+ # remote host.
13
+ def initialize(message)
14
+ super()
15
+
16
+ show_message(message)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,73 @@
1
+ require 'cloudflock-qt'
2
+
3
+ module CloudFlockQt
4
+ # Public: Class to be used for results windows.
5
+ class ResultsWindow < Qt::Widget
6
+ # Public: Width of the results window in pixels.
7
+ WINDOW_WIDTH = 400
8
+ # Public: Height of the results window in pixels.
9
+ WINDOW_HEIGHT = 500
10
+
11
+ # Public: Create and populate the window with results from profiling a
12
+ # remote host.
13
+ def initialize(profile)
14
+ super()
15
+
16
+ init_ui(profile)
17
+ end
18
+
19
+ private
20
+
21
+ # Internal: Create the results window and text field, then populate it with
22
+ # the results of a host profile.
23
+ #
24
+ # profile - CloudFlock::Task::ServerProfile object.
25
+ #
26
+ # Returns nothing.
27
+ def init_ui(profile)
28
+ hostname = profile.select_entries(/System/, /Hostname/).first.to_s
29
+
30
+ set_window_title "Results for #{hostname}"
31
+ resize WINDOW_WIDTH, WINDOW_HEIGHT
32
+
33
+ results = Qt::TextEdit.new self
34
+ results.set_geometry 5, 5, WINDOW_WIDTH - 5, WINDOW_HEIGHT - 5
35
+ results.set_text generate_report(profile)
36
+
37
+ show
38
+ end
39
+
40
+ # Internal: Generate a String representation of the profile run against a
41
+ # remote host.
42
+ #
43
+ # profile - CloudFlock::Task::ServerProfile object.
44
+ #
45
+ # Returns a String.
46
+ def host_info(profile)
47
+ data = profile.map { |section| [section.title, distill_entries(section)] }
48
+ data.map { |section| section.join("\n") }.join("\n\n")
49
+ end
50
+
51
+ # Internal: Filter any empty entries from a section, then map the rest to
52
+ # Strings.
53
+ #
54
+ # section - CloudFlock::Task::ServerProfile::Section
55
+ #
56
+ # Returns an Array containing Strings.
57
+ def distill_entries(section)
58
+ non_empty = section.entries.reject { |entry| entry.values.to_s.empty? }
59
+ non_empty.map { |entry| "#{entry.name}: #{entry.values}" }
60
+ end
61
+
62
+ # Internal: Produce a human-readable report from the results of profiling a
63
+ # target host.
64
+ #
65
+ # profile - CloudFlock::Task::ServerProfile object.
66
+ #
67
+ # Returns a String.
68
+ def generate_report(profile)
69
+ profile_hash = profile.to_hash
70
+ host_info(profile_hash[:info])
71
+ end
72
+ end
73
+ end
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cloudflock-qt
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.7.2
5
+ platform: ruby
6
+ authors:
7
+ - Chris Wuest
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-07-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: cloudflock
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.7'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.7.2
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '0.7'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 0.7.2
33
+ - !ruby/object:Gem::Dependency
34
+ name: qtbindings
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '4.8'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '4.8'
47
+ description: Graphical frontend for CloudFlock in Qt
48
+ email: chris@chriswuest.com
49
+ executables:
50
+ - qtflock
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - bin/qtflock
55
+ - lib/cloudflock-qt.rb
56
+ - lib/cloudflock-qt/app.rb
57
+ - lib/cloudflock-qt/error.rb
58
+ - lib/cloudflock-qt/results.rb
59
+ homepage: http://github.com/cwuest/cloudflock-qt
60
+ licenses:
61
+ - Apache 2.0
62
+ metadata: {}
63
+ post_install_message:
64
+ rdoc_options: []
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubyforge_project:
79
+ rubygems_version: 2.2.2
80
+ signing_key:
81
+ specification_version: 4
82
+ summary: Unix migration automation
83
+ test_files: []