cheftacular 2.0.9 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/cheftacular/README.md +85 -119
- data/lib/cheftacular/actions/check.rb +20 -0
- data/lib/cheftacular/actions/console.rb +6 -0
- data/lib/cheftacular/actions/db_console.rb +6 -0
- data/lib/cheftacular/actions/deploy.rb +26 -0
- data/lib/cheftacular/actions/log.rb +93 -0
- data/lib/cheftacular/actions/migrate.rb +6 -0
- data/lib/cheftacular/actions/run.rb +6 -0
- data/lib/cheftacular/cheftacular.rb +1 -0
- data/lib/cheftacular/initializers.rb +3 -1
- data/lib/cheftacular/parsers.rb +1 -1
- data/lib/cheftacular/stateless_actions/arguments.rb +0 -2
- data/lib/cheftacular/stateless_actions/bootstrappers/ubuntu_bootstrap.rb +1 -1
- data/lib/cheftacular/stateless_actions/check_cheftacular_settings.rb +14 -0
- data/lib/cheftacular/stateless_actions/chef_environment.rb +3 -3
- data/lib/cheftacular/stateless_actions/clean_sensu_plugins.rb +1 -1
- data/lib/cheftacular/stateless_actions/create_git_key.rb +0 -2
- data/lib/cheftacular/stateless_actions/fetch_file.rb +1 -1
- data/lib/cheftacular/stateless_actions/fix_known_hosts.rb +5 -6
- data/lib/cheftacular/stateless_actions/get_log_from_bag.rb +2 -2
- data/lib/cheftacular/stateless_actions/initialize_data_bag_contents.rb +5 -1
- data/lib/cheftacular/stateless_actions/restart_swap.rb +1 -1
- data/lib/cheftacular/stateless_actions/rvm.rb +102 -2
- data/lib/cheftacular/stateless_actions/slack.rb +19 -0
- data/lib/cheftacular/version.rb +1 -1
- metadata +6 -21
- data/lib/sshkit/actions/start_commit_check.rb +0 -19
- data/lib/sshkit/actions/start_deploy.rb +0 -25
- data/lib/sshkit/actions/start_log_fetch.rb +0 -92
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 928f8a004cb74ca10ecca90795caecf6c8bd8af4
|
4
|
+
data.tar.gz: e0bcd6f10d0f059c3f852878a3015026bc694152
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6cdf8e3448ba4eb57f483f68edf18c20567607402ba3c88f47df410745d836e778b5555a441b5e187dd002572e89a37ff68a72023b35d4d68478d4c377702b7a
|
7
|
+
data.tar.gz: 87eefe7516479d2535131ac24e0c5efac2147cab265440c105b2b38ffecb1221064721776f89980f5eb95f99ac291cbeb3ef53ab1d9d277075011b9cd0fff6ac
|
data/lib/cheftacular/README.md
CHANGED
@@ -1,64 +1,12 @@
|
|
1
1
|
# Table of Contents for Cheftacular Commands
|
2
2
|
|
3
|
-
1. [Cheftacular Arguments and Flags](https://github.com/SocialCentivPublic/cheftacular/blob/master/lib/cheftacular/README.md#arguments-and-flags-for-cheftacular)
|
3
|
+
1. [Cheftacular Arguments and Flags](https://github.com/SocialCentivPublic/cheftacular/blob/master/lib/cheftacular/README.md#arguments-and-flags-for-cheftacular))
|
4
4
|
|
5
5
|
2. [Application Commands](https://github.com/SocialCentivPublic/cheftacular/blob/master/lib/cheftacular/README.md#commands-that-can-be-run-in-the-application-context)
|
6
6
|
|
7
|
-
3. [DevOps Commands](https://github.com/SocialCentivPublic/cheftacular/blob/master/lib/cheftacular/README.md#commands-that-can-only-be-run-in-the-devops-context)
|
7
|
+
3. [DevOps Commands](https://github.com/SocialCentivPublic/cheftacular/blob/master/lib/cheftacular/README.md#commands-that-can-only-be-run-in-the-devops-context))
|
8
8
|
|
9
9
|
|
10
|
-
## Arguments and flags for cheftacular
|
11
|
-
|
12
|
-
### Environment flags
|
13
|
-
|
14
|
-
1. `-d|--dev-remote` toggles on dev-remote mode. Commands passed to cft will hit the devremote server(s) instead of the default server(s)
|
15
|
-
|
16
|
-
2. `--env ENV` sets the environment commands hit to one you specify instead of the default one.
|
17
|
-
|
18
|
-
3. `-p|--prod` toggles on production mode. Commands passed to cft will hit the production server(s) instead of the default server(s)
|
19
|
-
|
20
|
-
4. `-Q|--qa` toggles on QA mode. Commands passed to cft will hit the QA server(s) instead of the default server(s)
|
21
|
-
|
22
|
-
5. `-s|--staging` toggles on staging mode. Commands passed to cft will hit the staging server(s) instead of the default server(s)
|
23
|
-
|
24
|
-
6. `--split-env SPLIT_ENV_NAME` sets the sub-environment to SPLIT_ENV_NAME. This only slightly affects certain commands.
|
25
|
-
|
26
|
-
7. `-t|--test` toggles on test mode. Commands passed to cft will hit the test server(s) instead of the default server(s)
|
27
|
-
|
28
|
-
### General Flags
|
29
|
-
|
30
|
-
1. `-a|--address ADDRESS` will force the command to only run against the specified address if it belongs to a node
|
31
|
-
|
32
|
-
2. `-D|--debug` toggles on extremely verbose logging. Chef-client runs will generate ~10 times the amounts of logs including any additional effects that the `-v` flag will activate
|
33
|
-
|
34
|
-
3. `--no-logs` will make the cft commands not generate log files, you must still specify `-v` if you want output of most verbose commands to your terminal.
|
35
|
-
|
36
|
-
4. `-n|--node-name NODE_NAME` will force the command to only run against the specified name if it belongs to a node
|
37
|
-
|
38
|
-
5. `-q|--quiet` will make the cft commands only output information that is a direct result of the command being run
|
39
|
-
|
40
|
-
6. `-r|--role-name ROLE_NAME` will force the command to only run against the specified role if it exists (this argument is generally not needed though it can be used to deploy a codebase for an application you're not currently cd'd into when running this as a gem)
|
41
|
-
|
42
|
-
7. `-R|--repository NAME` will make the command run against a specific repository or context (automatically set for application mode)
|
43
|
-
|
44
|
-
8. `-v|--verbose` toggles on verbose logging. All commands that write logs will also output to terminal AND write the logs.
|
45
|
-
|
46
|
-
### Help Related
|
47
|
-
|
48
|
-
1. `-h|--help` Displays the full readme and exits.
|
49
|
-
|
50
|
-
### Action Flags
|
51
|
-
|
52
|
-
1. `-e|--except-role ROLE_NAME` will *prevent* any server with this role from being *deployed to* for the deploy command. Other commands will ignore this argument.
|
53
|
-
|
54
|
-
2. `-z|--unset-revision` will unset a custom revision specified in the arg below and make the codebase utilize the default (staging branch for staging and master for production)
|
55
|
-
|
56
|
-
3. `-Z|--revision REVISION` will force the role you're deploying to to utilize the revision specified here. This can be a specific commit or a branch name.
|
57
|
-
|
58
|
-
1. Note: The system does not check if the revision exists, if you pass a non-existent revision no one will be able to deploy to that role until -Z with a correction revision or -z is passed.
|
59
|
-
|
60
|
-
2. *You will not be able to set a custom revision for beta environments.* The beta environments are tied to split-staging and splita/b/c/d respectively.
|
61
|
-
|
62
10
|
## Arguments and flags for cheftacular
|
63
11
|
|
64
12
|
### Environment flags
|
@@ -118,13 +66,7 @@
|
|
118
66
|
|
119
67
|
2. `cft check` Checks the commits for all servers for a repository (for an environment) and returns them in a simple chart. Also shows when these commits were deployed to the server.
|
120
68
|
|
121
|
-
3. `cft
|
122
|
-
|
123
|
-
1. `create` will create an environment if it does not exist.
|
124
|
-
|
125
|
-
2. `destroy` will destroy a chef environment *IF IT HAS NO NODES*
|
126
|
-
|
127
|
-
4. `cft client_list` Allows you check the basic information for all the servers setup via chef. Shows the server's short name, its public ip address and roles (run_list) by default.
|
69
|
+
3. `cft client_list` Allows you check the basic information for all the servers setup via chef. Shows the server's short name, its public ip address and roles (run_list) by default.
|
128
70
|
|
129
71
|
1. `-v` option will make this command display the server's domain name, whether its password is stored on the chef server and what that password is.
|
130
72
|
|
@@ -132,19 +74,19 @@
|
|
132
74
|
|
133
75
|
3. This command is aliased to `client-list` with no arguments or cft prefix.
|
134
76
|
|
135
|
-
|
77
|
+
4. `cft console` will create a pry session on the first node found for a codebase.
|
136
78
|
|
137
|
-
|
79
|
+
5. `cft db_console` will create a database console session on the first node found for a database stack in the current environment.
|
138
80
|
|
139
81
|
1. This command is aliased to psql, typing `cft psql` will drop you into a rails stack database psql session.
|
140
82
|
|
141
|
-
|
83
|
+
6. `cft deploy` will do a simple chef-client run on the servers for a role. Logs of the run itself will be sent to the local log directory in the application (or chef-repo) where the run was conducted.
|
142
84
|
|
143
85
|
1. This command also restarts services on the server and updates the code. Changes behavior slightly with the `-z|-Z` args.
|
144
86
|
|
145
|
-
|
87
|
+
7. `cft disk_report` will fetch useful statistics from every server for every environment and output it into your log directory.
|
146
88
|
|
147
|
-
|
89
|
+
8. `cft environment boot|destroy` will boot / destroy the current environment
|
148
90
|
|
149
91
|
1. `boot` will spin up servers and bring them to a stable state. This includes setting up their subdomains for the target environment.
|
150
92
|
|
@@ -152,23 +94,23 @@
|
|
152
94
|
|
153
95
|
3. This command will prompt when attempting to destroy servers in staging or production
|
154
96
|
|
155
|
-
|
97
|
+
9. `cft fix_known_hosts [HOSTNAME]` this command will delete entries in your known_hosts file for all the servers that are in our system (ip addresses AND dns names)
|
156
98
|
|
157
99
|
1. Passing in a hostname will make the command only remove entries with that hostname / ip specifically
|
158
100
|
|
159
|
-
|
101
|
+
10. `cft get_active_ssh_connections` will fetch the active ssh connections from every server and output it into your log directory.
|
160
102
|
|
161
|
-
|
103
|
+
11. `cft get_haproxy_log` this command will generate a haproxy html file for the load balancer(s) associated with a repository in the log directory. Opening this log file in the browser will show the status of that haproxy at the time of the log.
|
162
104
|
|
163
105
|
1. In devops mode, this command will not do anything without the -R repository passed.
|
164
106
|
|
165
|
-
|
107
|
+
12. `cft get_log_from_bag <NODE_NAME-COMMAND_TYPE>` this command grabs the latest command run log from the data bags and saves it to your log directory. There are different types of logs saved per server depending on command.
|
166
108
|
|
167
|
-
|
109
|
+
13. `cft get_pg_pass ['clip']` command will output the current environment's pg_password to your terminal. Optionally you can pass in clip like `cft get_pg_pass clip` to have it also copy the pass to your clipboard.
|
168
110
|
|
169
|
-
|
111
|
+
14. `cft help COMMAND|MODE` this command returns the documentation for a specific command if COMMAND matches the name of a command. Alternatively, it can be passed `action|arguments|application|current|devops|stateless_action` to fetch the commands for a specific mode.Misspellings of commands will display near hits.
|
170
112
|
|
171
|
-
|
113
|
+
15. `cft log` this command will output the last 500 lines of logs from every server set for CODEBASE (can be given additional args to specify) to the log directory
|
172
114
|
|
173
115
|
1. `--nginx` will fetch the nginx logs as well as the application logs
|
174
116
|
|
@@ -180,15 +122,15 @@
|
|
180
122
|
|
181
123
|
4. `--fetch-backup` If doing a pg_data log, this will fetch the latest logs from the pg_data log directory for each database.
|
182
124
|
|
183
|
-
|
125
|
+
16. `cft migrate` this command will grab the first alphabetical node for a repository and run a migration that will hit the database primary server.
|
184
126
|
|
185
|
-
|
127
|
+
17. `cft pass NODE_NAME` will drop the server's sudo password into your clipboard. Useful for when you need to ssh into the server itself and try advanced linux commands
|
186
128
|
|
187
|
-
|
129
|
+
18. `cft reinitialize IP_ADDRESS NODE_NAME` will reconnect a server previously managed by chef to a new chef server. The node name MUST MATCH THE NODE'S ORIGINAL NODE NAME for the roles to be setup correctly.
|
188
130
|
|
189
|
-
|
131
|
+
19. `cft remove_client -n NODE_NAME` removes a client (and its node data) from the chef-server. It also removes its dns records from the cloud service (if possible). This should not be done lightly as you will have to wipe the server and trigger another chef-client run to get it to register again
|
190
132
|
|
191
|
-
|
133
|
+
20. `cft run COMMAND [--all]` will trigger the command on the first server in the role. Can be used to run rake commands or anything else.
|
192
134
|
|
193
135
|
1. `--all` will make the command run against all servers in a role rather than the first server it comes across. Don't do this if you're modifying the database with the command.
|
194
136
|
|
@@ -198,11 +140,11 @@
|
|
198
140
|
|
199
141
|
4. IMPORTANT NOTE: You cannot run `cft run rake -T` as is, you have to enclose any command that uses command line dash arguments in quotes like `cft run "rake -T"`
|
200
142
|
|
201
|
-
|
143
|
+
21. `cft scale up|down [NUM_TO_SCALE]` will add (or remove) NUM_TO_SCALE servers from the server array. This command will not let you scale down below 1 server.
|
202
144
|
|
203
145
|
1. In the case of server creation, this command takes a great deal of time to execute. It will output what stage it is currently on to the terminal but <b>you must not kill this command while it is executing</b>.A failed build may require the server to be destroyed / examined by a DevOps engineer.
|
204
146
|
|
205
|
-
|
147
|
+
22. `cft tail` will tail the logs (return continuous output) of the first node if finds that has an application matching the repository running on it. Currently only supports rails stacks
|
206
148
|
|
207
149
|
1. pass `-n NODE_NAME` to grab the output of a node other than the first.
|
208
150
|
|
@@ -211,23 +153,35 @@
|
|
211
153
|
|
212
154
|
## Commands that can ONLY be run in the devops context
|
213
155
|
|
214
|
-
1. `cft
|
156
|
+
1. [NYI]`cft chef_environment ENVIRONMENT_NAME [create|destroy]` will allow you to interact with chef environments on the chef server.
|
157
|
+
|
158
|
+
1. `create` will create an environment if it does not exist.
|
159
|
+
|
160
|
+
2. `destroy` will destroy a chef environment *IF IT HAS NO NODES*
|
161
|
+
|
162
|
+
2. [NYI]`cft clean_sensu_plugins` will checkout / update the sensu community plugins github repo on your local machine and sync any sensu plugin files in your wrapper cookbook directory with what is in the repo.
|
163
|
+
|
164
|
+
3. [NYI]`cft fetch_file NODE_NAME LOCATION_ALIAS FILE_NAME` fetches a file from the remote node.
|
165
|
+
|
166
|
+
1. `LOCATION_ALIAS` will be parsed as a path if it has backslash characters. Otherwise it will be parsed from your location_aliases hash in your cheftacular.yml
|
167
|
+
|
168
|
+
2. `FILE_NAME` is the actual name of the file to be fetched. If no value is passed or the file does not exist in the LOCATION_ALIAS, the command will return the entries in LOCATION_ALIAS
|
169
|
+
|
170
|
+
4. `cft add_ssh_key_to_bag "<NEW SSH PUB KEY>" [SPECIFIC_REPOSITORY]` this command will add the given ssh key to the default authentication data bag. After this your server recipes should read the contents of the 'default' 'authentication' bag for the authorized_keys array.
|
215
171
|
|
216
172
|
1. `SPECIFIC_REPOSITORY` is a special argument, if left blank the key will be placed in the authorized_keys array in the bag, otherwise it will be placed in the specific_authorized_keys hash under a key named for the repository that is passed. The script will error if SPECIFIC_REPOSITORY does not exist in the cheftacular.yml respositories hash. You can then use this data to give users selective ssh access to certain servers.
|
217
173
|
|
218
|
-
|
174
|
+
5. `cft backup [activate|deactivate]` this command sets the fetch_backups and restore_backups flags in your config data bag for an environment. These can be used to give application developers a way to trigger / untrigger restores in an environment
|
219
175
|
|
220
|
-
|
176
|
+
6. `cft chef_bootstrap ADDRESS NODE_NAME` allows you to register a node in the chef system, remove any lingering data that may be associated with it and update the node's runlist if it has an entry in nodes_dir for its NODE_NAME.
|
221
177
|
|
222
|
-
|
178
|
+
7. `cft clean_cookbooks [force] [remove_cookbooks]` allows you to update the internal chef-repo's cookbooks easily. By default this script will force you to decide what to do with each cookbook individually (shows version numbers and whether to overwrite it to cookbooks or not).
|
223
179
|
|
224
180
|
1. `force` argument will cause the downloaded cookbooks to *always* overwrite the chef-repo's cookbooks as long as the downloaded cookbook has a higher version number.
|
225
181
|
|
226
182
|
2. If you would like to remove all the cookbooks on the chef server, run `knife cookbook bulk delete '.*' -p -c ~/.chef/knife.rb`
|
227
183
|
|
228
|
-
|
229
|
-
|
230
|
-
6. `cft client_list` Allows you check the basic information for all the servers setup via chef. Shows the server's short name, its public ip address and roles (run_list) by default.
|
184
|
+
8. `cft client_list` Allows you check the basic information for all the servers setup via chef. Shows the server's short name, its public ip address and roles (run_list) by default.
|
231
185
|
|
232
186
|
1. `-v` option will make this command display the server's domain name, whether its password is stored on the chef server and what that password is.
|
233
187
|
|
@@ -235,7 +189,7 @@
|
|
235
189
|
|
236
190
|
3. This command is aliased to `client-list` with no arguments or cft prefix.
|
237
191
|
|
238
|
-
|
192
|
+
9. `cft cloud <FIRST_LEVEL_ARG> [<SECOND_LEVEL_ARG>[:<SECOND_LEVEL_ARG_QUERY>]*] ` this command handles talking to various cloud apis. If no args are passed nothing will happen.
|
239
193
|
|
240
194
|
1. `domain` 1st level argument for interacting with cloud domains
|
241
195
|
|
@@ -307,7 +261,7 @@
|
|
307
261
|
|
308
262
|
1. Standard servers are listed as XGB with no spaces in their size, performance servers are listed as X GB with a space in their size. If you are about to create a server and are unsure, query flavors first.
|
309
263
|
|
310
|
-
|
264
|
+
10. `cft cloud_bootstrap NODE_NAME FLAVOR_NAME [DESCRIPTOR] [--with-dn DOMAIN]` uses a cloud api to create a server and attaches its DOMAIN_NAME to the TLD specified for that environment (IE: example-staging.com for staging)
|
311
265
|
|
312
266
|
1. If no DOMAIN_NAME is supplied it will use the node's NODE_NAME (IE: api01.example-staging.com)
|
313
267
|
|
@@ -317,19 +271,19 @@
|
|
317
271
|
|
318
272
|
4. DESCRIPTOR is used as an internal tag for the node, if left blank it will become the name of the node. It is recommended to enter a custom repository-dependent tag here to make nodes easier to load-balance like "lb:[CODEBASE_NAME]"
|
319
273
|
|
320
|
-
|
274
|
+
11. `cft compile_audit_log [clean]` compiles the audit logs in each environment's audit data bag a audit-log-CURRENTDAY.md file in the log folder of the application. Bear in mind that the bag can only hold 100K bytes and will need to have that data removed to store more than that.
|
321
275
|
|
322
|
-
|
276
|
+
12. `cft compile_readme` compiles all documentation methods and creates a README.md file in the log folder of the application.
|
323
277
|
|
324
|
-
|
278
|
+
13. `cft create_git_key ID_RSA_FILE [OAUTH_TOKEN]` This command will update the default/authentication data bag with new credentials. The [ID_RSA_FILE](https://help.github.com/articles/generating-ssh-keys) needs to exist beforehand.
|
325
279
|
|
326
280
|
1. This command will upload both the private and public key to the data bag. The public key should be the one that matches the github user for your deployment github user.
|
327
281
|
|
328
282
|
2. `OAUTH_TOKEN` *must* be generated by logging into github and generating an access token in the account settings -> applications -> personal access tokens
|
329
283
|
|
330
|
-
|
284
|
+
14. `cft disk_report` will fetch useful statistics from every server for every environment and output it into your log directory.
|
331
285
|
|
332
|
-
|
286
|
+
15. `cft environment boot|destroy` will boot / destroy the current environment
|
333
287
|
|
334
288
|
1. `boot` will spin up servers and bring them to a stable state. This includes setting up their subdomains for the target environment.
|
335
289
|
|
@@ -337,47 +291,59 @@
|
|
337
291
|
|
338
292
|
3. This command will prompt when attempting to destroy servers in staging or production
|
339
293
|
|
340
|
-
|
341
|
-
|
342
|
-
1. `LOCATION_ALIAS` will be parsed as a path if it has backslash characters. Otherwise it will be parsed from your location_aliases hash in your cheftacular.yml
|
343
|
-
|
344
|
-
2. `FILE_NAME` is the actual name of the file to be fetched. If no value is passed or the file does not exist in the LOCATION_ALIAS, the command will return the entries in LOCATION_ALIAS
|
345
|
-
|
346
|
-
15. `cft fix_known_hosts [HOSTNAME]` this command will delete entries in your known_hosts file for all the servers that are in our system (ip addresses AND dns names)
|
294
|
+
16. `cft fix_known_hosts [HOSTNAME]` this command will delete entries in your known_hosts file for all the servers that are in our system (ip addresses AND dns names)
|
347
295
|
|
348
296
|
1. Passing in a hostname will make the command only remove entries with that hostname / ip specifically
|
349
297
|
|
350
|
-
|
298
|
+
17. `cft full_bootstrap ADDRESS ROOT_PASS NODE_NAME` This command performs both ubuntu_bootstrap and chef_bootstrap.
|
351
299
|
|
352
|
-
|
300
|
+
18. `cft get_active_ssh_connections` will fetch the active ssh connections from every server and output it into your log directory.
|
353
301
|
|
354
|
-
|
302
|
+
19. `cft get_haproxy_log` this command will generate a haproxy html file for the load balancer(s) associated with a repository in the log directory. Opening this log file in the browser will show the status of that haproxy at the time of the log.
|
355
303
|
|
356
304
|
1. In devops mode, this command will not do anything without the -R repository passed.
|
357
305
|
|
358
|
-
|
306
|
+
20. `cft get_log_from_bag <NODE_NAME-COMMAND_TYPE>` this command grabs the latest command run log from the data bags and saves it to your log directory. There are different types of logs saved per server depending on command.
|
359
307
|
|
360
|
-
|
308
|
+
21. `cft get_pg_pass ['clip']` command will output the current environment's pg_password to your terminal. Optionally you can pass in clip like `cft get_pg_pass clip` to have it also copy the pass to your clipboard.
|
361
309
|
|
362
|
-
|
310
|
+
22. `cft help COMMAND|MODE` this command returns the documentation for a specific command if COMMAND matches the name of a command. Alternatively, it can be passed `action|arguments|application|current|devops|stateless_action` to fetch the commands for a specific mode.Misspellings of commands will display near hits.
|
363
311
|
|
364
|
-
|
312
|
+
23. `cft initialize_data_bag_contents ENVIRONMENT_NAME` will ensure the data bags always have the correct structure before each run. This command is run every time the gem is started and if called directly, will exit after completion.
|
365
313
|
|
366
|
-
|
314
|
+
24. `cft knife_upload` will resync the chef-server with the local chef-repo code. This command is analog for `knife upload /`
|
367
315
|
|
368
|
-
|
316
|
+
25. `cft pass NODE_NAME` will drop the server's sudo password into your clipboard. Useful for when you need to ssh into the server itself and try advanced linux commands
|
369
317
|
|
370
|
-
|
318
|
+
26. `cft replication_status` will check the status of the database master and slaves in every environment. Also lists how far behind the slaves are from the master in milliseconds.
|
371
319
|
|
372
|
-
|
320
|
+
27. `cft restart_swap` will restart the swap on every server that doesn't have swap currently on. Useful if you notice servers with no swap activated from `cft disk_report`
|
373
321
|
|
374
322
|
1. There is no risk in running this command. Sometimes swap doesnt reactivate if the server was rebooted and this command fixes that.
|
375
323
|
|
376
|
-
|
324
|
+
28. `cft rvm [COMMAND] [ADDITIONAL_COMMANDS]*` will run rvm commands on the remote servers. Output from this command for each server will go into your rvm directory under the log directory. Please refer to [the rvm help page](https://rvm.io/rvm) for more information on rvm commands.
|
325
|
+
|
326
|
+
1. When no commands are passed, rvm will just run `rvm list` on each server on all servers in the current environment.
|
327
|
+
|
328
|
+
2. When `list|list_rubies` is passed, rvm will run `rvm list rubies` on all servers in the current environment.
|
329
|
+
|
330
|
+
3. When `install RUBY_TO_INSTALL` is passed, rvm will attempt to install that ruby on each system in the current environment. It is a good idea to use strings like ruby-2.2.1
|
331
|
+
|
332
|
+
4. `run [RVM_COMMANDS]+` will run the rest of the arguments as a complete rvm command. An example of this being `cft rvm run gemset update`. This will run on all servers in the current environment.
|
333
|
+
|
334
|
+
5. `all_environments [RVM_COMMANDS]+` will run the rest of the arguments as a complete rvm command *on all of the servers in every environment*.
|
335
|
+
|
336
|
+
6. `test [RVM_COMMANDS]+` will run the rest of the arguments as a complete rvm command with scoping. By default, rvm commands run against all servers in the environment but with test you can pass -n NODE_NAME or -r ROLE_NAME flags to scope the servers the rvm command will be run on. Useful for testing.
|
337
|
+
|
338
|
+
7. `upgrade_rvm` will run `rvm get stable --auth-dotfiles` on all servers for the current environment. It will also check and attempt to upgrade pre 1.25 installations of RVM to 1.26+ (which requires a GPG key).
|
339
|
+
|
340
|
+
29. `cft server_update [restart]` allows you to force update all nodes' packages for a specific environment. This should be done with caution as this *might* break something.
|
377
341
|
|
378
342
|
1. `hip apt_update restart` will prompt to ask if you also want to restart all servers in a rolling restart. This should be done with extreme caution and only in a worst-case scenario.
|
379
343
|
|
380
|
-
|
344
|
+
30. `cft slack "MESSAGE" [CHANNEL]` will attempt to post the message to the webhook set in your cheftacular.yml. Slack posts to your default channel by default but if the CHANNEL argument is supplied the message will post there.
|
345
|
+
|
346
|
+
31. `cft test_env [TARGET_ENV] boot|destroy` will create (or destroy) the test nodes for a particular environment (defaults to staging, prod split-envs can be set with `-p`). Please read below for how TARGET_ENV works
|
381
347
|
|
382
348
|
1. TARGET_ENV changes functionality depending on the overall (like staging / production) environment
|
383
349
|
|
@@ -387,9 +353,9 @@
|
|
387
353
|
|
388
354
|
3. The default tld used should change depending on which environment you are booting / destroying. This is set in the environment's config data bag under the tld key
|
389
355
|
|
390
|
-
|
356
|
+
32. `cft ubuntu_bootstrap ADDRESS ROOT_PASS` This command will bring a fresh server to a state where chef-client can be run on it via `cft chef-bootstrap`. It should be noted that it is in this step where a server's randomized deploy_user sudo password is generated.
|
391
357
|
|
392
|
-
|
358
|
+
33. `cft update_split_branches` will perform a series of git commands that will merge all the split branches for your split_branch enabled repositories with what is currently on master and push them.
|
393
359
|
|
394
360
|
1. Repository must be set with `-R REPOSITORY_NAME` for this command to work.
|
395
361
|
|
@@ -399,9 +365,9 @@
|
|
399
365
|
|
400
366
|
4. This command will return a helpful error statement if you attempt to run the command with changes to your current working directory. You must commit these changes before running this command.
|
401
367
|
|
402
|
-
|
368
|
+
34. `cft update_tld TLD` command will force a full dns update for a tld in the preferred cloud. It will ensure all the subdomain entries are correct (based on the contents of the addresses data bag) and update them if they are not. It will also create the local subdomain for the entry as well if it does exist and point it to the correct private address.
|
403
369
|
|
404
|
-
|
370
|
+
35. `cft upload_nodes` This command will resync the chef server's nodes with the data in our chef-repo/node_roles.
|
405
371
|
|
406
372
|
1. This command changes behavior depending on several factors about both your mode and the state of your environment
|
407
373
|
|
@@ -413,4 +379,4 @@
|
|
413
379
|
|
414
380
|
1. Due to this, only users running this against their chef-repo need to worry about having a nodes_dir, the way it should be.
|
415
381
|
|
416
|
-
|
382
|
+
36. `cft upload_roles` This command will resync the chef server's roles with the data in the chef-repo/roles.
|
@@ -30,3 +30,23 @@ class Cheftacular
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
end
|
33
|
+
|
34
|
+
module SSHKit
|
35
|
+
module Backend
|
36
|
+
class Netssh
|
37
|
+
def start_commit_check name, ip_address, options, locs, cheftacular, out={'name'=>'', 'time'=> ''}
|
38
|
+
app_loc = "#{ cheftacular['base_file_path'] }/#{ options['repository'] }/releases"
|
39
|
+
|
40
|
+
if test("[ -d #{ app_loc } ]") #true if file exists
|
41
|
+
within app_loc do
|
42
|
+
out['name'] = capture( :ls, '-rt', :|, :tail, '-1' )
|
43
|
+
|
44
|
+
out['time'] = Time.parse(capture( :stat, out['name'], '--printf=%y' )).strftime('%Y-%m-%d %I:%M:%S %p')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
out
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -58,5 +58,11 @@ class Cheftacular
|
|
58
58
|
def start_console_all
|
59
59
|
raise "Not yet implemented"
|
60
60
|
end
|
61
|
+
|
62
|
+
def console_
|
63
|
+
puts "Console method tried to create a console for the role \"#{ @options['role'] }\" but it doesn't appear to have a repository set! Skipping..."
|
64
|
+
|
65
|
+
return false
|
66
|
+
end
|
61
67
|
end
|
62
68
|
end
|
@@ -42,6 +42,12 @@ class Cheftacular
|
|
42
42
|
raise "You attempted to create a database console for a role that had no database type attached to it, this is not possible."
|
43
43
|
end
|
44
44
|
|
45
|
+
def db_console_
|
46
|
+
puts "db_console method tried to create a db_console for the role \"#{ @options['role'] }\" but it doesn't appear to have a repository set! Skipping..."
|
47
|
+
|
48
|
+
return false
|
49
|
+
end
|
50
|
+
|
45
51
|
alias_method :psql, :db_console_postgresql
|
46
52
|
|
47
53
|
private
|
@@ -38,3 +38,29 @@ class Cheftacular
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
41
|
+
|
42
|
+
module SSHKit
|
43
|
+
module Backend
|
44
|
+
class Netssh
|
45
|
+
def start_deploy name, ip_address, options, locs, passwords, out=""
|
46
|
+
log_loc, timestamp = set_log_loc_and_timestamp(locs)
|
47
|
+
|
48
|
+
puts "Generating log file for #{ name } (#{ ip_address }) at #{ log_loc }/deploy/#{ name }-deploy-#{ timestamp }.txt"
|
49
|
+
|
50
|
+
capture_args = [ "chef-client" ]
|
51
|
+
capture_args << [ '-l', 'debug' ] if options['debug']
|
52
|
+
#capture_args << [ '>', '/dev/tty']
|
53
|
+
|
54
|
+
out << sudo_capture( passwords[ip_address], *capture_args.flatten )
|
55
|
+
|
56
|
+
::File.open("#{ log_loc }/deploy/#{ name }-deploy-#{ timestamp }.txt", "w") { |f| f.write(out.scrub_pretty_text) } unless options['no_logs']
|
57
|
+
|
58
|
+
puts(out) if options['output'] || options['verbose']
|
59
|
+
|
60
|
+
puts "Succeeded deploy of #{ name } (#{ ip_address }) on role #{ options['role'] }"
|
61
|
+
|
62
|
+
[out, timestamp] #return out to send to logs_bag
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -45,3 +45,96 @@ class Cheftacular
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
end
|
48
|
+
|
49
|
+
module SSHKit
|
50
|
+
module Backend
|
51
|
+
class Netssh
|
52
|
+
def start_log_role_map name, ip_address, target_log_loc, options, locs, cheftacular, passwords, out=""
|
53
|
+
log_loc, timestamp = set_log_loc_and_timestamp(locs)
|
54
|
+
log_cmnd, log_lines = get_log_command_and_lines(options)
|
55
|
+
|
56
|
+
|
57
|
+
puts "Fetching log file(s) for #{ name } (#{ ip_address }). Outputting to #{ log_loc }/rolelog with timestamp: #{ timestamp }"
|
58
|
+
|
59
|
+
target_log_loc.split(',').each do |parsed_log_loc|
|
60
|
+
parsed_log_loc = parsed_log_loc.gsub('|current_repo_location|', "#{ cheftacular['base_file_path'] }/#{ options['repository'] }/current")
|
61
|
+
|
62
|
+
if parsed_log_loc != '/var/log/syslog' && !test("[ -e #{ parsed_log_loc }]") #true if file exists ()
|
63
|
+
puts "#{ name } (#{ ip_address }) does not have a #{ parsed_log_loc } log file for #{ options['env'] } at the moment..."
|
64
|
+
else
|
65
|
+
if log_lines.nil?
|
66
|
+
out << sudo_capture(passwords[ip_address], log_cmnd.to_sym, parsed_log_loc)
|
67
|
+
|
68
|
+
else
|
69
|
+
out << sudo_capture(passwords[ip_address], log_cmnd.to_sym, log_lines, parsed_log_loc)
|
70
|
+
end
|
71
|
+
|
72
|
+
::File.open("#{ log_loc }/rolelog/#{ name }-#{ parsed_log_loc.split('/').last.split('.').first }-#{ timestamp }.txt", "w") { |f| f.write(out.scrub_pretty_text) } unless options['no_logs']
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def start_log_fetch_ruby_on_rails name, ip_address, run_list, options, locs, cheftacular, passwords, out=""
|
78
|
+
log_loc, timestamp = set_log_loc_and_timestamp(locs)
|
79
|
+
true_env = get_true_environment run_list, cheftacular['run_list_environments'], options['env']
|
80
|
+
app_log_loc = "#{ cheftacular['base_file_path'] }/#{ options['repository'] }/current/log"
|
81
|
+
log_cmnd, log_lines = get_log_command_and_lines(options)
|
82
|
+
|
83
|
+
if !test("[ -e /#{ app_log_loc }/#{ true_env }.log ]") #true if file exists
|
84
|
+
puts "#{ name } (#{ ip_address }) does not have a log file for #{ true_env } at the moment..."
|
85
|
+
|
86
|
+
else
|
87
|
+
|
88
|
+
puts "Fetching log file(s) for #{ name } (#{ ip_address }). Outputting to #{ log_loc }/applog/#{ name }-applog-#{ timestamp }.txt"
|
89
|
+
|
90
|
+
within app_log_loc do
|
91
|
+
if log_lines.nil?
|
92
|
+
out << capture(log_cmnd.to_sym, "#{ true_env }.log")
|
93
|
+
|
94
|
+
else
|
95
|
+
out << capture(log_cmnd.to_sym, log_lines, "#{ true_env }.log")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
#To create the file locally you must namespace like this
|
100
|
+
::File.open("#{ log_loc }/applog/#{ name }-applog-#{ timestamp }.txt", "w") { |f| f.write(out.scrub_pretty_text) } unless options['no_logs']
|
101
|
+
end
|
102
|
+
|
103
|
+
out << start_log_fetch_nginx(name, log_loc, log_cmnd, timestamp, options, out) if run_list.include?('role[web]') && options['get_nginx_logs']
|
104
|
+
|
105
|
+
out << start_log_role_map(name, ip_address, get_role_map(cheftacular, get_worker_role(cheftacular))['log_location'], log_cmnd, app_log_loc, timestamp, options) if run_list.include?("role[#{ get_worker_role(cheftacular) }]")
|
106
|
+
|
107
|
+
puts(out) if options['verbose']
|
108
|
+
end
|
109
|
+
|
110
|
+
def start_log_fetch_nginx name, log_loc, log_cmnd, timestamp, options, out=""
|
111
|
+
out = "" unless options['no_logs']
|
112
|
+
|
113
|
+
nginx_log_loc = "/var/log/nginx/#{ options['repository'] }_access.log"
|
114
|
+
|
115
|
+
puts "Fetching nginx log file... Outputting to #{ log_loc }/applog/#{ name }-nginxlog-#{ timestamp }.txt "
|
116
|
+
|
117
|
+
if log_lines.nil?
|
118
|
+
out << capture(log_cmnd.to_sym, nginx_log_loc)
|
119
|
+
|
120
|
+
else
|
121
|
+
out << capture(log_cmnd.to_sym, log_lines, nginx_log_loc)
|
122
|
+
end
|
123
|
+
|
124
|
+
::File.open("#{ log_loc }/applog/#{ name }-nginxlog-#{ timestamp }.txt", "w") { |f| f.write(out.scrub_pretty_text) } unless options['no_logs']
|
125
|
+
|
126
|
+
out
|
127
|
+
end
|
128
|
+
|
129
|
+
private
|
130
|
+
|
131
|
+
def get_log_command_and_lines options
|
132
|
+
log_cmnd = options['get_full_logs'] ? 'cat' : 'tail'
|
133
|
+
|
134
|
+
log_lines = options['get_full_logs'] ? nil : "-" + ( options['get_log_lines'] ? options['get_log_lines'] : "500" )
|
135
|
+
|
136
|
+
[log_cmnd, log_lines]
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -53,5 +53,11 @@ class Cheftacular
|
|
53
53
|
def migrate_all nodes=[]
|
54
54
|
raise "You attempted to migrate the all role, this is not possible."
|
55
55
|
end
|
56
|
+
|
57
|
+
def migrate_ nodes=[]
|
58
|
+
puts "Migrate method tried to migrate the role \"#{ @options['role'] }\" but it doesn't appear to have a repository set! Skipping..."
|
59
|
+
|
60
|
+
return false
|
61
|
+
end
|
56
62
|
end
|
57
63
|
end
|
@@ -60,5 +60,11 @@ class Cheftacular
|
|
60
60
|
def run_all
|
61
61
|
raise "You attempted to run a command for the all role, this is not possible."
|
62
62
|
end
|
63
|
+
|
64
|
+
def run_
|
65
|
+
puts "Run method tried to run a command for the role \"#{ @options['role'] }\" but it doesn't appear to have a repository set! Skipping..."
|
66
|
+
|
67
|
+
return false
|
68
|
+
end
|
63
69
|
end
|
64
70
|
end
|
@@ -427,7 +427,9 @@ class Cheftacular
|
|
427
427
|
end
|
428
428
|
|
429
429
|
def initialize_directories
|
430
|
-
|
430
|
+
['applog', 'deploy', 'rolelog', 'rvm', 'stashedlog'].each do |sub_log_directory|
|
431
|
+
FileUtils.mkdir_p File.join( @config['locs']['chef-log'], sub_log_directory )
|
432
|
+
end
|
431
433
|
|
432
434
|
FileUtils.mkdir_p File.join( @config['locs']['app-root'], 'tmp', @config['helper'].declassify)
|
433
435
|
|
data/lib/cheftacular/parsers.rb
CHANGED
@@ -61,7 +61,7 @@ class Cheftacular
|
|
61
61
|
|
62
62
|
elsif repo_check_array.include?(true)
|
63
63
|
@config['cheftacular']['repositories'].each_pair do |key, repo_hash|
|
64
|
-
@options['role'] = key if repo_hash['repo_name'] == repository && set_variables
|
64
|
+
@options['role'] = key if repo_hash['repo_name'] == repository && set_variables && @options['role'].nil?
|
65
65
|
end
|
66
66
|
else
|
67
67
|
raise "Unable to parse repository: #{ repository }, the repository you're referring to does not exist in your cheftacular.yml."
|
@@ -55,8 +55,6 @@ class Cheftacular
|
|
55
55
|
' 2. *You will not be able to set a custom revision for beta environments.* The beta environments are tied to split-staging and splita/b/c/d respectively.',
|
56
56
|
]
|
57
57
|
end
|
58
|
-
|
59
|
-
alias_method :stateless_arguments, :arguments
|
60
58
|
end
|
61
59
|
|
62
60
|
class StatelessAction
|
@@ -0,0 +1,14 @@
|
|
1
|
+
#interact with an rvm installation on servers
|
2
|
+
class Cheftacular
|
3
|
+
class StatelessActionDocumentation
|
4
|
+
def check_cheftacular_settings
|
5
|
+
#TODO
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class StatelessAction
|
10
|
+
def check_cheftacular_settings
|
11
|
+
raise "Not Yet Implemented"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
class Cheftacular
|
2
2
|
class StatelessActionDocumentation
|
3
3
|
def chef_environment
|
4
|
-
@config['documentation']['
|
5
|
-
"`cft chef_environment ENVIRONMENT_NAME [create|destroy]` will allow you to interact with chef environments on the chef server.",
|
4
|
+
@config['documentation']['stateless_action'] << [
|
5
|
+
"[NYI]`cft chef_environment ENVIRONMENT_NAME [create|destroy]` will allow you to interact with chef environments on the chef server.",
|
6
6
|
|
7
7
|
[
|
8
8
|
" 1. `create` will create an environment if it does not exist.",
|
@@ -18,4 +18,4 @@ class Cheftacular
|
|
18
18
|
#TODO
|
19
19
|
end
|
20
20
|
end
|
21
|
-
end
|
21
|
+
end
|
@@ -2,7 +2,7 @@ class Cheftacular
|
|
2
2
|
class StatelessActionDocumentation
|
3
3
|
def clean_sensu_plugins
|
4
4
|
@config['documentation']['stateless_action'] << [
|
5
|
-
"`cft clean_sensu_plugins`
|
5
|
+
"[NYI]`cft clean_sensu_plugins` will checkout / update the sensu community plugins github repo on your " +
|
6
6
|
"local machine and sync any sensu plugin files in your wrapper cookbook directory with what is in the repo."
|
7
7
|
]
|
8
8
|
end
|
@@ -2,7 +2,7 @@ class Cheftacular
|
|
2
2
|
class StatelessActionDocumentation
|
3
3
|
def fetch_file
|
4
4
|
@config['documentation']['stateless_action'] << [
|
5
|
-
"`cft fetch_file NODE_NAME LOCATION_ALIAS FILE_NAME` fetches a file from the remote node. ",
|
5
|
+
"[NYI]`cft fetch_file NODE_NAME LOCATION_ALIAS FILE_NAME` fetches a file from the remote node. ",
|
6
6
|
|
7
7
|
[
|
8
8
|
" 1. `LOCATION_ALIAS` will be parsed as a path if it has backslash characters. Otherwise it will be parsed from your " +
|
@@ -17,8 +17,6 @@ class Cheftacular
|
|
17
17
|
|
18
18
|
class StatelessAction
|
19
19
|
def fix_known_hosts
|
20
|
-
include Config
|
21
|
-
|
22
20
|
targets = ["all"]
|
23
21
|
|
24
22
|
if ARGV[1].class == String
|
@@ -28,12 +26,13 @@ class Cheftacular
|
|
28
26
|
if targets.first == 'all'
|
29
27
|
nodes = @config['getter'].get_true_node_objects(true)
|
30
28
|
arr = []
|
31
|
-
environments = (nodes.map { |n| n.chef_environment }).uniq
|
32
29
|
|
33
|
-
|
30
|
+
@config['chef_environments'].each do |env|
|
31
|
+
@config['initializer'].initialize_data_bags_for_environment env, false, ['addresses']
|
32
|
+
|
33
|
+
@config['initializer'].initialize_addresses_bag_contents env
|
34
34
|
|
35
|
-
|
36
|
-
@config[env]['addresses_bag_hash'].each do |serv_hash|
|
35
|
+
@config[env]['addresses_bag_hash']['addresses'].each do |serv_hash|
|
37
36
|
arr << serv_hash['dn'].split('.').first
|
38
37
|
arr << serv_hash['public']
|
39
38
|
end
|
@@ -24,9 +24,9 @@ class Cheftacular
|
|
24
24
|
|
25
25
|
nodes.each do |node|
|
26
26
|
if @config[@options['env']]['logs_bag_hash'].has_key?("#{ node.name }-deploy")
|
27
|
-
puts("Found log data in logs bag. Outputting to #{ log_loc }/#{ node.name }-deploystash-#{ @config[@options['env']]['logs_bag_hash']["#{ node.name }-deploy"][:timestamp] }.txt") unless @options['quiet']
|
27
|
+
puts("Found log data in logs bag. Outputting to #{ log_loc }/stashedlog/#{ node.name }-deploystash-#{ @config[@options['env']]['logs_bag_hash']["#{ node.name }-deploy"][:timestamp] }.txt") unless @options['quiet']
|
28
28
|
|
29
|
-
File.open("#{ log_loc }/#{ node.name }-deploystash-#{@config[@options['env']]['logs_bag_hash']["#{ node.name }-deploy"][:timestamp] }.txt", "w") do |f|
|
29
|
+
File.open("#{ log_loc }/stashedlog/#{ node.name }-deploystash-#{@config[@options['env']]['logs_bag_hash']["#{ node.name }-deploy"][:timestamp] }.txt", "w") do |f|
|
30
30
|
f.write(@config[@options['env']]['logs_bag_hash']["#{ node.name }-deploy"][:text])
|
31
31
|
end
|
32
32
|
|
@@ -9,9 +9,11 @@ class Cheftacular
|
|
9
9
|
end
|
10
10
|
|
11
11
|
class StatelessAction
|
12
|
-
def initialize_data_bag_contents env
|
12
|
+
def initialize_data_bag_contents env=""
|
13
13
|
raise "Environment does not exist on chef server!" unless @config['chef_environments'].include?(env)
|
14
14
|
|
15
|
+
env = ARGV[1] if env.blank?
|
16
|
+
|
15
17
|
@config['initializer'].initialize_audit_bag_contents env
|
16
18
|
|
17
19
|
@config['initializer'].initialize_authentication_bag_contents
|
@@ -166,6 +168,8 @@ class Cheftacular
|
|
166
168
|
end
|
167
169
|
|
168
170
|
envs_to_build_in_hash.each do |env|
|
171
|
+
hash[env] ||= {}
|
172
|
+
|
169
173
|
if !hash[env].has_key?('tld') || ( hash[env].has_key?('tld') && hash[env]['tld'].blank? )
|
170
174
|
hash[env]['tld'] = "" unless hash[env].has_key?('tld')
|
171
175
|
|
@@ -3,7 +3,7 @@ class Cheftacular
|
|
3
3
|
def restart_swap
|
4
4
|
@config['documentation']['stateless_action'] << [
|
5
5
|
"`cft restart_swap` will restart the swap on every server that doesn't have swap currently on. " +
|
6
|
-
"Useful if you notice servers with no swap activated from `
|
6
|
+
"Useful if you notice servers with no swap activated from `cft disk_report`",
|
7
7
|
|
8
8
|
[
|
9
9
|
" 1. There is no risk in running this command. Sometimes swap doesnt reactivate if " +
|
@@ -2,13 +2,113 @@
|
|
2
2
|
class Cheftacular
|
3
3
|
class StatelessActionDocumentation
|
4
4
|
def rvm
|
5
|
-
|
5
|
+
@config['documentation']['stateless_action'] << [
|
6
|
+
"`cft rvm [COMMAND] [ADDITIONAL_COMMANDS]*` will run rvm commands on the remote servers. " +
|
7
|
+
"Output from this command for each server will go into your rvm directory under the log directory. " +
|
8
|
+
"Please refer to [the rvm help page](https://rvm.io/rvm) for more information on rvm commands.",
|
9
|
+
|
10
|
+
[
|
11
|
+
" 1. When no commands are passed, rvm will just run `rvm list` on each server on all servers in " +
|
12
|
+
"the current environment.",
|
13
|
+
|
14
|
+
" 2. When `list|list_rubies` is passed, rvm will run `rvm list rubies` on all servers in the " +
|
15
|
+
"current environment.",
|
16
|
+
|
17
|
+
" 3. When `install RUBY_TO_INSTALL` is passed, rvm will attempt to install that ruby on each " +
|
18
|
+
"system in the current environment. It is a good idea to use strings like ruby-2.2.1",
|
19
|
+
|
20
|
+
" 4. `run [RVM_COMMANDS]+` will run the rest of the arguments as a complete rvm command. An example " +
|
21
|
+
"of this being `cft rvm run gemset update`. This will run on all servers in the current environment.",
|
22
|
+
|
23
|
+
" 5. `all_environments [RVM_COMMANDS]+` will run the rest of the arguments as a complete rvm command " +
|
24
|
+
"*on all of the servers in every environment*.",
|
25
|
+
|
26
|
+
" 6. `test [RVM_COMMANDS]+` will run the rest of the arguments as a complete rvm command with scoping. " +
|
27
|
+
"By default, rvm commands run against all servers in the environment but with test you can pass -n NODE_NAME " +
|
28
|
+
" or -r ROLE_NAME flags to scope the servers the rvm command will be run on. Useful for testing.",
|
29
|
+
|
30
|
+
" 7. `upgrade_rvm` will run `rvm get stable --auth-dotfiles` on all servers for the current environment. " +
|
31
|
+
"It will also check and attempt to upgrade pre 1.25 installations of RVM to 1.26+ (which requires a GPG key)."
|
32
|
+
]
|
33
|
+
]
|
6
34
|
end
|
7
35
|
end
|
8
36
|
|
9
37
|
class StatelessAction
|
10
|
-
def rvm
|
38
|
+
def rvm command=''
|
39
|
+
raise "This action can only be performed if the mode is set to devops" unless @config['helper'].running_in_mode?('devops')
|
40
|
+
|
41
|
+
command = case ARGV[1]
|
42
|
+
when nil then 'list'
|
43
|
+
when /list|list_rubies/ then 'list rubies'
|
44
|
+
when 'install' then "install #{ ARGV[2] }"
|
45
|
+
when 'run' then ARGV[2..(ARGV.length-1)].join(' ')
|
46
|
+
when 'all_environments' then ARGV[2..(ARGV.length-1)].join(' ')
|
47
|
+
when 'test' then ARGV[2..(ARGV.length-1)].join(' ')
|
48
|
+
when 'upgrade_rvm' then 'get stable --auto-dotfiles'
|
49
|
+
else 'list'
|
50
|
+
end
|
51
|
+
|
52
|
+
if @config['cheftacular']['rvm_gpg_key'].nil? || @config['cheftacular']['rvm_gpg_key'].blank?
|
53
|
+
raise "GPG Key not found in cheftacular.yml! Please update your rvm_gpg_key in the file!"
|
54
|
+
end
|
55
|
+
|
56
|
+
nodes = ARGV[1] == 'test' ? @config['getter'].get_true_node_objects : @config['getter'].get_true_node_objects(true)
|
57
|
+
|
58
|
+
nodes = @config['parser'].exclude_nodes( nodes, [{ unless: { env: @options['env'] }}] ) unless ARGV[1] == 'all_servers'
|
59
|
+
|
60
|
+
@config['chef_environments'].each do |env|
|
61
|
+
@config['initializer'].initialize_data_bags_for_environment env, false, ['addresses', 'server_passwords']
|
62
|
+
|
63
|
+
@config['initializer'].initialize_passwords env
|
64
|
+
end if ARGV[1] == 'all_servers'
|
65
|
+
|
66
|
+
options, locs, ridley, logs_bag_hash, pass_bag_hash, bundle_command, cheftacular, passwords = @config['helper'].set_local_instance_vars
|
67
|
+
|
68
|
+
on ( nodes.map { |n| "deploy@" + n.public_ipaddress } ), in: :groups, limit: 5, wait: 2 do |host|
|
69
|
+
n = get_node_from_address(nodes, host.hostname)
|
70
|
+
|
71
|
+
puts "Beginning run of \"rvm #{ command }\" for #{ n.name } (#{ n.public_ipaddress })"
|
72
|
+
|
73
|
+
start_rvm( n.name, n.public_ipaddress, options, locs, passwords, command, cheftacular )
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
module SSHKit
|
80
|
+
module Backend
|
81
|
+
class Netssh
|
82
|
+
def start_rvm name, ip_address, options, locs, passwords, command, cheftacular, out=""
|
83
|
+
log_loc, timestamp = set_log_loc_and_timestamp(locs)
|
84
|
+
upgrade_rvm = command.include?('get stable')
|
85
|
+
rvm_location = "/home/#{ cheftacular['deploy_user'] }/.rvm/bin/rvm"
|
86
|
+
|
87
|
+
puts "Generating rvm log file for #{ name } (#{ ip_address }) at #{ log_loc }/rvm/#{ name }-rvm-#{ timestamp }.txt"
|
88
|
+
|
89
|
+
|
90
|
+
if !test("[ -e /home/#{ cheftacular['deploy_user'] }/.rvm/bin/rvm ]") #true if file exists
|
91
|
+
puts "#{ name } (#{ ip_address }) does not have a rvm bin command at the moment! Updating installation to latest..."
|
92
|
+
|
93
|
+
upgrade_rvm = true
|
94
|
+
end
|
95
|
+
|
96
|
+
if upgrade_rvm
|
97
|
+
out << sudo_capture( passwords[ip_address], :chown, "#{ cheftacular['deploy_user'] }:root", '-R', "/home/#{ cheftacular['deploy_user'] }/.gnupg")
|
98
|
+
|
99
|
+
out << capture( :gpg, '--keyserver hkp://keys.gnupg.net', "--recv-keys #{ cheftacular['rvm_gpg_key'] }")
|
100
|
+
|
101
|
+
rvm_location = "/home/#{ cheftacular['deploy_user'] }/.rvm/.rvm/bin/rvm" if test("[ -e /home/#{ cheftacular['deploy_user'] }/.rvm/.rvm/bin/rvm ]")
|
102
|
+
end
|
103
|
+
|
104
|
+
out << capture( rvm_location, command )
|
105
|
+
|
106
|
+
::File.open("#{ log_loc }/rvm/#{ name }-rvm-#{ timestamp }.txt", "w") { |f| f.write(out.scrub_pretty_text) } unless options['no_logs']
|
107
|
+
|
108
|
+
puts(out.scrub_pretty_text) if options['output'] || options['verbose']
|
11
109
|
|
110
|
+
puts "Succeeded run of \"rvm #{ command }\" for #{ name } (#{ ip_address })"
|
111
|
+
end
|
12
112
|
end
|
13
113
|
end
|
14
114
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class Cheftacular
|
2
|
+
class StatelessActionDocumentation
|
3
|
+
def slack
|
4
|
+
@config['documentation']['stateless_action'] << [
|
5
|
+
"`cft slack \"MESSAGE\" [CHANNEL]` will attempt to post the message to the webhook set in your cheftacular.yml. " +
|
6
|
+
"Slack posts to your default channel by default but if the CHANNEL argument is supplied the message will post there.",
|
7
|
+
]
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class StatelessAction
|
12
|
+
def slack
|
13
|
+
notifier = Slack::Notifier.new @config['cheftacular']['slack_webhook'], username: 'Cheftacular'
|
14
|
+
|
15
|
+
notifier.channel = '#default' unless ARGV[2]
|
16
|
+
notifier.ping ARGV[1]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/cheftacular/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cheftacular
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Louis Alridge
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-04-
|
11
|
+
date: 2015-04-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: hashie
|
@@ -193,27 +193,13 @@ dependencies:
|
|
193
193
|
- !ruby/object:Gem::Version
|
194
194
|
version: '0'
|
195
195
|
- !ruby/object:Gem::Dependency
|
196
|
-
name:
|
197
|
-
requirement: !ruby/object:Gem::Requirement
|
198
|
-
requirements:
|
199
|
-
- - '='
|
200
|
-
- !ruby/object:Gem::Version
|
201
|
-
version: 1.6.1
|
202
|
-
type: :development
|
203
|
-
prerelease: false
|
204
|
-
version_requirements: !ruby/object:Gem::Requirement
|
205
|
-
requirements:
|
206
|
-
- - '='
|
207
|
-
- !ruby/object:Gem::Version
|
208
|
-
version: 1.6.1
|
209
|
-
- !ruby/object:Gem::Dependency
|
210
|
-
name: mechanize
|
196
|
+
name: slack-notifier
|
211
197
|
requirement: !ruby/object:Gem::Requirement
|
212
198
|
requirements:
|
213
199
|
- - ">="
|
214
200
|
- !ruby/object:Gem::Version
|
215
201
|
version: '0'
|
216
|
-
type: :
|
202
|
+
type: :runtime
|
217
203
|
prerelease: false
|
218
204
|
version_requirements: !ruby/object:Gem::Requirement
|
219
205
|
requirements:
|
@@ -270,6 +256,7 @@ files:
|
|
270
256
|
- lib/cheftacular/stateless_actions/bootstrappers/redhat_bootstrap.rb
|
271
257
|
- lib/cheftacular/stateless_actions/bootstrappers/ubuntu_bootstrap.rb
|
272
258
|
- lib/cheftacular/stateless_actions/bootstrappers/vyatta_bootstrap.rb
|
259
|
+
- lib/cheftacular/stateless_actions/check_cheftacular_settings.rb
|
273
260
|
- lib/cheftacular/stateless_actions/chef_bootstrap.rb
|
274
261
|
- lib/cheftacular/stateless_actions/chef_environment.rb
|
275
262
|
- lib/cheftacular/stateless_actions/clean_cookbooks.rb
|
@@ -302,6 +289,7 @@ files:
|
|
302
289
|
- lib/cheftacular/stateless_actions/rvm.rb
|
303
290
|
- lib/cheftacular/stateless_actions/server_update.rb
|
304
291
|
- lib/cheftacular/stateless_actions/service.rb
|
292
|
+
- lib/cheftacular/stateless_actions/slack.rb
|
305
293
|
- lib/cheftacular/stateless_actions/test_env.rb
|
306
294
|
- lib/cheftacular/stateless_actions/update_split_branches.rb
|
307
295
|
- lib/cheftacular/stateless_actions/update_tld.rb
|
@@ -342,9 +330,6 @@ files:
|
|
342
330
|
- lib/cloud_interactor/volume/list.rb
|
343
331
|
- lib/cloud_interactor/volume/read.rb
|
344
332
|
- lib/ridley/monkeypatches.rb
|
345
|
-
- lib/sshkit/actions/start_commit_check.rb
|
346
|
-
- lib/sshkit/actions/start_deploy.rb
|
347
|
-
- lib/sshkit/actions/start_log_fetch.rb
|
348
333
|
- lib/sshkit/actions/start_task.rb
|
349
334
|
- lib/sshkit/getters.rb
|
350
335
|
- lib/sshkit/helpers.rb
|
@@ -1,19 +0,0 @@
|
|
1
|
-
module SSHKit
|
2
|
-
module Backend
|
3
|
-
class Netssh
|
4
|
-
def start_commit_check name, ip_address, options, locs, cheftacular, out={'name'=>'', 'time'=> ''}
|
5
|
-
app_loc = "#{ cheftacular['base_file_path'] }/#{ options['repository'] }/releases"
|
6
|
-
|
7
|
-
if test("[ -d #{ app_loc } ]") #true if file exists
|
8
|
-
within app_loc do
|
9
|
-
out['name'] = capture( :ls, '-rt', :|, :tail, '-1' )
|
10
|
-
|
11
|
-
out['time'] = Time.parse(capture( :stat, out['name'], '--printf=%y' )).strftime('%Y-%m-%d %I:%M:%S %p')
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
out
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
module SSHKit
|
2
|
-
module Backend
|
3
|
-
class Netssh
|
4
|
-
def start_deploy name, ip_address, options, locs, passwords, out=""
|
5
|
-
log_loc, timestamp = set_log_loc_and_timestamp(locs)
|
6
|
-
|
7
|
-
puts "Generating log file for #{ name } (#{ ip_address }) at #{ log_loc }/#{ name }-deploy-#{ timestamp }.txt"
|
8
|
-
|
9
|
-
capture_args = [ "chef-client" ]
|
10
|
-
capture_args << [ '-l', 'debug' ] if options['debug']
|
11
|
-
#capture_args << [ '>', '/dev/tty']
|
12
|
-
|
13
|
-
out << sudo_capture( passwords[ip_address], *capture_args.flatten )
|
14
|
-
|
15
|
-
::File.open("#{ log_loc }/#{ name }-deploy-#{ timestamp }.txt", "w") { |f| f.write(out.scrub_pretty_text) } unless options['no_logs']
|
16
|
-
|
17
|
-
puts(out) if options['output'] || options['verbose']
|
18
|
-
|
19
|
-
puts "Succeeded deploy of #{ name } (#{ ip_address }) on role #{ options['role'] }"
|
20
|
-
|
21
|
-
[out, timestamp] #return out to send to logs_bag
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,92 +0,0 @@
|
|
1
|
-
module SSHKit
|
2
|
-
module Backend
|
3
|
-
class Netssh
|
4
|
-
def start_log_role_map name, ip_address, target_log_loc, options, locs, cheftacular, passwords, out=""
|
5
|
-
log_loc, timestamp = set_log_loc_and_timestamp(locs)
|
6
|
-
log_cmnd, log_lines = get_log_command_and_lines(options)
|
7
|
-
|
8
|
-
|
9
|
-
puts "Fetching log file(s) for #{ name } (#{ ip_address }). Outputting to #{ log_loc } with timestamp: #{ timestamp }"
|
10
|
-
|
11
|
-
target_log_loc.split(',').each do |parsed_log_loc|
|
12
|
-
parsed_log_loc = parsed_log_loc.gsub('|current_repo_location|', "#{ cheftacular['base_file_path'] }/#{ options['repository'] }/current")
|
13
|
-
|
14
|
-
if parsed_log_loc != '/var/log/syslog' && !test("[ -e #{ parsed_log_loc }]") #true if file exists ()
|
15
|
-
puts "#{ name } (#{ ip_address }) does not have a #{ parsed_log_loc } log file for #{ options['env'] } at the moment..."
|
16
|
-
else
|
17
|
-
if log_lines.nil?
|
18
|
-
out << sudo_capture(passwords[ip_address], log_cmnd.to_sym, parsed_log_loc)
|
19
|
-
|
20
|
-
else
|
21
|
-
out << sudo_capture(passwords[ip_address], log_cmnd.to_sym, log_lines, parsed_log_loc)
|
22
|
-
end
|
23
|
-
|
24
|
-
::File.open("#{ log_loc }/#{ name }-#{ parsed_log_loc.split('/').last.split('.').first }-#{ timestamp }.txt", "w") { |f| f.write(out.scrub_pretty_text) } unless options['no_logs']
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def start_log_fetch_ruby_on_rails name, ip_address, run_list, options, locs, cheftacular, passwords, out=""
|
30
|
-
log_loc, timestamp = set_log_loc_and_timestamp(locs)
|
31
|
-
true_env = get_true_environment run_list, cheftacular['run_list_environments'], options['env']
|
32
|
-
app_log_loc = "#{ cheftacular['base_file_path'] }/#{ options['repository'] }/current/log"
|
33
|
-
log_cmnd, log_lines = get_log_command_and_lines(options)
|
34
|
-
|
35
|
-
if !test("[ -e /#{ app_log_loc }/#{ true_env }.log ]") #true if file exists
|
36
|
-
puts "#{ name } (#{ ip_address }) does not have a log file for #{ true_env } at the moment..."
|
37
|
-
|
38
|
-
else
|
39
|
-
|
40
|
-
puts "Fetching log file(s) for #{ name } (#{ ip_address }). Outputting to #{ log_loc }/#{ name }-applog-#{ timestamp }.txt"
|
41
|
-
|
42
|
-
within app_log_loc do
|
43
|
-
if log_lines.nil?
|
44
|
-
out << capture(log_cmnd.to_sym, "#{ true_env }.log")
|
45
|
-
|
46
|
-
else
|
47
|
-
out << capture(log_cmnd.to_sym, log_lines, "#{ true_env }.log")
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
#To create the file locally you must namespace like this
|
52
|
-
::File.open("#{ log_loc }/#{ name }-applog-#{ timestamp }.txt", "w") { |f| f.write(out.scrub_pretty_text) } unless options['no_logs']
|
53
|
-
end
|
54
|
-
|
55
|
-
out << start_log_fetch_nginx(name, log_loc, log_cmnd, timestamp, options, out) if run_list.include?('role[web]') && options['get_nginx_logs']
|
56
|
-
|
57
|
-
out << start_log_role_map(name, ip_address, get_role_map(cheftacular, get_worker_role(cheftacular))['log_location'], log_cmnd, app_log_loc, timestamp, options) if run_list.include?("role[#{ get_worker_role(cheftacular) }]")
|
58
|
-
|
59
|
-
puts(out) if options['verbose']
|
60
|
-
end
|
61
|
-
|
62
|
-
def start_log_fetch_nginx name, log_loc, log_cmnd, timestamp, options, out=""
|
63
|
-
out = "" unless options['no_logs']
|
64
|
-
|
65
|
-
nginx_log_loc = "/var/log/nginx/#{ options['repository'] }_access.log"
|
66
|
-
|
67
|
-
puts "Fetching nginx log file... Outputting to #{ log_loc }/#{ name }-nginxlog-#{ timestamp }.txt "
|
68
|
-
|
69
|
-
if log_lines.nil?
|
70
|
-
out << capture(log_cmnd.to_sym, nginx_log_loc)
|
71
|
-
|
72
|
-
else
|
73
|
-
out << capture(log_cmnd.to_sym, log_lines, nginx_log_loc)
|
74
|
-
end
|
75
|
-
|
76
|
-
::File.open("#{ log_loc }/#{ name }-nginxlog-#{ timestamp }.txt", "w") { |f| f.write(out.scrub_pretty_text) } unless options['no_logs']
|
77
|
-
|
78
|
-
out
|
79
|
-
end
|
80
|
-
|
81
|
-
private
|
82
|
-
|
83
|
-
def get_log_command_and_lines options
|
84
|
-
log_cmnd = options['get_full_logs'] ? 'cat' : 'tail'
|
85
|
-
|
86
|
-
log_lines = options['get_full_logs'] ? nil : "-" + ( options['get_log_lines'] ? options['get_log_lines'] : "500" )
|
87
|
-
|
88
|
-
[log_cmnd, log_lines]
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|