Flucti-flucti-cli 0.1.16

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.
Files changed (65) hide show
  1. data/LICENSE +7 -0
  2. data/README.mdown +24 -0
  3. data/Rakefile +56 -0
  4. data/TODO.txt +19 -0
  5. data/bin/flucti +4 -0
  6. data/flucti-cli.gemspec +46 -0
  7. data/lib/flucti.rb +20 -0
  8. data/lib/flucti/api_access.rb +56 -0
  9. data/lib/flucti/cli.rb +107 -0
  10. data/lib/flucti/parameters.rb +37 -0
  11. data/lib/flucti/resources.rb +41 -0
  12. data/lib/flucti/resources/account.rb +7 -0
  13. data/lib/flucti/resources/app_type.rb +18 -0
  14. data/lib/flucti/resources/backend.rb +28 -0
  15. data/lib/flucti/resources/basic_resource.rb +16 -0
  16. data/lib/flucti/resources/container.rb +15 -0
  17. data/lib/flucti/resources/db_server.rb +38 -0
  18. data/lib/flucti/resources/domain.rb +8 -0
  19. data/lib/flucti/resources/general.rb +14 -0
  20. data/lib/flucti/resources/mail_client.rb +7 -0
  21. data/lib/flucti/resources/mail_server.rb +7 -0
  22. data/lib/flucti/resources/port_forwarding.rb +15 -0
  23. data/lib/flucti/resources/port_forwarding/services +13921 -0
  24. data/lib/flucti/resources/ssh_details.rb +96 -0
  25. data/lib/flucti/resources/webserver.rb +9 -0
  26. data/lib/flucti/resources/website.rb +9 -0
  27. data/lib/flucti/tasks.rb +3 -0
  28. data/lib/flucti/tasks/apikey_tasks.rb +57 -0
  29. data/lib/flucti/tasks/apptype_tasks.rb +264 -0
  30. data/lib/flucti/tasks/connect_pack.rb +161 -0
  31. data/lib/flucti/tasks/db_tasks.rb +158 -0
  32. data/lib/flucti/tasks/mail_tasks.rb +104 -0
  33. data/lib/flucti/tasks/miscellaneous_tasks.rb +6 -0
  34. data/lib/flucti/tasks/progress_tasks.rb +24 -0
  35. data/lib/flucti/tasks/sshkey_tasks.rb +151 -0
  36. data/lib/flucti/tasks/vps/firewall_tasks.rb +84 -0
  37. data/lib/flucti/tasks/vps_tasks.rb +37 -0
  38. data/lib/flucti/tasks/webserver_tasks.rb +154 -0
  39. data/lib/flucti/tasks/website/apptype_tasks.rb +42 -0
  40. data/lib/flucti/tasks/website/backends/instances_tasks.rb +37 -0
  41. data/lib/flucti/tasks/website/backends_tasks.rb +254 -0
  42. data/lib/flucti/tasks/website/capfile_tasks.rb +41 -0
  43. data/lib/flucti/tasks/website/domains_tasks.rb +107 -0
  44. data/lib/flucti/tasks/website_tasks.rb +221 -0
  45. data/lib/flucti/utilities.rb +20 -0
  46. data/lib/flucti/utilities/connection_error_handling.rb +50 -0
  47. data/lib/flucti/utilities/core_ext.rb +35 -0
  48. data/lib/flucti/utilities/list_displayer.rb +57 -0
  49. data/lib/flucti/utilities/miscellaneous.rb +65 -0
  50. data/lib/flucti/utilities/progress_bar.rb +17 -0
  51. data/lib/flucti/utilities/table.rb +25 -0
  52. data/lib/flucti/utilities/task_packing.rb +10 -0
  53. data/lib/flucti/utilities/user_interface.rb +117 -0
  54. data/lib/vendor/ruby-progressbar-0.9/lib/ChangeLog +113 -0
  55. data/lib/vendor/ruby-progressbar-0.9/lib/progressbar.en.rd +103 -0
  56. data/lib/vendor/ruby-progressbar-0.9/lib/progressbar.ja.rd +100 -0
  57. data/lib/vendor/ruby-progressbar-0.9/lib/progressbar.rb +236 -0
  58. data/lib/vendor/ruby-progressbar-0.9/lib/test.rb +105 -0
  59. data/test/flucti/resources_test.rb +32 -0
  60. data/test/flucti/tasks_test.rb +28 -0
  61. data/test/flucti/utilities/miscellaneous_test.rb +54 -0
  62. data/test/flucti/utilities/table_test.rb +28 -0
  63. data/test/flucti/utilities/user_interface_test.rb +161 -0
  64. data/test/test_helper.rb +5 -0
  65. metadata +221 -0
@@ -0,0 +1,158 @@
1
+ namespace :db do
2
+ namespace :server do
3
+ task(:default) { list }
4
+ import_pack(:connect, self, "database server")
5
+
6
+ desc <<-DESC
7
+ List all database servers.
8
+ DESC
9
+ task :list do
10
+ puts_title "Database servers"
11
+ puts_list DbServer.all do |t|
12
+ t.col("Host") { |s| s.vps.hostname }
13
+ t.col("Port", :port)
14
+ t.col("Running as", :user)
15
+ end
16
+ end
17
+
18
+ desc <<-DESC
19
+ Set up a new MySQL database server on a certain VPS.
20
+
21
+ Environment variables:
22
+ (optional) $ON: the ID or hostname of the VPS to set up the server
23
+ onto.
24
+ Default: the newest VPS.
25
+ DESC
26
+ task :setup do
27
+ vps = fetch_vps
28
+
29
+ db_server = vps.db_servers.build
30
+ try_save db_server do
31
+ puts_title "Request sent"
32
+ puts "Database server successfully scheduled for setup on #{q vps}."
33
+ end
34
+ end
35
+
36
+ desc <<-DESC
37
+ Display the root credentials. One can only connect as root to 127.0.0.1
38
+ so commands that require root privilege must be executed directly on the
39
+ database server VPS, not any another one.
40
+
41
+ For example:
42
+ $ #{command 'db:server:root'}
43
+ $ #{command 'db:server:enter'}
44
+ > env HISTFILE= mysql -h 127.0.0.1 -u root-1a28 -p'f6561b' foo -e 'SHOW TABLES'
45
+
46
+ The above is actually equivalent to:
47
+ $ #{command 'db:server:run'} DB=foo Q='SHOW TABLES'
48
+
49
+ Environment variables:
50
+ (optional) $ID: the ID of the server to display the root credentials of.
51
+ Default: the last server set up.
52
+ DESC
53
+ task :root do
54
+ server = fetch_current
55
+ root = server.root
56
+ puts_long <<-EOS
57
+ * Host: 127.0.0.1
58
+ * Login: #{root.login}
59
+ * Password: #{root.password}
60
+
61
+ Query execution:
62
+ $ #{root.command_for_display '<database>', '<command>'}
63
+ EOS
64
+ end
65
+
66
+ desc <<-DESC
67
+ Quick way to run a query as root on a database server.
68
+
69
+ Example usage:
70
+ $ #{command "db:server:run"} Q="SHOW DATABASES"
71
+
72
+ Environment variables:
73
+ (optional) $ID: the ID of the server to run the query in.
74
+ Default: the last server set up.
75
+ DESC
76
+ task :run do
77
+ server = fetch_current
78
+
79
+ queries = ENV["Q"] || (!$stdin.tty? and $stdin.read) or error! <<-MSG
80
+ Specify the query(ies) to execute either in the $Q environment
81
+ variable or through STDIN.
82
+ MSG
83
+ db = ENV["DB"]
84
+
85
+ root = server.root
86
+ command = root.command(db, queries)
87
+
88
+ server.vps.ssh_details.as(server.user).run(command)
89
+ end
90
+
91
+ desc <<-DESC
92
+ List all the databases hosted on a certain server.
93
+
94
+ Environment variables:
95
+ (optional) $ID: the ID of the server to list the databases from.
96
+ Default: the last server set up.
97
+ DESC
98
+ task :databases do
99
+ ENV["Q"] = "SHOW DATABASES"
100
+ run
101
+ end
102
+
103
+ desc <<-DESC
104
+ Remove a database server. So is done by stopping the daemon and
105
+ soft-clearing all of the related files.
106
+
107
+ That is, for a database server run as a UNIX account named `mysql', the
108
+ `mysql' account is removed, but the files are kept in /home/_mysql.
109
+
110
+ Environment variables:
111
+ (optional) $ID: the ID of the server to remove.
112
+ Default: the last server set up.
113
+ DESC
114
+ task :remove do
115
+ server = fetch_current
116
+ server.destroy
117
+ puts_long <<-MSG
118
+ Database server #{q server} successfully scheduled for removal.
119
+ MSG
120
+ end
121
+
122
+ def fetch_current
123
+ (id = ENV["ID"]) ? DbServer.find(id) : DbServer.last
124
+ end
125
+
126
+ def fetch_vps
127
+ (id = ENV["ON"]) ? VPS.find(id) : VPS.last
128
+ end
129
+ end
130
+
131
+ desc <<-DESC
132
+ Create a new database on a certain server. Once created, you will receive
133
+ the credentials via e-mail.
134
+
135
+ Example usage:
136
+ $ #{command "db:create"} NAME=foo
137
+
138
+ Environment variables:
139
+ (optional) $ID: the ID of the database server to create the database on.
140
+ Default: the server last set up.
141
+ DESC
142
+ task :create do
143
+ name = ENV["NAME"] or error! <<-MSG
144
+ The name of the database to create must be specified in the $NAME
145
+ environment variable.
146
+ MSG
147
+ server = (id = ENV["ID"]) ? DbServer.find(id) : DbServer.last
148
+ db = server.databases.build :name => name
149
+
150
+ try_save db do
151
+ puts_title "Request sent"
152
+ puts_long <<-MSG
153
+ Database #{q db} successfully created on #{q server}. Check your
154
+ e-mails for the connection details, including the credentials.
155
+ MSG
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,104 @@
1
+ namespace :mail do
2
+ namespace :server do
3
+ task(:default) { list }
4
+
5
+ desc <<-DESC
6
+ List all VPS's acting as outgoing mail servers.
7
+ DESC
8
+ task :list do
9
+ puts_title "Mail servers"
10
+ puts_list MailServer.all, :id => false, :table => true do |t|
11
+ t.col("Host", :host)
12
+ t.col("Port", :port)
13
+ end
14
+ end
15
+
16
+ desc <<-DESC
17
+ Set up an outgoing (SMTP) mail server on a VPS.
18
+
19
+ ATTENTION: Outgoing mail servers, like their name suggests, can only
20
+ send e-mails out and cannot receive any. As a consequence,
21
+ that they cannot be used as public Internet MX hosts (yet).
22
+
23
+ After the setup has completed, you will be able to send out e-mails from
24
+ the mail server VPS in addition to any VPS configured as mail client of
25
+ that mail server (see #{qcommand "mail:client:setup"}). From these
26
+ VPS's, e-mails can be sent with for example:
27
+
28
+ * Out-of-the-box:
29
+ - PHP's mail() function,
30
+ - Rails mailers (ActionMailer subclasses),
31
+ - the #{q "sendmail"} command,
32
+ - any other way that eventually relies on sendmail.
33
+
34
+ * Any method that relies on SMTP, after configuring SMTP connection
35
+ details based on the output of #{qcommand 'mail:server:list'}.
36
+
37
+ Environment variables:
38
+ (optional) $ON: the hostname of the VPS to set up the mail server on.
39
+ Default: the newest VPS.
40
+ DESC
41
+ task :setup do
42
+ confirm <<-WARN
43
+ Any previously installed MTA (Mail Transfer Agent) will be removed
44
+ prior to configuring the new mail server.
45
+ WARN
46
+
47
+ vps = mail.fetch_target_vps
48
+ mail_server = vps.build_mail_server
49
+
50
+ try_save mail_server do
51
+ puts_title "Request sent"
52
+ puts "Mail server has been scheduled for setup on VPS #{q vps}."
53
+ end
54
+ end
55
+ end
56
+
57
+ namespace :client do
58
+ desc <<-DESC
59
+ Configure a mail client on a VPS. This will enable e-mail sending via
60
+ a previously configured mail server on another VPS (see #{qcommand \
61
+ 'mail:server:setup'}.
62
+
63
+ For example, given a VPS `foo' and a VPS `bar':
64
+ $ #{command 'mail:server:setup'} ON=foo
65
+ $ #{command 'mail:client:setup'} ON=bar
66
+
67
+ Environment variables:
68
+ (optional) $ON: the ID or hostname of the VPS to configure the mail
69
+ client on.
70
+ Default: the newest VPS.
71
+
72
+ (optional) $OF or $SERVER: the ID or hostname of the mail server VPS
73
+ that the client is to send e-mails
74
+ through.
75
+ Default: the mail server last set up.
76
+ DESC
77
+ task :setup do
78
+ id = ENV["SERVER"] || ENV["OF"]
79
+ unless server = id ? MailServer.find(id) : MailServer.last
80
+ error! <<-MSG
81
+ There is no mail server set up yet. To remedy this situation,
82
+ execute the following command:
83
+ $ #{command 'mail:server:setup'}
84
+ MSG
85
+ end
86
+
87
+ server = server.vps
88
+ client = mail.fetch_target_vps
89
+
90
+ mail_client = client.build_mail_client(:server => server)
91
+
92
+ try_save mail_client do
93
+ puts_title "Request sent"
94
+ puts_long <<-MSG
95
+ Mail client of #{q server} successfully scheduled for setup on #{q client}.
96
+ MSG
97
+ end
98
+ end
99
+ end
100
+
101
+ def fetch_target_vps
102
+ ENV["ON"] ? VPS.find(ENV["ON"]) : VPS.last
103
+ end
104
+ end
@@ -0,0 +1,6 @@
1
+ desc "Open an IRB console with access to all resource classes."
2
+ task :console do
3
+ require 'irb'
4
+ ARGV.clear
5
+ IRB.start(nil)
6
+ end
@@ -0,0 +1,24 @@
1
+ desc <<-DESC
2
+ Show a progress-bar for in-progress operations. Blocks until 100% is
3
+ reached.
4
+
5
+ When you create, alter or delete an entity, resulting in operations
6
+ necessary for the changes to take effect, like software installation and/or
7
+ configuration -- be it on one or several of your VPS's, and/or in our
8
+ registries -- these operations are started processing in the background on
9
+ our end.
10
+
11
+ This task lets you know how much of these are left to do (roughly), and when
12
+ they are all done (accurately).
13
+ DESC
14
+ task :progress do
15
+ key, bar = nil, Utilities::ProgressBar.new("Progress", 100, $stdout)
16
+ loop do
17
+ progress = Progress.first(:key => key)
18
+ bar.set(progress.percent)
19
+ break if progress.percent >= 100
20
+ key = progress.key
21
+ sleep 2
22
+ end
23
+ bar.finish
24
+ end
@@ -0,0 +1,151 @@
1
+ namespace :sshkey do
2
+ class PublicKeyPathNotFound < StandardError
3
+ end
4
+
5
+ task(:default) { list }
6
+
7
+ desc <<-DESC
8
+ List all registered SSH keys.
9
+ DESC
10
+ task :list do
11
+ puts_title "Registered SSH keys"
12
+ puts_list SshKey.all, :table => true do |t|
13
+ t.col("Public key") { |k| k.public_key.to_s[0, 50] + '...' }
14
+ end
15
+ end
16
+
17
+ registration_env_vars = <<-DESC
18
+ Environment variables:
19
+ (optional) $FILE: path/to/id_{rsa,dsa}.pub
20
+ Default: your public key is searched
21
+ for at the usual locations.
22
+
23
+ (optional) STDIN: the public key can be fed through STDIN instead of by
24
+ path. Example:
25
+ $ #{command "sshkey:register"} < path/to/the/key.pub
26
+ DESC
27
+
28
+ desc <<-DESC
29
+ Register your public SSH key. You can register more than one. Doing so
30
+ grants you password-less SSH/SFTP/SCP access to all UNIX accounts created
31
+ either automatically or manually via #{qcommand "vps:user:add"}.
32
+
33
+ Upon registration, the new key will be granted access all UNIX accounts of
34
+ all your VPS's (actually, only the ones that have a home folder). It will
35
+ also automatically be granted access to UNIX accounts created later.
36
+
37
+ #{registration_env_vars}
38
+ DESC
39
+ task :register do
40
+ current_key = local_key!
41
+
42
+ puts_title "Registering SSH key"
43
+ puts "Public key at: #{current_key}"
44
+
45
+ key = SshKey.new :public_key => current_key.read
46
+ try_save key do
47
+ puts_title "SSH key registered"
48
+ puts(key.public_key)
49
+ end
50
+ end
51
+
52
+ desc <<-DESC
53
+ Make sure that your public key is registered; register it otherwise. If
54
+ you don't have a pair of keys (private and public) yet, one is attempted
55
+ to be generated for you at ~/.ssh.
56
+
57
+ If even the generation failed, all UNIX accounts are switched to password
58
+ mode. In this mode, each time an account is created, a password is
59
+ generated for you to log in with. At creation time, an e-mail is sent to
60
+ you containing SSH connection details, including the generated password.
61
+
62
+ #{registration_env_vars}
63
+ DESC
64
+ task :ensure_registered do
65
+ begin
66
+ current_key = local_key
67
+ rescue PublicKeyPathNotFound
68
+ if system("which ssh-keygen")
69
+ sh %{echo | ssh-keygen -t dsa -P ''}
70
+ register
71
+ else
72
+ Account.put(:password_auth)
73
+ error! <<-MSG
74
+ You do not appear to already have an SSH key pair present at the
75
+ regular location. One has been attempted to be generated for you but
76
+ the #{q "ssh-keygen"} was missing.
77
+
78
+ As a consequence, password-authentication have been enabled so that
79
+ you can connect to each account on your VPS's using passwords
80
+ instead of a public key.
81
+
82
+ Also, whenever the #{q "ssh"} is supposed to be executed, you will
83
+ be presented with connections details for use in a graphical client
84
+ application such as PuTTy and WinSCP (for Windows).
85
+ MSG
86
+ end
87
+ else
88
+ puts_title "Status of your public key"
89
+ begin
90
+ SshKey.create :public_key => current_key.read
91
+ rescue WebService::ResourceInvalid
92
+ puts "The public key of the current user (#{ENV['USER']}) is registered."
93
+ else
94
+ puts "The public key of the current user (#{ENV['USER']}) has been registered successfully."
95
+ end
96
+ end
97
+ end
98
+
99
+ desc <<-DESC
100
+ Unregister a key. It will be revoked access from all UNIX accounts it is
101
+ currently granted access to, and won't be automatically granted access to
102
+ the UNIX account of new website backends anymore.
103
+
104
+ Environment variables:
105
+ $ID: the ID of the key to unregister (get the list with #{qcommand "sshkey:list"}).
106
+ DESC
107
+ task :unregister do
108
+ id = require_id!
109
+
110
+ SshKey.delete(id)
111
+ puts_title "Request sent"
112
+ puts "SSH key successfully scheduled for unregistration."
113
+ end
114
+
115
+ def require_id!
116
+ ENV["ID"] or
117
+ error! <<-MSG
118
+ The ID of the key to deal with must be specified by setting the ID
119
+ environment variable. To list all registered SSH keys, run
120
+ #{qcommand "sshkey:list"}.
121
+ MSG
122
+ end
123
+
124
+ def local_key!
125
+ local_key
126
+ rescue PublicKeyPathNotFound
127
+ error! $!.message
128
+ end
129
+
130
+ def local_key
131
+ if !$stdin.tty?
132
+ file = STDINWrapper.new
133
+ elsif path = ENV["FILE"]
134
+ file = Pathname(path)
135
+ raise PublicKeyPathNotFound, "No such file: #{path}." unless file.file?
136
+ else
137
+ file = Pathname.glob("{.,#{ENV['HOME']}/.{ssh,ssh2}}/id_{dsa,rsa}.pub{,.txt}").first
138
+ end
139
+ file or raise PublicKeyPathNotFound, "Could not guess the path of your public SSH key."
140
+ end
141
+
142
+ class STDINWrapper
143
+ def to_s
144
+ "STDIN"
145
+ end
146
+
147
+ def read
148
+ $stdin.gets
149
+ end
150
+ end
151
+ end