Flucti-flucti-cli 0.1.16

Sign up to get free protection for your applications and to get access to all the features.
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