fastlyctl 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +34 -0
- data/LICENSE.txt +21 -0
- data/README.md +324 -0
- data/Rakefile +1 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/build.rb +3 -0
- data/exe/fastlyctl +6 -0
- data/fastlyctl.gemspec +38 -0
- data/lib/fastlyctl/cli.rb +43 -0
- data/lib/fastlyctl/clone_utils.rb +149 -0
- data/lib/fastlyctl/commands/acl.rb +88 -0
- data/lib/fastlyctl/commands/activate.rb +27 -0
- data/lib/fastlyctl/commands/clone.rb +40 -0
- data/lib/fastlyctl/commands/copy.rb +41 -0
- data/lib/fastlyctl/commands/create_service.rb +18 -0
- data/lib/fastlyctl/commands/dictionary.rb +75 -0
- data/lib/fastlyctl/commands/diff.rb +97 -0
- data/lib/fastlyctl/commands/domain.rb +47 -0
- data/lib/fastlyctl/commands/download.rb +85 -0
- data/lib/fastlyctl/commands/login.rb +58 -0
- data/lib/fastlyctl/commands/open.rb +24 -0
- data/lib/fastlyctl/commands/purge_all.rb +17 -0
- data/lib/fastlyctl/commands/skeleton.rb +24 -0
- data/lib/fastlyctl/commands/snippet.rb +105 -0
- data/lib/fastlyctl/commands/token.rb +53 -0
- data/lib/fastlyctl/commands/upload.rb +155 -0
- data/lib/fastlyctl/commands/watch.rb +49 -0
- data/lib/fastlyctl/fetcher.rb +250 -0
- data/lib/fastlyctl/utils.rb +72 -0
- data/lib/fastlyctl/version.rb +3 -0
- data/lib/fastlyctl.rb +28 -0
- metadata +155 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c99e7a36c4d22a02bd9dc8547be8e57e026b5e781eca956454bf29567ab0ff12
|
4
|
+
data.tar.gz: a5c608f10b5259f9f08d61ee77f18c874a46aae079943b812854bc615eddc7ef
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6b33f5cdc219afdb8be0872a893577264c7a1c7c16911a29646807dddf75f8cef941f3dd5c9aaa2b28c770705da12a7dbdadf7a8844d70d10e07d9a8977f09a7
|
7
|
+
data.tar.gz: 9326d1f7ba46d301582fffd593d6a6821df4b4a2aab124d889a49f261c8bb3a250d780c8cded06b4b94512864aa4388cb8a65b7ecf0f73ebcc9d1afcdbd0ce6b
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
fastlyctl (1.0.0)
|
5
|
+
bundler (~> 1.10)
|
6
|
+
diffy (~> 3.2.1)
|
7
|
+
launchy (~> 2.4.3, >= 2.4.3)
|
8
|
+
thor (~> 0.19.4)
|
9
|
+
typhoeus (~> 1.3.1)
|
10
|
+
|
11
|
+
GEM
|
12
|
+
remote: https://rubygems.org/
|
13
|
+
specs:
|
14
|
+
addressable (2.6.0)
|
15
|
+
public_suffix (>= 2.0.2, < 4.0)
|
16
|
+
diffy (3.2.1)
|
17
|
+
ethon (0.12.0)
|
18
|
+
ffi (>= 1.3.0)
|
19
|
+
ffi (1.10.0)
|
20
|
+
launchy (2.4.3)
|
21
|
+
addressable (~> 2.3)
|
22
|
+
public_suffix (3.0.3)
|
23
|
+
thor (0.19.4)
|
24
|
+
typhoeus (1.3.1)
|
25
|
+
ethon (>= 0.9.0)
|
26
|
+
|
27
|
+
PLATFORMS
|
28
|
+
ruby
|
29
|
+
|
30
|
+
DEPENDENCIES
|
31
|
+
fastlyctl!
|
32
|
+
|
33
|
+
BUNDLED WITH
|
34
|
+
1.17.2
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Stephen Basile
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,324 @@
|
|
1
|
+
# FastlyCTL
|
2
|
+
|
3
|
+
CLI for manipulating objects with [Fastly's API](https://docs.fastly.com/api/config).
|
4
|
+
|
5
|
+
## Dependencies
|
6
|
+
|
7
|
+
* Ruby 2.2+
|
8
|
+
* diff
|
9
|
+
* Bundler
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
```
|
14
|
+
gem install fastlyctl
|
15
|
+
```
|
16
|
+
|
17
|
+
## Workflow
|
18
|
+
|
19
|
+
Basic setup for a service:
|
20
|
+
|
21
|
+
```
|
22
|
+
$ fastlyctl download --service 72rdJo8ipqaHRFYnn12G2q
|
23
|
+
No VCLs on this service, however a folder has been created. Create VCLs in this folder and upload.
|
24
|
+
$ cd Sandbox\ -\ 72rdJo8ipqaHRFYnn12G2q/
|
25
|
+
$ fastlyctl skeleton
|
26
|
+
Boilerplate written to main.vcl.
|
27
|
+
$ fastlyctl upload
|
28
|
+
VCL main does not currently exist on the service, would you like to create it? y
|
29
|
+
[You will see a diff here for the new VCL]
|
30
|
+
Given the above diff, are you sure you want to upload your changes? y
|
31
|
+
main uploaded to 72rdJo8ipqaHRFYnn12G2q
|
32
|
+
VCL(s) have been uploaded to version 286 and validated.
|
33
|
+
$ fastlyctl activate
|
34
|
+
Version 286 on 72rdJo8ipqaHRFYnn12G2q activated.
|
35
|
+
```
|
36
|
+
|
37
|
+
Once you are past this point you can edit your VCLs and use the commmand `fastlyctl upload && fastlyctl activate`. The service ID will be automatically inferred from the folder you are currently in. In fact, all commands will attempt to assume the service ID of the current directory if it is relevant.
|
38
|
+
|
39
|
+
You may find it useful to keep a Github repo with one folder created by this command for each service. This way you can version your VCL files.
|
40
|
+
|
41
|
+
## Command Reference
|
42
|
+
|
43
|
+
### acl
|
44
|
+
|
45
|
+
Manipulate ACLs on a service.
|
46
|
+
|
47
|
+
Usage:
|
48
|
+
|
49
|
+
```
|
50
|
+
fastlyctl acl [action] [acl_name] [ip_or_subnet]
|
51
|
+
```
|
52
|
+
|
53
|
+
Available Actions:
|
54
|
+
* create: Creates a new ACL. `ip_or_subnet` parameter is omitted.
|
55
|
+
* delete: Deletes an ACL. `ip_or_subnet` parameter is omitted.
|
56
|
+
* list: Lists all ACLs. `ip_or_subnet` parameter is omitted.
|
57
|
+
* add: Adds a new IP or Subnet to an ACL.
|
58
|
+
* remove: Removes an IP or Subnet from an ACL.
|
59
|
+
* list_ips: Lists all IPs/Subnets in an ACL.
|
60
|
+
* bulk_add: Adds multiple items to an ACL. See [this documentation](https://docs.fastly.com/api/config#acl_entry_c352ca5aee49b7898535cce488e3ba82) for information on the format.
|
61
|
+
|
62
|
+
Flags:
|
63
|
+
* --s: The service ID to use. Current working directory is assumed.
|
64
|
+
* --v: The version to use. Latest writable version is assumed.
|
65
|
+
|
66
|
+
### activate
|
67
|
+
|
68
|
+
Activates a service version.
|
69
|
+
|
70
|
+
Usage:
|
71
|
+
|
72
|
+
```
|
73
|
+
fastlyctl activate
|
74
|
+
```
|
75
|
+
|
76
|
+
Flags:
|
77
|
+
* --s: The service ID to activate. Current working directory is assumed.
|
78
|
+
* --v: The version to activate. Latest writable version is assumed.
|
79
|
+
* --c: Adds a comment to the version.
|
80
|
+
|
81
|
+
### clone
|
82
|
+
|
83
|
+
Clones a service version to a new version on another service.
|
84
|
+
|
85
|
+
Usage:
|
86
|
+
|
87
|
+
```
|
88
|
+
fastlyctl clone [sid_1] [sid_2]
|
89
|
+
```
|
90
|
+
|
91
|
+
Flags
|
92
|
+
* --v: The version to clone. The currently active version is assumed.
|
93
|
+
* --sl: Skip logging objects during the clone.
|
94
|
+
|
95
|
+
### copy
|
96
|
+
|
97
|
+
Copies an object from one service to another
|
98
|
+
|
99
|
+
Usage:
|
100
|
+
|
101
|
+
```
|
102
|
+
fastlyctl copy [sid_1] [sid_2] [obj_type] [obj_name]
|
103
|
+
```
|
104
|
+
|
105
|
+
Flags
|
106
|
+
* --v1: The version to clone from on the source service. The currently active version is assumed.
|
107
|
+
* --v2: The version to clone to on the target service. Latest writable version is assumed.
|
108
|
+
|
109
|
+
### create_service
|
110
|
+
|
111
|
+
Creates a new service.
|
112
|
+
|
113
|
+
Usage:
|
114
|
+
|
115
|
+
```
|
116
|
+
fastlyctl create_service [name]
|
117
|
+
```
|
118
|
+
|
119
|
+
Flags:
|
120
|
+
* --c: [Admin only] The customer ID to create the service on.
|
121
|
+
|
122
|
+
### dictionary
|
123
|
+
|
124
|
+
Manipulate edge dictionaries on a service.
|
125
|
+
|
126
|
+
Usage:
|
127
|
+
|
128
|
+
```
|
129
|
+
fastlyctl dictionary [action] [dictionary_name] [key] [value]
|
130
|
+
```
|
131
|
+
|
132
|
+
Available Actions:
|
133
|
+
* create: Creates a new dictionary. Key and value parameters are omitted.
|
134
|
+
* delete: Deletes a dictionary. Key and value parameters are omitted.
|
135
|
+
* list: Lists all dictionaries. Key and value parameters are omitted.
|
136
|
+
* upsert: Inserts a new item into a dictionary. If the item exists, its value will be updated.
|
137
|
+
* remove: Removes an item from a dictionary.
|
138
|
+
* list_items: Lists all items in a dictionary.
|
139
|
+
* bulk_add: Adds multiple items to a dictionary. See [this documentation](https://docs.fastly.com/api/config#dictionary_item_dc826ce1255a7c42bc48eb204eed8f7f) for information on the format.
|
140
|
+
|
141
|
+
Flags:
|
142
|
+
* --s: The service ID to use. Current working directory is assumed.
|
143
|
+
* --v: The version to use. Latest writable version is assumed.
|
144
|
+
|
145
|
+
### diff
|
146
|
+
|
147
|
+
Provides a diff of two service versions. You may optionally specify which two service IDs and which two versions to diff. If you do not provide service IDs, the context of the current working directory is assumed.
|
148
|
+
|
149
|
+
* If you provide no service IDs, the service ID of the working directory is assumed.
|
150
|
+
* If you do not specify versions, active VCL will be diffed with local VCL in the current directory.
|
151
|
+
* If you specify version 1 but not version 2, version 1 will be diffed with local VCL
|
152
|
+
* If you specify both versions, they will be diffed with each other.
|
153
|
+
* If you provide service 1 but not service 2, service 2 will be assumed from the current working directory.
|
154
|
+
* Regardless of how you specify services, if service 1 and service 2 are _different_, the versions will default to the active versions instead of local VCL.
|
155
|
+
|
156
|
+
Usage:
|
157
|
+
|
158
|
+
```
|
159
|
+
fastlyctl diff
|
160
|
+
```
|
161
|
+
|
162
|
+
* --s1: The first service to diff against.
|
163
|
+
* --v1: The version to diff.
|
164
|
+
* --s2: The second service to diff against.
|
165
|
+
* --v2: The second service's version to diff.
|
166
|
+
* --g: Diffs the generated VCL instead of the custom VCL.
|
167
|
+
|
168
|
+
### domain
|
169
|
+
|
170
|
+
Manipulate domains on a service.
|
171
|
+
|
172
|
+
Usage:
|
173
|
+
|
174
|
+
```
|
175
|
+
fastlyctl domain [action] [hostname]
|
176
|
+
```
|
177
|
+
|
178
|
+
Available Actions:
|
179
|
+
* create: Create a new domain.
|
180
|
+
* delete: Delete a domain.
|
181
|
+
* list: List all domains.
|
182
|
+
* check: Check the DNS of all domains on a service and print the status.
|
183
|
+
|
184
|
+
Flags:
|
185
|
+
* --s: The service ID to use. Current working directory is assumed.
|
186
|
+
* --v: The version to use. Latest writable version is assumed.
|
187
|
+
|
188
|
+
### download
|
189
|
+
|
190
|
+
Download the VCLs and snippets on a service. If you are not in a service directory already, a new directory will be created.
|
191
|
+
|
192
|
+
Usage:
|
193
|
+
|
194
|
+
```
|
195
|
+
fastlyctl download
|
196
|
+
```
|
197
|
+
|
198
|
+
Flags:
|
199
|
+
* --s: The service ID to download. Current working directory is assumed.
|
200
|
+
* --v: The version to download. The currently active version is assumed.
|
201
|
+
|
202
|
+
### login
|
203
|
+
|
204
|
+
Login to the Fastly app and create an API token. This token will be stored in your home directory for the CLI to use for all requests.
|
205
|
+
|
206
|
+
If your origanization uses SSO to login to Fastly, this command will prompt you to create a token and save it to `~/.fastlyctl_token` on your computer. You may also create the token and save it to the fastlyctl_token file without using the `fastlyctl login` command at all.
|
207
|
+
|
208
|
+
Usage:
|
209
|
+
|
210
|
+
```
|
211
|
+
fastlyctl login
|
212
|
+
```
|
213
|
+
|
214
|
+
### open
|
215
|
+
|
216
|
+
Opens the Fastly app for a service for a hostname of a service ID.
|
217
|
+
|
218
|
+
Usage:
|
219
|
+
|
220
|
+
```
|
221
|
+
fastlyctl open [hostname]
|
222
|
+
```
|
223
|
+
|
224
|
+
Flags:
|
225
|
+
* --s: The service ID to open. Current working directory is assumed.
|
226
|
+
|
227
|
+
### purge_all
|
228
|
+
|
229
|
+
Perform a purge all on a service.
|
230
|
+
|
231
|
+
Usage:
|
232
|
+
|
233
|
+
```
|
234
|
+
fastlyctl purge_all
|
235
|
+
```
|
236
|
+
Flags:
|
237
|
+
* --s: The service ID to purge. Current working directory is assumed.
|
238
|
+
|
239
|
+
### skeleton
|
240
|
+
|
241
|
+
Download the VCL boilerplate into the current directory.
|
242
|
+
|
243
|
+
Usage
|
244
|
+
|
245
|
+
```
|
246
|
+
fastlyctl skeleton [local_filename]
|
247
|
+
```
|
248
|
+
|
249
|
+
### snippet
|
250
|
+
|
251
|
+
Manipulate snippets on a service.
|
252
|
+
|
253
|
+
Usage:
|
254
|
+
|
255
|
+
```
|
256
|
+
fastlyctl snippet [action] [snippet_name]
|
257
|
+
```
|
258
|
+
|
259
|
+
Available Actions:
|
260
|
+
* create: Create a new snippet
|
261
|
+
* upload: Upload a specific dynamic snippet
|
262
|
+
* delete: Delete a snippet
|
263
|
+
* list: List all snippets
|
264
|
+
|
265
|
+
Flags:
|
266
|
+
* --s: The service ID to use. Current working directory is assumed.
|
267
|
+
* --v: The version to use. Latest writable version is assumed.
|
268
|
+
* --t: The type of snippet to create. Types are named after subroutines--for instance a snippet for `vcl_recv` would be of type `recv`. Use `init` for snippets outside of a subroutine.
|
269
|
+
* --d: When used with the create command, specifies that the snippet should be dynamic.
|
270
|
+
|
271
|
+
### token
|
272
|
+
|
273
|
+
Manipulate tokens for an account.
|
274
|
+
|
275
|
+
Usage:
|
276
|
+
|
277
|
+
```
|
278
|
+
fastlyctl token [action]
|
279
|
+
```
|
280
|
+
|
281
|
+
Available Actions:
|
282
|
+
* create: Create a token
|
283
|
+
* delete: Delete a token
|
284
|
+
* list: List all tokens on the account
|
285
|
+
|
286
|
+
Flags:
|
287
|
+
* --scope: Scope of the token. See Fastly's public API documentation for a [list of scopes](https://docs.fastly.com/api/auth#scopes).
|
288
|
+
* --s: The services to restrict this token to. The token cannot be used to modify any services not on this list if this option is specified.
|
289
|
+
|
290
|
+
### upload
|
291
|
+
|
292
|
+
Upload VCLs and snippets to a service.
|
293
|
+
|
294
|
+
Usage:
|
295
|
+
|
296
|
+
```
|
297
|
+
fastlyctl upload
|
298
|
+
```
|
299
|
+
|
300
|
+
Flags:
|
301
|
+
* --v: The version to upload the VCL to. The latest writable version is assumed.
|
302
|
+
* --c: Adds a comment to the version.
|
303
|
+
|
304
|
+
### watch
|
305
|
+
|
306
|
+
Watch live stats on a service.
|
307
|
+
|
308
|
+
Usage:
|
309
|
+
|
310
|
+
```
|
311
|
+
fastlyctl watch [pop]
|
312
|
+
```
|
313
|
+
|
314
|
+
Flags:
|
315
|
+
* --s: The service ID to watch. Current working directory is assumed.
|
316
|
+
|
317
|
+
## Contributing
|
318
|
+
|
319
|
+
Submit a pull request. Don't break anything.
|
320
|
+
|
321
|
+
## License
|
322
|
+
|
323
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
324
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "fastlyctl"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/build.rb
ADDED
data/exe/fastlyctl
ADDED
data/fastlyctl.gemspec
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'fastlyctl/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "fastlyctl"
|
8
|
+
spec.version = FastlyCTL::VERSION
|
9
|
+
spec.authors = ["Stephen Basile"]
|
10
|
+
spec.email = ["stephen@fastly.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{CLI tool for interacting with the Fastly API}
|
13
|
+
spec.description = %q{This gem provides a CLI for managing Fastly configurations}
|
14
|
+
spec.homepage = "http://www.github.com/fastly/fastlyctl"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.required_ruby_version = '>= 2.2.0'
|
18
|
+
|
19
|
+
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
20
|
+
# delete this section to allow pushing this gem to any host.
|
21
|
+
if spec.respond_to?(:metadata)
|
22
|
+
spec.metadata['allowed_push_host'] = "https://rubygems.org/"
|
23
|
+
else
|
24
|
+
raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
25
|
+
end
|
26
|
+
|
27
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
28
|
+
spec.bindir = "exe"
|
29
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
30
|
+
spec.executables << "fastlyctl"
|
31
|
+
spec.require_paths = ["lib"]
|
32
|
+
|
33
|
+
spec.add_runtime_dependency "bundler", "~> 1.10"
|
34
|
+
spec.add_runtime_dependency "typhoeus", "~> 1.3.1"
|
35
|
+
spec.add_runtime_dependency "thor", "~> 0.19.4"
|
36
|
+
spec.add_runtime_dependency 'diffy', '~> 3.2.1'
|
37
|
+
spec.add_runtime_dependency 'launchy', '~> 2.4.3', '>= 2.4.3'
|
38
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require "fastlyctl/commands/purge_all"
|
2
|
+
require "fastlyctl/commands/open"
|
3
|
+
require "fastlyctl/commands/download"
|
4
|
+
require "fastlyctl/commands/diff"
|
5
|
+
require "fastlyctl/commands/upload"
|
6
|
+
require "fastlyctl/commands/activate"
|
7
|
+
require "fastlyctl/commands/skeleton"
|
8
|
+
require "fastlyctl/commands/clone"
|
9
|
+
require "fastlyctl/commands/create_service"
|
10
|
+
require "fastlyctl/commands/dictionary"
|
11
|
+
require "fastlyctl/commands/login"
|
12
|
+
require "fastlyctl/commands/watch"
|
13
|
+
require "fastlyctl/commands/token"
|
14
|
+
require "fastlyctl/commands/domain"
|
15
|
+
require "fastlyctl/commands/snippet"
|
16
|
+
require "fastlyctl/commands/acl"
|
17
|
+
require "fastlyctl/commands/copy"
|
18
|
+
|
19
|
+
|
20
|
+
module FastlyCTL
|
21
|
+
class CLI < Thor
|
22
|
+
class_option :debug, :desc => 'Enabled debug mode output'
|
23
|
+
|
24
|
+
def initialize(a,b,c)
|
25
|
+
unless File.exist?(FastlyCTL::TOKEN_FILE)
|
26
|
+
if yes?("Unable to locate API token. Would you like to login first?")
|
27
|
+
self.login
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
super
|
32
|
+
|
33
|
+
if options.key?(:debug)
|
34
|
+
Typhoeus::Config.verbose = true
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
desc "version", "Displays version of the VCL gem."
|
39
|
+
def version
|
40
|
+
say("VCL gem version is #{FastlyCTL::VERSION}")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
module FastlyCTL
|
2
|
+
module CloneUtils
|
3
|
+
OBJECT_TYPES = {
|
4
|
+
"condition" => {},
|
5
|
+
"acl" => {child: "entry", include_version: false},
|
6
|
+
"healthcheck" => {},
|
7
|
+
"cache_settings" => {},
|
8
|
+
"backend" => {},
|
9
|
+
"director" => {},
|
10
|
+
"dictionary" => {child: "item", include_version: false},
|
11
|
+
"gzip" => {},
|
12
|
+
"header" => {},
|
13
|
+
"request_settings" => {},
|
14
|
+
"response_object" => {},
|
15
|
+
"settings" => {method: :put},
|
16
|
+
"vcl" => {},
|
17
|
+
"snippet" => {},
|
18
|
+
"logging/s3" => {},
|
19
|
+
"logging/s3canary" => {},
|
20
|
+
"logging/azureblob" => {},
|
21
|
+
"logging/cloudfiles" => {},
|
22
|
+
"logging/digitalocean" => {},
|
23
|
+
"logging/ftp" => {},
|
24
|
+
"logging/bigquery" => {},
|
25
|
+
"logging/gcs" => {},
|
26
|
+
"logging/honeycomb" => {},
|
27
|
+
"logging/logshuttle" => {},
|
28
|
+
"logging/logentries" => {},
|
29
|
+
"logging/loggly" => {},
|
30
|
+
"logging/heroku" => {},
|
31
|
+
"logging/openstack" => {},
|
32
|
+
"logging/papertrail" => {},
|
33
|
+
"logging/scalyr" => {},
|
34
|
+
"logging/splunk" => {},
|
35
|
+
"logging/sumologic" => {},
|
36
|
+
"logging/syslog" => {}
|
37
|
+
}
|
38
|
+
|
39
|
+
def self.copy(obj,type,sid,version)
|
40
|
+
meta = FastlyCTL::CloneUtils::OBJECT_TYPES[type]
|
41
|
+
meta ||= {}
|
42
|
+
|
43
|
+
abort "No service ID on object" unless obj.key?("service_id")
|
44
|
+
source_sid = obj["service_id"]
|
45
|
+
abort "No version on object" unless obj.key?("version")
|
46
|
+
source_version = obj["version"]
|
47
|
+
|
48
|
+
if type == "director"
|
49
|
+
backends = obj["backends"].dup
|
50
|
+
end
|
51
|
+
|
52
|
+
if type == "snippet" && obj["dynamic"] == "1"
|
53
|
+
obj.merge!(FastlyCTL::Fetcher.api_request(:get, "/service/#{source_sid}/snippet/#{obj["id"]}"))
|
54
|
+
end
|
55
|
+
|
56
|
+
obj_id = obj["id"]
|
57
|
+
obj = FastlyCTL::CloneUtils.filter(type,obj)
|
58
|
+
|
59
|
+
obj = FastlyCTL::Fetcher.api_request(meta.key?(:method) ? meta[:method] : :post, "/service/#{sid}/version/#{version}/#{type}", body: obj )
|
60
|
+
|
61
|
+
if type == "director"
|
62
|
+
backends.each do |b|
|
63
|
+
FastlyCTL::Fetcher.api_request(:post, "/service/#{sid}/version/#{version}/director/#{obj["name"]}/backend/#{b}", body: obj )
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
return obj unless meta.key?(:child)
|
68
|
+
new_obj_id = obj["id"]
|
69
|
+
child = meta[:child]
|
70
|
+
|
71
|
+
path = FastlyCTL::CloneUtils.construct_path(source_sid,source_version,meta[:include_version])
|
72
|
+
|
73
|
+
items = []
|
74
|
+
entries = []
|
75
|
+
FastlyCTL::Fetcher.api_request(:get, "#{path}/#{type}/#{obj_id}/#{FastlyCTL::CloneUtils.pluralize(child)}").each do |child_obj|
|
76
|
+
case child
|
77
|
+
when "item"
|
78
|
+
items.push({
|
79
|
+
"op" => "create","item_key" => child_obj["item_key"],"item_value" => child_obj["item_value"]
|
80
|
+
})
|
81
|
+
next
|
82
|
+
when "entry"
|
83
|
+
entries.push({
|
84
|
+
"op" => "create","ip" => child_obj["ip"],"subnet" => child_obj["subnet"]
|
85
|
+
})
|
86
|
+
next
|
87
|
+
end
|
88
|
+
|
89
|
+
child_obj = FastlyCTL::CloneUtils.filter(type,child_obj)
|
90
|
+
|
91
|
+
path = FastlyCTL::CloneUtils.construct_path(sid,version,meta[:include_version])
|
92
|
+
|
93
|
+
FastlyCTL::Fetcher.api_request(:post, "#{path}/#{type}/#{new_obj_id}/#{child}", body: child_obj )
|
94
|
+
end
|
95
|
+
|
96
|
+
FastlyCTL::Fetcher.api_request(:patch, "/service/#{sid}/dictionary/#{new_obj_id}/items", body: {"items" => items}.to_json, headers: {"Content-Type" => "application/json"} ) if items.length > 0
|
97
|
+
FastlyCTL::Fetcher.api_request(:patch, "/service/#{sid}/acl/#{new_obj_id}/entries", body: {"entries" => entries}.to_json, headers: {"Content-Type" => "application/json"} ) if entries.length > 0
|
98
|
+
|
99
|
+
return obj
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.filter(type,obj)
|
103
|
+
filter_keys = ["version","id","service_id","created_at","updated_at","deleted_at","locked"]
|
104
|
+
|
105
|
+
obj.delete_if { |key, value| filter_keys.include?(key) }
|
106
|
+
obj.delete_if { |key, value| value.nil? }
|
107
|
+
|
108
|
+
case type
|
109
|
+
when "backend"
|
110
|
+
obj.delete("ipv4")
|
111
|
+
obj.delete("hostname")
|
112
|
+
obj.delete("ipv6")
|
113
|
+
when "director"
|
114
|
+
obj.delete("backends")
|
115
|
+
when "snippet"
|
116
|
+
obj.delete("snippet_id")
|
117
|
+
when "settings"
|
118
|
+
# this is to account for a bug in the API which disallows even setting this to zero
|
119
|
+
obj.delete("general.default_pci") if obj["general.default_pci"] == 0
|
120
|
+
end
|
121
|
+
|
122
|
+
return obj
|
123
|
+
end
|
124
|
+
|
125
|
+
def self.construct_path(id,version,include_version)
|
126
|
+
if include_version != false
|
127
|
+
path = "/service/#{id}/version/#{version}"
|
128
|
+
else
|
129
|
+
path = "/service/#{id}"
|
130
|
+
end
|
131
|
+
|
132
|
+
return path
|
133
|
+
end
|
134
|
+
|
135
|
+
def self.unpluralize(type)
|
136
|
+
type = type.dup
|
137
|
+
type.sub!(/ies/,"y")
|
138
|
+
type.sub!(/s$/,"")
|
139
|
+
return type
|
140
|
+
end
|
141
|
+
|
142
|
+
def self.pluralize(type)
|
143
|
+
type = type.dup
|
144
|
+
type += "s" unless type[-1] == "s"
|
145
|
+
type.sub!(/ys$/,"ies")
|
146
|
+
return type
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|