├── Gopkg.lock ├── Gopkg.toml ├── LICENSE ├── Makefile ├── README.md ├── cmd ├── api.go ├── autogenerate │ └── autogenerate.go ├── autogenerated.go ├── configure.go └── root.go ├── definitions ├── README.md ├── definitions.go ├── definitions.toml └── definitions_test.go ├── lib ├── .cf │ └── credentials ├── creds.go └── creds_test.go ├── logo.png └── main.go /Gopkg.lock: -------------------------------------------------------------------------------- 1 | # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. 2 | 3 | 4 | [[projects]] 5 | branch = "master" 6 | name = "github.com/99designs/keyring" 7 | packages = ["."] 8 | revision = "82da6802f65f1ac7963cfc3b7c62ae12dab8ee5d" 9 | 10 | [[projects]] 11 | name = "github.com/BurntSushi/toml" 12 | packages = ["."] 13 | revision = "3012a1dbe2e4bd1391d42b32f0577cb7bbc7f005" 14 | version = "v0.3.1" 15 | 16 | [[projects]] 17 | branch = "master" 18 | name = "github.com/aulanov/go.dbus" 19 | packages = ["."] 20 | revision = "25c3068a42a0b50b877953fb249dbcffc6bd1bca" 21 | 22 | [[projects]] 23 | name = "github.com/aws/aws-sdk-go" 24 | packages = [ 25 | "aws", 26 | "aws/awserr", 27 | "aws/awsutil", 28 | "aws/client", 29 | "aws/client/metadata", 30 | "aws/corehandlers", 31 | "aws/credentials", 32 | "aws/credentials/ec2rolecreds", 33 | "aws/credentials/endpointcreds", 34 | "aws/credentials/processcreds", 35 | "aws/credentials/stscreds", 36 | "aws/csm", 37 | "aws/defaults", 38 | "aws/ec2metadata", 39 | "aws/endpoints", 40 | "aws/request", 41 | "aws/session", 42 | "aws/signer/v4", 43 | "internal/ini", 44 | "internal/sdkio", 45 | "internal/sdkrand", 46 | "internal/sdkuri", 47 | "internal/shareddefaults", 48 | "private/protocol", 49 | "private/protocol/query", 50 | "private/protocol/query/queryutil", 51 | "private/protocol/rest", 52 | "private/protocol/xml/xmlutil", 53 | "service/sts" 54 | ] 55 | revision = "a86c8123483bed64c20a08cddc5155e8e8c89dcb" 56 | version = "v1.16.31" 57 | 58 | [[projects]] 59 | name = "github.com/cloudflare/cloudflare-go" 60 | packages = ["."] 61 | revision = "9837a599c0ba49ff8208dd679b4500e8ece407a5" 62 | 63 | [[projects]] 64 | name = "github.com/danieljoos/wincred" 65 | packages = ["."] 66 | revision = "412b574fb496839b312a75fba146bd32a89001cf" 67 | version = "v1.0.1" 68 | 69 | [[projects]] 70 | name = "github.com/dvsekhvalnov/jose2go" 71 | packages = [ 72 | ".", 73 | "aes", 74 | "arrays", 75 | "base64url", 76 | "compact", 77 | "kdf", 78 | "keys/ecc", 79 | "padding" 80 | ] 81 | revision = "f21a8cedbbae609f623613ec8f81125c243212e6" 82 | version = "v1.3" 83 | 84 | [[projects]] 85 | name = "github.com/godbus/dbus" 86 | packages = ["."] 87 | revision = "2ff6f7ffd60f0f2410b3105864bdd12c7894f844" 88 | version = "v5.0.1" 89 | 90 | [[projects]] 91 | branch = "master" 92 | name = "github.com/gsterjov/go-libsecret" 93 | packages = ["."] 94 | revision = "a6f4afe4910cad8688db3e0e9b9ac92ad22d54e1" 95 | 96 | [[projects]] 97 | name = "github.com/inconshreveable/mousetrap" 98 | packages = ["."] 99 | revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" 100 | version = "v1.0" 101 | 102 | [[projects]] 103 | name = "github.com/jmespath/go-jmespath" 104 | packages = ["."] 105 | revision = "c2b33e84" 106 | 107 | [[projects]] 108 | branch = "master" 109 | name = "github.com/keybase/go-keychain" 110 | packages = ["."] 111 | revision = "f1daa725cce4049b1715f1e97d6a51880e401e70" 112 | 113 | [[projects]] 114 | name = "github.com/konsorten/go-windows-terminal-sequences" 115 | packages = ["."] 116 | revision = "5c8c8bd35d3832f5d134ae1e1e375b69a4d25242" 117 | version = "v1.0.1" 118 | 119 | [[projects]] 120 | branch = "master" 121 | name = "github.com/marshallbrekka/go-u2fhost" 122 | packages = [ 123 | ".", 124 | "bytes", 125 | "hid" 126 | ] 127 | revision = "72b0e7a3f583583996b3b382d2dfaa81fdc4b82c" 128 | 129 | [[projects]] 130 | branch = "master" 131 | name = "github.com/marshallbrekka/go.hid" 132 | packages = ["."] 133 | revision = "2c1c4616a9e71d08897a583653abca4b4ac55028" 134 | 135 | [[projects]] 136 | name = "github.com/mitchellh/go-homedir" 137 | packages = ["."] 138 | revision = "af06845cf3004701891bf4fdb884bfe4920b3727" 139 | version = "v1.1.0" 140 | 141 | [[projects]] 142 | name = "github.com/pkg/errors" 143 | packages = ["."] 144 | revision = "ba968bfe8b2f7e042a574c888954fccecfa385b4" 145 | version = "v0.8.1" 146 | 147 | [[projects]] 148 | name = "github.com/segmentio/aws-okta" 149 | packages = [ 150 | "lib", 151 | "lib/saml" 152 | ] 153 | revision = "798d7d0535489dc9c821d624ebc302f76b8123e4" 154 | version = "v0.19.5" 155 | 156 | [[projects]] 157 | name = "github.com/sirupsen/logrus" 158 | packages = ["."] 159 | revision = "e1e72e9de974bd926e5c56f83753fba2df402ce5" 160 | version = "v1.3.0" 161 | 162 | [[projects]] 163 | name = "github.com/spf13/cobra" 164 | packages = ["."] 165 | revision = "ef82de70bb3f60c65fb8eebacbb2d122ef517385" 166 | version = "v0.0.3" 167 | 168 | [[projects]] 169 | name = "github.com/spf13/pflag" 170 | packages = ["."] 171 | revision = "298182f68c66c05229eb03ac171abe6e309ee79a" 172 | version = "v1.0.3" 173 | 174 | [[projects]] 175 | branch = "master" 176 | name = "github.com/vaughan0/go-ini" 177 | packages = ["."] 178 | revision = "a98ad7ee00ec53921f08832bc06ecf7fd600e6a1" 179 | 180 | [[projects]] 181 | branch = "master" 182 | name = "github.com/vitaminwater/cgo.wchar" 183 | packages = ["."] 184 | revision = "5dd6f4be3f2a8c064325fe63439975cf37a8aa1d" 185 | 186 | [[projects]] 187 | branch = "master" 188 | name = "golang.org/x/crypto" 189 | packages = ["ssh/terminal"] 190 | revision = "193df9c0f06f8bb35fba505183eaf0acc0136505" 191 | 192 | [[projects]] 193 | branch = "master" 194 | name = "golang.org/x/net" 195 | packages = [ 196 | "html", 197 | "html/atom", 198 | "idna", 199 | "publicsuffix" 200 | ] 201 | revision = "65e2d4e15006aab9813ff8769e768bbf4bb667a0" 202 | 203 | [[projects]] 204 | branch = "master" 205 | name = "golang.org/x/sys" 206 | packages = [ 207 | "unix", 208 | "windows" 209 | ] 210 | revision = "3b5209105503162ded1863c307ac66fec31120dd" 211 | 212 | [[projects]] 213 | name = "golang.org/x/text" 214 | packages = [ 215 | "collate", 216 | "collate/build", 217 | "internal/colltab", 218 | "internal/gen", 219 | "internal/tag", 220 | "internal/triegen", 221 | "internal/ucd", 222 | "language", 223 | "secure/bidirule", 224 | "transform", 225 | "unicode/bidi", 226 | "unicode/cldr", 227 | "unicode/norm", 228 | "unicode/rangetable" 229 | ] 230 | revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" 231 | version = "v0.3.0" 232 | 233 | [[projects]] 234 | branch = "master" 235 | name = "golang.org/x/time" 236 | packages = ["rate"] 237 | revision = "85acf8d2951cb2a3bde7632f9ff273ef0379bcbd" 238 | 239 | [solve-meta] 240 | analyzer-name = "dep" 241 | analyzer-version = 1 242 | inputs-digest = "cdfce4f52044eb828996578b9195bbc99c5e6dec1216fe8b85f49ed0a9470f6f" 243 | solver-name = "gps-cdcl" 244 | solver-version = 1 245 | -------------------------------------------------------------------------------- /Gopkg.toml: -------------------------------------------------------------------------------- 1 | # Gopkg.toml example 2 | # 3 | # Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md 4 | # for detailed Gopkg.toml documentation. 5 | # 6 | # required = ["github.com/user/thing/cmd/thing"] 7 | # ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] 8 | # 9 | # [[constraint]] 10 | # name = "github.com/user/project" 11 | # version = "1.0.0" 12 | # 13 | # [[constraint]] 14 | # name = "github.com/user/project2" 15 | # branch = "dev" 16 | # source = "github.com/myfork/project2" 17 | # 18 | # [[override]] 19 | # name = "github.com/x/y" 20 | # version = "2.4.0" 21 | # 22 | # [prune] 23 | # non-go = false 24 | # go-tests = true 25 | # unused-packages = true 26 | 27 | 28 | [[constraint]] 29 | branch = "master" 30 | name = "github.com/99designs/keyring" 31 | 32 | [[constraint]] 33 | name = "github.com/BurntSushi/toml" 34 | version = "0.3.1" 35 | 36 | [[constraint]] 37 | name = "github.com/cloudflare/cloudflare-go" 38 | revision="9837a599c0ba49ff8208dd679b4500e8ece407a5" 39 | 40 | [[constraint]] 41 | name = "github.com/segmentio/aws-okta" 42 | version = "0.19.5" 43 | 44 | [[constraint]] 45 | name = "github.com/spf13/cobra" 46 | version = "0.0.3" 47 | 48 | [prune] 49 | go-tests = true 50 | unused-packages = true 51 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2018 Evan Johnson 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | 10 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | depends: 3 | dep ensure 4 | 5 | generate: 6 | go run cmd/autogenerate/autogenerate.go 7 | 8 | clean: 9 | -rm cf 10 | -rm -rf dist 11 | 12 | cf: generate 13 | go build 14 | 15 | all: depends clean cf 16 | 17 | dist-linux: 18 | GOOS=linux go build -o dist/cf-linux 19 | 20 | dist: 21 | -mkdir dist 22 | 23 | dist-osx: 24 | GOOS=darwin go build -o dist/cf-osx 25 | 26 | release: clean dist dist-linux dist-osx 27 | 28 | .PHONY: all 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | cf logo 3 |
4 | 5 | A cloudflare command line interface. It makes heavy use of [cloudflare-go](https://github.com/cloudflare/cloudflare-go) 6 | 7 | # Installation 8 | ``` 9 | go get -u github.com/ejcx/cf 10 | ``` 11 | 12 | # Demo 13 |
14 | cf logo 15 |
16 | 17 | # Usage 18 | **The cf is a full featured cli. All product areas are divided in to subcommands. All commands and subcommands will describe themselves and list options, required arguments, and information about what the command does.** 19 | 20 |
21 | cf logo 22 |
23 | 24 | **Interacting with the full Cloudflare API and retrieving the most detailed information can be done quickly and easily.** 25 | 26 |
27 | cf logo 28 |
29 | 30 | **Automate common operations quickly and easily** 31 | 32 |
33 | cf logo 34 |
35 | 36 | # Credentials 37 | Your cloudflare api credentials can be stored in `~/.cf/credentials` as 38 | environment variables or in your keychain. 39 | 40 | ### Keychain 41 | To store your credentials in your keychain run `cf configure` and enter your 42 | email, apikey, and user service apikey. 43 | ``` 44 | e :) cf configure 45 | Cloudflare Email: evan@cloudflare.com 46 | Cloudflare APIKey: 47 | Origin CA APIKey: 48 | 49 | e :) 50 | ``` 51 | ### Ignore Keychain 52 | To avoid storing your credentials in the keychain, specify the `--no-keychain` 53 | flag when calling `cf configure` to store your api credentials in plaintext. 54 | 55 | ``` 56 | e :) cf configure --help 57 | A command for configuring your cloudflare api credentials 58 | 59 | Usage: 60 | cf configure [flags] 61 | 62 | Flags: 63 | -h, --help help for configure 64 | --no-keychain Do not attempt to store cloudflare api credentials in the keychain. Just use plaintext file. 65 | 66 | e :) cf configure --no-keychain 67 | Cloudflare Email: evan@cloudflare.com 68 | Cloudflare APIKey: 69 | Service APIKey: 70 | 71 | e :) cat ~/.cf/credentials 72 | {"Email":"evan@cloudflare","Key":"xxx","UserServiceKey":"yyy","Keychain":false}% 73 | ``` 74 | 75 | ### Environment Variables 76 | The three environment variables that should be set are `CF_API_KEY`, `CF_API_EMAIL`, and `CF_USER_SERVICE_KEY`. If any of the environment variables are set then the credentials file is ignored -------------------------------------------------------------------------------- /cmd/api.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "io/ioutil" 7 | "log" 8 | "os" 9 | "strings" 10 | "time" 11 | 12 | cloudflare "github.com/cloudflare/cloudflare-go" 13 | ) 14 | 15 | func ListZones(api *cloudflare.API, ZoneNameFilter string) (resp interface{}, err error) { 16 | if ZoneNameFilter != "" { 17 | resp, err = api.ListZones(ZoneNameFilter) 18 | } else { 19 | resp, err = api.ListZones() 20 | } 21 | return 22 | } 23 | 24 | func ListDnsRecords(api *cloudflare.API, ZoneId string, Type string, Name string, Content string) (resp interface{}, err error) { 25 | rec := cloudflare.DNSRecord{} 26 | if Type != "" { 27 | rec.Type = Type 28 | } 29 | if Name != "" { 30 | rec.Name = Name 31 | } 32 | if Content != "" { 33 | rec.Content = Content 34 | } 35 | resp, err = api.DNSRecords(ZoneId, rec) 36 | return 37 | } 38 | 39 | func CreateDnsRecord(api *cloudflare.API, ZoneId string, Type string, Name string, Content string, Ttl int, NotProxied bool, Priority int) (resp interface{}, err error) { 40 | rec := cloudflare.DNSRecord{} 41 | if Type != "" { 42 | rec.Type = Type 43 | } 44 | if Name != "" { 45 | rec.Name = Name 46 | } 47 | if Content != "" { 48 | rec.Content = Content 49 | } 50 | if Priority > 0 { 51 | rec.Priority = Priority 52 | } 53 | if Ttl != 0 { 54 | rec.TTL = Ttl 55 | } 56 | rec.Proxied = true 57 | if NotProxied { 58 | rec.Proxied = false 59 | } 60 | resp, err = api.CreateDNSRecord(ZoneId, rec) 61 | return 62 | } 63 | 64 | func DeleteDnsRecord(api *cloudflare.API, ZoneId string, RecordId string) (resp interface{}, err error) { 65 | err = api.DeleteDNSRecord(ZoneId, RecordId) 66 | if err == nil { 67 | resp = map[string]interface{}{ 68 | "Success": true, 69 | } 70 | } 71 | return 72 | } 73 | 74 | func DeleteZone(api *cloudflare.API, ZoneId string) (resp interface{}, err error) { 75 | resp, err = api.DeleteZone(ZoneId) 76 | return 77 | } 78 | 79 | func CreateZone(api *cloudflare.API, Name string, Jumpstart bool, OrganizationId string) (resp interface{}, err error) { 80 | org := cloudflare.Organization{} 81 | if OrganizationId != "" { 82 | org.ID = OrganizationId 83 | } 84 | resp, err = api.CreateZone(Name, Jumpstart, org) 85 | return 86 | } 87 | 88 | func DNSRecord(api *cloudflare.API, ZoneId string, RecordId string) (resp interface{}, err error) { 89 | resp, err = api.DNSRecord(ZoneId, RecordId) 90 | return 91 | } 92 | 93 | func ListAllRateLimits(api *cloudflare.API, ZoneId string) (resp interface{}, err error) { 94 | resp, err = api.ListAllRateLimits(ZoneId) 95 | return 96 | } 97 | 98 | func ListLoadBalancers(api *cloudflare.API, ZoneId string) (resp interface{}, err error) { 99 | resp, err = api.ListLoadBalancers(ZoneId) 100 | return 101 | } 102 | 103 | func ListOrganizations(api *cloudflare.API) (resp interface{}, err error) { 104 | resp, _, err = api.ListOrganizations() 105 | return 106 | } 107 | 108 | func ListPageRules(api *cloudflare.API, ZoneId string) (resp interface{}, err error) { 109 | resp, err = api.ListPageRules(ZoneId) 110 | return 111 | } 112 | 113 | func ListCustomCerts(api *cloudflare.API, ZoneId string) (resp interface{}, err error) { 114 | resp, err = api.ListSSL(ZoneId) 115 | return 116 | } 117 | 118 | func ListUserAgentRules(api *cloudflare.API, ZoneId string, Page int) (resp interface{}, err error) { 119 | page := 1 120 | if Page != 0 { 121 | page = Page 122 | } 123 | resp, err = api.ListUserAgentRules(ZoneId, page) 124 | return 125 | } 126 | 127 | func ListWAFPackages(api *cloudflare.API, ZoneId string) (resp interface{}, err error) { 128 | resp, err = api.ListWAFPackages(ZoneId) 129 | return 130 | } 131 | 132 | func ListWAFRules(api *cloudflare.API, ZoneId string, PackageId string) (resp interface{}, err error) { 133 | resp, err = api.ListWAFRules(ZoneId, PackageId) 134 | return 135 | } 136 | 137 | func ListZoneLockdowns(api *cloudflare.API, ZoneId string, Page int) (resp interface{}, err error) { 138 | page := 1 139 | if Page != 0 { 140 | page = Page 141 | } 142 | resp, err = api.ListZoneLockdowns(ZoneId, page) 143 | return 144 | } 145 | 146 | func ZoneLockdown(api *cloudflare.API, ZoneId string, LockdownId string) (resp interface{}, err error) { 147 | resp, err = api.ZoneLockdown(ZoneId, LockdownId) 148 | return 149 | } 150 | 151 | func EditZonePaused(api *cloudflare.API, ZoneId string, Paused bool) (resp interface{}, err error) { 152 | z := cloudflare.ZoneOptions{ 153 | Paused: &Paused, 154 | } 155 | resp, err = api.EditZone(ZoneId, z) 156 | return 157 | } 158 | 159 | func EditZoneVanityNS(api *cloudflare.API, ZoneId string, VanityNs string) (resp interface{}, err error) { 160 | vns := strings.Split(VanityNs, ",") 161 | z := cloudflare.ZoneOptions{ 162 | VanityNS: vns, 163 | } 164 | resp, err = api.EditZone(ZoneId, z) 165 | return 166 | } 167 | 168 | func ZoneSetVanityNS(api *cloudflare.API, ZoneId string, VanityNs string) (resp interface{}, err error) { 169 | vns := strings.Split(VanityNs, ",") 170 | resp, err = api.ZoneSetVanityNS(ZoneId, vns) 171 | return 172 | } 173 | 174 | func EditDNSRecord(api *cloudflare.API, Proxied bool, ZoneId string, RecordId string, Type string, Name string, Content string, Ttl int) (resp interface{}, err error) { 175 | rec := cloudflare.DNSRecord{ 176 | Type: Type, 177 | Name: Name, 178 | Content: Content, 179 | Proxied: Proxied, 180 | TTL: Ttl, 181 | } 182 | err = api.UpdateDNSRecord(ZoneId, RecordId, rec) 183 | return 184 | } 185 | 186 | func ListLoadBalancerMonitors(api *cloudflare.API) (resp interface{}, err error) { 187 | resp, err = api.ListLoadBalancerMonitors() 188 | return 189 | } 190 | 191 | func ListLoadBalancerPools(api *cloudflare.API) (resp interface{}, err error) { 192 | resp, err = api.ListLoadBalancerPools() 193 | return 194 | } 195 | 196 | func ListOrganizationAccessRules(api *cloudflare.API, OrganizationId string, Notes string, Mode string, Page int) (resp interface{}, err error) { 197 | ar := cloudflare.AccessRule{} 198 | if Notes != "" { 199 | ar.Notes = Notes 200 | } 201 | if Mode != "" { 202 | ar.Mode = Mode 203 | } 204 | resp, err = api.ListOrganizationAccessRules(OrganizationId, ar, Page) 205 | return 206 | } 207 | 208 | func ListRailguns(api *cloudflare.API) (resp interface{}, err error) { 209 | resp, err = api.ListRailguns(cloudflare.RailgunListOptions{}) 210 | return 211 | } 212 | 213 | func ListZoneRailguns(api *cloudflare.API) (resp interface{}, err error) { 214 | resp, err = api.ZoneRailguns(ZoneId) 215 | return 216 | } 217 | 218 | func ListUserAccessRules(api *cloudflare.API, Notes string, Mode string, Page int) (resp interface{}, err error) { 219 | ar := cloudflare.AccessRule{} 220 | if Notes != "" { 221 | ar.Notes = Notes 222 | } 223 | if Mode != "" { 224 | ar.Mode = Mode 225 | } 226 | resp, err = api.ListUserAccessRules(ar, Page) 227 | return 228 | } 229 | 230 | func ListVirtualDns(api *cloudflare.API) (resp interface{}, err error) { 231 | resp, err = api.ListVirtualDNS() 232 | return 233 | } 234 | 235 | func AvailableZoneRatePlans(api *cloudflare.API, ZoneId string) (resp interface{}, err error) { 236 | resp, err = api.AvailableZoneRatePlans(ZoneId) 237 | return 238 | } 239 | 240 | func ConnectZoneRailgun(api *cloudflare.API, ZoneId string, RailgunId string) (resp interface{}, err error) { 241 | resp, err = api.ConnectZoneRailgun(ZoneId, RailgunId) 242 | return 243 | } 244 | 245 | func CreateCustomHostname(api *cloudflare.API, ZoneId string, Hostname string, Method string, Type string) (resp interface{}, err error) { 246 | resp, err = api.CreateCustomHostname(ZoneId, cloudflare.CustomHostname{ 247 | Hostname: Hostname, 248 | SSL: cloudflare.CustomHostnameSSL{ 249 | Method: Method, 250 | Type: Type, 251 | }, 252 | }) 253 | return 254 | } 255 | 256 | func CreateLoadBalancerMonitor(api *cloudflare.API, ExpectedCodes string, Method string, Header string, Timeout int, Path string, Interval int, Retries int, ExpectedBody string, Type string, Description string) (resp interface{}, err error) { 257 | l := cloudflare.LoadBalancerMonitor{ExpectedCodes: ExpectedCodes} 258 | if Method != "" { 259 | l.Method = Method 260 | } 261 | if Timeout > 0 { 262 | l.Timeout = Timeout 263 | } 264 | if Header != "" { 265 | h := make(map[string][]string) 266 | err = json.Unmarshal([]byte(Header), &h) 267 | if err != nil { 268 | return nil, err 269 | } 270 | l.Header = h 271 | } 272 | if Path != "" { 273 | l.Path = Path 274 | } 275 | if Interval > 0 { 276 | l.Interval = Interval 277 | } 278 | if Retries > 0 { 279 | l.Retries = Retries 280 | } 281 | if Type != "" { 282 | l.Type = Type 283 | } 284 | if Description != "" { 285 | l.Description = Description 286 | } 287 | resp, err = api.CreateLoadBalancerMonitor(l) 288 | return 289 | } 290 | 291 | func CreateLoadBalancer(api *cloudflare.API, ZoneId string, Name string, FallbackPool string, DefaultPools string, Proxied bool, Ttl int) (resp interface{}, err error) { 292 | d := strings.Split(DefaultPools, ",") 293 | l := cloudflare.LoadBalancer{ 294 | Name: Name, 295 | FallbackPool: FallbackPool, 296 | DefaultPools: d, 297 | Proxied: Proxied, 298 | } 299 | if Ttl > 0 { 300 | l.TTL = Ttl 301 | } 302 | api.CreateLoadBalancer(ZoneId, l) 303 | return 304 | } 305 | 306 | func PurgeEverything(api *cloudflare.API, ZoneId string) (resp interface{}, err error) { 307 | resp, err = api.PurgeEverything(ZoneId) 308 | return 309 | } 310 | 311 | func ActivationCheck(api *cloudflare.API, ZoneId string) (resp interface{}, err error) { 312 | resp, err = api.ZoneActivationCheck(ZoneId) 313 | return 314 | } 315 | 316 | func ZoneDetails(api *cloudflare.API, ZoneId string) (resp interface{}, err error) { 317 | resp, err = api.ZoneDetails(ZoneId) 318 | return 319 | } 320 | 321 | func GetIDByName(api *cloudflare.API, ZoneName string) (resp interface{}, err error) { 322 | resp, err = api.ZoneIDByName(ZoneName) 323 | return 324 | } 325 | 326 | func ZoneSSLSettings(api *cloudflare.API, ZoneId string) (resp interface{}, err error) { 327 | resp, err = api.ZoneSSLSettings(ZoneId) 328 | return 329 | } 330 | 331 | func ZoneSettings(api *cloudflare.API, ZoneId string) (resp interface{}, err error) { 332 | resp, err = api.ZoneSettings(ZoneId) 333 | return 334 | } 335 | 336 | func UserDetails(api *cloudflare.API) (resp interface{}, err error) { 337 | resp, err = api.UserDetails() 338 | return 339 | } 340 | 341 | func UserBillingProfile(api *cloudflare.API) (resp interface{}, err error) { 342 | resp, err = api.UserBillingProfile() 343 | return 344 | } 345 | 346 | func VirtualDNS(api *cloudflare.API, VirtualDnsId string) (resp interface{}, err error) { 347 | resp, err = api.VirtualDNS(VirtualDnsId) 348 | return 349 | } 350 | 351 | func DeleteVirtualDNS(api *cloudflare.API, VirtualDnsId string) (resp interface{}, err error) { 352 | err = api.DeleteVirtualDNS(VirtualDnsId) 353 | return 354 | } 355 | 356 | func PageRule(api *cloudflare.API, ZoneId string, PageruleId string) (resp interface{}, err error) { 357 | resp, err = api.PageRule(ZoneId, PageruleId) 358 | return 359 | } 360 | 361 | func LoadBalancerDetails(api *cloudflare.API, ZoneId string, LoadbalancerId string) (resp interface{}, err error) { 362 | resp, err = api.LoadBalancerDetails(ZoneId, LoadbalancerId) 363 | return 364 | } 365 | 366 | func LoadBalancerMonitorDetails(api *cloudflare.API, MonitorId string) (resp interface{}, err error) { 367 | resp, err = api.LoadBalancerMonitorDetails(MonitorId) 368 | return 369 | } 370 | 371 | func LoadBalancerPoolDetails(api *cloudflare.API, PoolId string) (resp interface{}, err error) { 372 | resp, err = api.LoadBalancerPoolDetails(PoolId) 373 | return 374 | } 375 | 376 | func OrganizationDetails(api *cloudflare.API, OrganizationId string) (resp interface{}, err error) { 377 | resp, err = api.OrganizationDetails(OrganizationId) 378 | return 379 | } 380 | 381 | func OrganizationInvites(api *cloudflare.API, OrganizationId string) (resp interface{}, err error) { 382 | resp, _, err = api.OrganizationInvites(OrganizationId) 383 | return 384 | } 385 | 386 | func OrganizationMembers(api *cloudflare.API, OrganizationId string) (resp interface{}, err error) { 387 | resp, _, err = api.OrganizationMembers(OrganizationId) 388 | return 389 | } 390 | 391 | func OrganizationRoles(api *cloudflare.API, OrganizationId string) (resp interface{}, err error) { 392 | resp, _, err = api.OrganizationRoles(OrganizationId) 393 | return 394 | } 395 | 396 | func OriginCertificates(api *cloudflare.API, ZoneId string) (resp interface{}, err error) { 397 | resp, err = api.OriginCertificates(cloudflare.OriginCACertificateListOptions{ZoneID: ZoneId}) 398 | return 399 | } 400 | 401 | func OriginCertificate(api *cloudflare.API, CertificateId string) (resp interface{}, err error) { 402 | resp, err = api.OriginCertificate(CertificateId) 403 | return 404 | } 405 | 406 | func SSLDetails(api *cloudflare.API, CertificateId string, ZoneId string) (resp interface{}, err error) { 407 | resp, err = api.SSLDetails(ZoneId, CertificateId) 408 | return 409 | } 410 | 411 | func RailgunDetails(api *cloudflare.API, RailgunId string) (resp interface{}, err error) { 412 | resp, err = api.RailgunDetails(RailgunId) 413 | return 414 | } 415 | 416 | func RailgunZones(api *cloudflare.API, RailgunId string) (resp interface{}, err error) { 417 | resp, err = api.RailgunZones(RailgunId) 418 | return 419 | } 420 | 421 | func RateLimit(api *cloudflare.API, ZoneId string, RatelimitId string) (resp interface{}, err error) { 422 | resp, err = api.RateLimit(ZoneId, RatelimitId) 423 | return 424 | } 425 | 426 | func RevokeOriginCertificate(api *cloudflare.API, CertificateId string) (resp interface{}, err error) { 427 | resp, err = api.RevokeOriginCertificate(CertificateId) 428 | return 429 | } 430 | 431 | func TestRailgunConnection(api *cloudflare.API, ZoneId string, RailgunId string) (resp interface{}, err error) { 432 | resp, err = api.TestRailgunConnection(ZoneId, RailgunId) 433 | return 434 | } 435 | 436 | func ZoneRailgunDetails(api *cloudflare.API, ZoneId string, RailgunId string) (resp interface{}, err error) { 437 | resp, err = api.ZoneRailgunDetails(ZoneId, RailgunId) 438 | return 439 | } 440 | 441 | func CustomHostname(api *cloudflare.API, ZoneId string, CustomHostnameId string) (resp interface{}, err error) { 442 | resp, err = api.CustomHostname(ZoneId, CustomHostnameId) 443 | return 444 | } 445 | 446 | func CustomHostnameIDByName(api *cloudflare.API, ZoneId string, Name string) (resp interface{}, err error) { 447 | resp, err = api.CustomHostnameIDByName(ZoneId, Name) 448 | return 449 | } 450 | 451 | func ZoneSetPaused(api *cloudflare.API, ZoneId string, Paused bool) (resp interface{}, err error) { 452 | resp, err = api.ZoneSetPaused(ZoneId, Paused) 453 | return 454 | } 455 | 456 | func DeletePageRule(api *cloudflare.API, ZoneId string, PageruleId string) (resp interface{}, err error) { 457 | err = api.DeletePageRule(ZoneId, PageruleId) 458 | return 459 | } 460 | 461 | func DeleteRailgun(api *cloudflare.API, RailgunId string) (resp interface{}, err error) { 462 | err = api.DeleteRailgun(RailgunId) 463 | return 464 | } 465 | 466 | func DisableRailgun(api *cloudflare.API, RailgunId string) (resp interface{}, err error) { 467 | resp, err = api.DisableRailgun(RailgunId) 468 | return 469 | } 470 | 471 | func DisconnectZoneRailgun(api *cloudflare.API, RailgunId string, ZoneId string) (resp interface{}, err error) { 472 | resp, err = api.DisconnectZoneRailgun(ZoneId, RailgunId) 473 | return 474 | } 475 | 476 | func EnableRailgun(api *cloudflare.API, RailgunId string) (resp interface{}, err error) { 477 | resp, err = api.EnableRailgun(RailgunId) 478 | return 479 | } 480 | 481 | func DeleteRateLimit(api *cloudflare.API, ZoneId string, RatelimitId string) (resp interface{}, err error) { 482 | err = api.DeleteRateLimit(ZoneId, RatelimitId) 483 | return 484 | } 485 | 486 | func DeleteSSL(api *cloudflare.API, ZoneId string, CertificateId string) (resp interface{}, err error) { 487 | err = api.DeleteSSL(ZoneId, CertificateId) 488 | return 489 | } 490 | 491 | func DeleteCustomHostname(api *cloudflare.API, ZoneId string, CustomHostnameId string) (resp interface{}, err error) { 492 | err = api.DeleteCustomHostname(ZoneId, CustomHostnameId) 493 | return 494 | } 495 | 496 | func DeleteLoadBalancer(api *cloudflare.API, ZoneId string, LoadbalancerId string) (resp interface{}, err error) { 497 | err = api.DeleteLoadBalancer(ZoneId, LoadbalancerId) 498 | return 499 | } 500 | 501 | func DeleteLoadBalancerMonitor(api *cloudflare.API, MonitorId string) (resp interface{}, err error) { 502 | err = api.DeleteLoadBalancerMonitor(MonitorId) 503 | return 504 | } 505 | 506 | func DeleteLoadBalancerPool(api *cloudflare.API, PoolId string) (resp interface{}, err error) { 507 | err = api.DeleteLoadBalancerPool(PoolId) 508 | return 509 | } 510 | 511 | func DeleteOrganizationAccessRule(api *cloudflare.API, OrganizationId string, AccessRuleId string) (resp interface{}, err error) { 512 | resp, err = api.DeleteOrganizationAccessRule(OrganizationId, AccessRuleId) 513 | return 514 | } 515 | 516 | func CreateRailgun(api *cloudflare.API, Name string) (resp interface{}, err error) { 517 | resp, err = api.CreateRailgun(Name) 518 | return 519 | } 520 | 521 | func DeleteUserAccessRule(api *cloudflare.API, AccessRuleId string) (resp interface{}, err error) { 522 | resp, err = api.DeleteUserAccessRule(AccessRuleId) 523 | return 524 | } 525 | 526 | func DeleteUserAgentRule(api *cloudflare.API, UserAgentId string, ZoneId string) (resp interface{}, err error) { 527 | resp, err = api.DeleteUserAgentRule(ZoneId, UserAgentId) 528 | return 529 | } 530 | 531 | func DeleteZoneAccessRule(api *cloudflare.API, AccessRuleId string, ZoneId string) (resp interface{}, err error) { 532 | resp, err = api.DeleteZoneAccessRule(ZoneId, AccessRuleId) 533 | return 534 | } 535 | 536 | func DeleteZoneLockdown(api *cloudflare.API, ZoneId string, LockdownId string) (resp interface{}, err error) { 537 | resp, err = api.DeleteZoneLockdown(ZoneId, LockdownId) 538 | return 539 | } 540 | 541 | func ZoneAnalyticsByColocation(api *cloudflare.API, ZoneId string, Since string, Until string, Continuous bool) (resp interface{}, err error) { 542 | z := cloudflare.ZoneAnalyticsOptions{} 543 | if Since != "" { 544 | t, err := time.Parse(time.RFC3339, Since) 545 | if err != nil { 546 | log.Fatalf("Invalid timestamp passed to Since: %s", err) 547 | } 548 | z.Since = &t 549 | } 550 | if Until != "" { 551 | t, err := time.Parse(time.RFC3339, Until) 552 | if err != nil { 553 | log.Fatalf("Invalid timestamp passed to Until: %s", err) 554 | } 555 | z.Until = &t 556 | } 557 | z.Continuous = &Continuous 558 | resp, err = api.ZoneAnalyticsDashboard(ZoneId, z) 559 | return 560 | } 561 | 562 | func ZoneAnalyticsDashboard(api *cloudflare.API, ZoneId string, Since string, Until string, Continuous bool) (resp interface{}, err error) { 563 | z := cloudflare.ZoneAnalyticsOptions{} 564 | if Since != "" { 565 | t, err := time.Parse(time.RFC3339, Since) 566 | if err != nil { 567 | log.Fatalf("Invalid timestamp passed to Since: %s", err) 568 | } 569 | z.Since = &t 570 | } 571 | if Until != "" { 572 | t, err := time.Parse(time.RFC3339, Until) 573 | if err != nil { 574 | log.Fatalf("Invalid timestamp passed to Until: %s", err) 575 | } 576 | z.Until = &t 577 | } 578 | z.Continuous = &Continuous 579 | resp, err = api.ZoneAnalyticsDashboard(ZoneId, z) 580 | return 581 | } 582 | 583 | func UpdateUser(api *cloudflare.API, FirstName string, LastName string, Telephone string, Country string, Zipcode string) (resp interface{}, err error) { 584 | u := &cloudflare.User{} 585 | var setVar bool 586 | if FirstName != "" { 587 | u.FirstName = FirstName 588 | setVar = true 589 | } 590 | if LastName != "" { 591 | u.LastName = LastName 592 | setVar = true 593 | } 594 | if Telephone != "" { 595 | u.Telephone = Telephone 596 | setVar = true 597 | } 598 | if Country != "" { 599 | u.Country = Country 600 | setVar = true 601 | } 602 | if Zipcode != "" { 603 | u.Zipcode = Zipcode 604 | setVar = true 605 | } 606 | if setVar { 607 | resp, err = api.UpdateUser(u) 608 | } else { 609 | resp, err = api.UserDetails() 610 | } 611 | return 612 | } 613 | 614 | func CreateLoadBalancerPool(api *cloudflare.API, Name string, Origins string, Description string, Disabled bool, MinimumOrigins int, Monitor string, NotificationEmail string) (resp interface{}, err error) { 615 | var lbo []cloudflare.LoadBalancerOrigin 616 | err = json.Unmarshal([]byte(Origins), &lbo) 617 | if err != nil { 618 | return 619 | } 620 | l := cloudflare.LoadBalancerPool{ 621 | Name: Name, 622 | Origins: lbo, 623 | } 624 | if Description != "" { 625 | l.Description = Description 626 | } 627 | if Disabled { 628 | l.Enabled = false 629 | } 630 | if MinimumOrigins > 0 { 631 | l.MinimumOrigins = MinimumOrigins 632 | } 633 | if Monitor != "" { 634 | l.Monitor = Monitor 635 | } 636 | if NotificationEmail != "" { 637 | l.NotificationEmail = NotificationEmail 638 | } 639 | resp, err = api.CreateLoadBalancerPool(l) 640 | return 641 | } 642 | 643 | func ModifyLoadBalancerPool(api *cloudflare.API, PoolId string, Name string, Origins string, Description string, Disabled bool, MinimumOrigins int, Monitor string, NotificationEmail string) (resp interface{}, err error) { 644 | var lbo []cloudflare.LoadBalancerOrigin 645 | err = json.Unmarshal([]byte(Origins), &lbo) 646 | if err != nil { 647 | return 648 | } 649 | l := cloudflare.LoadBalancerPool{ 650 | ID: PoolId, 651 | Name: Name, 652 | Origins: lbo, 653 | } 654 | if Description != "" { 655 | l.Description = Description 656 | } 657 | if Disabled { 658 | l.Enabled = false 659 | } 660 | if MinimumOrigins > 0 { 661 | l.MinimumOrigins = MinimumOrigins 662 | } 663 | if Monitor != "" { 664 | l.Monitor = Monitor 665 | } 666 | if NotificationEmail != "" { 667 | l.NotificationEmail = NotificationEmail 668 | } 669 | resp, err = api.ModifyLoadBalancerPool(l) 670 | return 671 | } 672 | 673 | func UpdateZoneSettings(api *cloudflare.API, ZoneId string, ZoneSettings string) (resp interface{}, err error) { 674 | var zs []cloudflare.ZoneSetting 675 | err = json.Unmarshal([]byte(ZoneSettingsObject), &zs) 676 | if err != nil { 677 | return 678 | } 679 | resp, err = api.UpdateZoneSettings(ZoneId, zs) 680 | return 681 | } 682 | 683 | func UpdateZoneLockdown(api *cloudflare.API, ZoneId string, LockdownId string, Configuration string, Urls string, Paused bool, Description string) (resp interface{}, err error) { 684 | var c []cloudflare.ZoneLockdownConfig 685 | err = json.Unmarshal([]byte(Configuration), &c) 686 | if err != nil { 687 | return 688 | } 689 | urlList := strings.Split(Urls, ",") 690 | zl := cloudflare.ZoneLockdown{ 691 | URLs: urlList, 692 | Paused: Paused, 693 | Configurations: c, 694 | } 695 | if Description != "" { 696 | zl.Description = Description 697 | } 698 | resp, err = api.UpdateZoneLockdown(ZoneId, LockdownId, zl) 699 | return 700 | } 701 | 702 | func CreateZoneLockdown(api *cloudflare.API, ZoneId string, Configuration string, Urls string, Paused bool, Description string) (resp interface{}, err error) { 703 | var c []cloudflare.ZoneLockdownConfig 704 | err = json.Unmarshal([]byte(Configuration), &c) 705 | if err != nil { 706 | return 707 | } 708 | urlList := strings.Split(Urls, ",") 709 | zl := cloudflare.ZoneLockdown{ 710 | URLs: urlList, 711 | Paused: Paused, 712 | Configurations: c, 713 | } 714 | if Description != "" { 715 | zl.Description = Description 716 | } 717 | resp, err = api.CreateZoneLockdown(ZoneId, zl) 718 | return 719 | } 720 | 721 | func CreateVirtualDNS(api *cloudflare.API, Name string, OriginIps string, MinimumCacheTtl int, MaximumCacheTtl int, DeprecateAnyRequest bool) (resp interface{}, err error) { 722 | v := &cloudflare.VirtualDNS{} 723 | v.Name = Name 724 | v.OriginIPs = strings.Split(OriginIps, ",") 725 | if MinimumCacheTtl > 0 { 726 | v.MinimumCacheTTL = uint(MinimumCacheTtl) 727 | } 728 | if MaximumCacheTtl > 0 { 729 | v.MaximumCacheTTL = uint(MaximumCacheTtl) 730 | } 731 | v.DeprecateAnyRequests = DeprecateAnyRequest 732 | resp, err = api.CreateVirtualDNS(v) 733 | return 734 | } 735 | 736 | func UpdateVirtualDNS(api *cloudflare.API, VirtualDnsId string, OriginIps string, MinimumCacheTtl int, MaximumCacheTtl int, DeprecateAnyRequest bool) (resp interface{}, err error) { 737 | v := &cloudflare.VirtualDNS{} 738 | if Name != "" { 739 | v.Name = Name 740 | } 741 | if OriginIps != "" { 742 | v.OriginIPs = strings.Split(OriginIps, ",") 743 | } 744 | if MinimumCacheTtl > 0 { 745 | v.MinimumCacheTTL = uint(MinimumCacheTtl) 746 | } 747 | if MaximumCacheTtl > 0 { 748 | v.MaximumCacheTTL = uint(MaximumCacheTtl) 749 | } 750 | v.DeprecateAnyRequests = DeprecateAnyRequest 751 | err = api.UpdateVirtualDNS(VirtualDnsId, *v) 752 | return 753 | } 754 | 755 | func CreatePageRule(api *cloudflare.API, ZoneId string, Targets string, Actions string, Priority int, Status string) (resp interface{}, err error) { 756 | var ( 757 | prt []cloudflare.PageRuleTarget 758 | pra []cloudflare.PageRuleAction 759 | r = cloudflare.PageRule{} 760 | ) 761 | 762 | err = json.Unmarshal([]byte(Targets), &prt) 763 | if err != nil { 764 | return 765 | } 766 | err = json.Unmarshal([]byte(Actions), &pra) 767 | if err != nil { 768 | return 769 | } 770 | if Priority > 0 { 771 | r.Priority = Priority 772 | } 773 | r.Status = Status 774 | r.Actions = pra 775 | r.Targets = prt 776 | resp, err = api.CreatePageRule(ZoneId, r) 777 | return 778 | } 779 | 780 | func ChangePageRule(api *cloudflare.API, ZoneId string, PageruleId string, Targets string, Actions string, Priority int, Status string) (resp interface{}, err error) { 781 | var ( 782 | prt []cloudflare.PageRuleTarget 783 | pra []cloudflare.PageRuleAction 784 | r = cloudflare.PageRule{} 785 | ) 786 | 787 | err = json.Unmarshal([]byte(Targets), &prt) 788 | if err != nil { 789 | return 790 | } 791 | err = json.Unmarshal([]byte(Actions), &pra) 792 | if err != nil { 793 | return 794 | } 795 | if Priority > 0 { 796 | r.Priority = Priority 797 | } 798 | r.Status = Status 799 | r.Actions = pra 800 | r.Targets = prt 801 | err = api.ChangePageRule(ZoneId, PageruleId, r) 802 | return 803 | } 804 | 805 | func CreateOrganizationAccessRule(api *cloudflare.API, OrganizationId string, Mode string, Configuration string, Notes string) (resp interface{}, err error) { 806 | h := strings.Split(Hostnames, ",") 807 | c := cloudflare.OriginCACertificate{ 808 | Hostnames: h, 809 | RequestValidity: RequestValidity, 810 | RequestType: RequestType, 811 | CSR: Csr, 812 | } 813 | resp, err = api.CreateOriginCertificate(c) 814 | return 815 | } 816 | 817 | func CreateOriginCertificate(api *cloudflare.API, Hostnames string, RequestValidity int, RequestType string, Csr string) (resp interface{}, err error) { 818 | h := strings.Split(Hostnames, ",") 819 | c := cloudflare.OriginCACertificate{ 820 | Hostnames: h, 821 | RequestValidity: RequestValidity, 822 | RequestType: RequestType, 823 | CSR: Csr, 824 | } 825 | resp, err = api.CreateOriginCertificate(c) 826 | return 827 | } 828 | 829 | func CreateRateLimit(api *cloudflare.API, ZoneId string, Match string, Threshold int, Period int, Action string, Enabled bool, Description string, Bypass string) (resp interface{}, err error) { 830 | var ( 831 | rlkv []cloudflare.RateLimitKeyValue 832 | m cloudflare.RateLimitTrafficMatcher 833 | a cloudflare.RateLimitAction 834 | ) 835 | err = json.Unmarshal([]byte(Match), &m) 836 | if err != nil { 837 | return 838 | } 839 | err = json.Unmarshal([]byte(Action), &a) 840 | if err != nil { 841 | return 842 | } 843 | rl := cloudflare.RateLimit{ 844 | Disabled: Enabled, 845 | Period: Period, 846 | Threshold: Threshold, 847 | Match: m, 848 | Action: a, 849 | } 850 | if Bypass != "" { 851 | err = json.Unmarshal([]byte(Bypass), &rlkv) 852 | if err != nil { 853 | return 854 | } 855 | rl.Bypass = rlkv 856 | } 857 | if Description != "" { 858 | rl.Description = Description 859 | } 860 | resp, err = api.CreateRateLimit(ZoneId, rl) 861 | return 862 | } 863 | 864 | func UpdateRateLimit(api *cloudflare.API, ZoneId string, LimitId string, Match string, Threshold int, Period int, Action string, Enabled bool, Description string, Bypass string) (resp interface{}, err error) { 865 | var ( 866 | rlkv []cloudflare.RateLimitKeyValue 867 | m cloudflare.RateLimitTrafficMatcher 868 | a cloudflare.RateLimitAction 869 | ) 870 | err = json.Unmarshal([]byte(Match), &m) 871 | if err != nil { 872 | return 873 | } 874 | err = json.Unmarshal([]byte(Action), &a) 875 | if err != nil { 876 | return 877 | } 878 | rl := cloudflare.RateLimit{ 879 | ID: LimitId, 880 | Disabled: Enabled, 881 | Period: Period, 882 | Threshold: Threshold, 883 | Match: m, 884 | Action: a, 885 | } 886 | if Bypass != "" { 887 | err = json.Unmarshal([]byte(Bypass), &rlkv) 888 | if err != nil { 889 | return 890 | } 891 | rl.Bypass = rlkv 892 | } 893 | if Description != "" { 894 | rl.Description = Description 895 | } 896 | resp, err = api.CreateRateLimit(ZoneId, rl) 897 | return 898 | } 899 | 900 | func CreateUserAccessRule(api *cloudflare.API, Mode string, Configuration string, Notes string) (resp interface{}, err error) { 901 | var arc cloudflare.AccessRuleConfiguration 902 | err = json.Unmarshal([]byte(Configuration), &arc) 903 | if err != nil { 904 | return 905 | } 906 | ar := cloudflare.AccessRule{ 907 | Configuration: arc, 908 | Mode: Mode, 909 | } 910 | if Notes != "" { 911 | ar.Notes = Notes 912 | } 913 | resp, err = api.CreateUserAccessRule(ar) 914 | return 915 | } 916 | 917 | func UpdateUserAccessRule(api *cloudflare.API, AccessRuleId string, Mode string, Configuration string, Notes string) (resp interface{}, err error) { 918 | var arc cloudflare.AccessRuleConfiguration 919 | err = json.Unmarshal([]byte(Configuration), &arc) 920 | if err != nil { 921 | return 922 | } 923 | ar := cloudflare.AccessRule{ 924 | Configuration: arc, 925 | Mode: Mode, 926 | } 927 | if Notes != "" { 928 | ar.Notes = Notes 929 | } 930 | resp, err = api.UpdateUserAccessRule(AccessRuleId, ar) 931 | return 932 | } 933 | 934 | func UpdateZoneAccessRule(api *cloudflare.API, ZoneId string, AccessRuleId string, Mode string, Configuration string, Notes string) (resp interface{}, err error) { 935 | var arc cloudflare.AccessRuleConfiguration 936 | err = json.Unmarshal([]byte(Configuration), &arc) 937 | if err != nil { 938 | return 939 | } 940 | ar := cloudflare.AccessRule{ 941 | Configuration: arc, 942 | Mode: Mode, 943 | } 944 | if Notes != "" { 945 | ar.Notes = Notes 946 | } 947 | resp, err = api.UpdateZoneAccessRule(OrganizationId, AccessRuleId, ar) 948 | return 949 | } 950 | 951 | func UpdateOrganizationAccessRule(api *cloudflare.API, OrganizationId string, AccessRuleId string, Mode string, Configuration string, Notes string) (resp interface{}, err error) { 952 | var arc cloudflare.AccessRuleConfiguration 953 | err = json.Unmarshal([]byte(Configuration), &arc) 954 | if err != nil { 955 | return 956 | } 957 | ar := cloudflare.AccessRule{ 958 | Configuration: arc, 959 | Mode: Mode, 960 | } 961 | if Notes != "" { 962 | ar.Notes = Notes 963 | } 964 | resp, err = api.UpdateOrganizationAccessRule(OrganizationId, AccessRuleId, ar) 965 | return 966 | } 967 | 968 | func ListZoneAccessRules(api *cloudflare.API, ZoneId string, Notes string, Mode string, Page int) (resp interface{}, err error) { 969 | ar := cloudflare.AccessRule{} 970 | if Notes != "" { 971 | ar.Notes = Notes 972 | } 973 | if Mode != "" { 974 | ar.Mode = Mode 975 | } 976 | resp, err = api.ListOrganizationAccessRules(ZoneId, ar, Page) 977 | return 978 | } 979 | 980 | func CreateSSL(api *cloudflare.API, ZoneId string, Certificate string, PrivateKey string, BundleMethod string) (resp interface{}, err error) { 981 | z := cloudflare.ZoneCustomSSLOptions{ 982 | Certificate: Certificate, 983 | PrivateKey: PrivateKey, 984 | } 985 | if BundleMethod != "" { 986 | z.BundleMethod = BundleMethod 987 | } 988 | resp, err = api.CreateSSL(ZoneId, z) 989 | return 990 | } 991 | 992 | func UpdateSSL(api *cloudflare.API, ZoneId string, CertificateId string, Certificate string, PrivateKey string, BundleMethod string) (resp interface{}, err error) { 993 | z := cloudflare.ZoneCustomSSLOptions{ 994 | Certificate: Certificate, 995 | PrivateKey: PrivateKey, 996 | } 997 | if BundleMethod != "" { 998 | z.BundleMethod = BundleMethod 999 | } 1000 | resp, err = api.UpdateSSL(ZoneId, CertificateId, z) 1001 | return 1002 | } 1003 | 1004 | func Purge(api *cloudflare.API, ZoneId string, Files string, Tags string, Hosts string) (resp interface{}, err error) { 1005 | p := cloudflare.PurgeCacheRequest{} 1006 | if Files != "" { 1007 | p.Files = strings.Split(Files, ",") 1008 | } 1009 | if Hosts != "" { 1010 | p.Hosts = strings.Split(Hosts, ",") 1011 | } 1012 | if Tags != "" { 1013 | p.Tags = strings.Split(Tags, ",") 1014 | } 1015 | resp, err = api.PurgeCache(ZoneId, p) 1016 | return 1017 | } 1018 | 1019 | func CreateUserAgentRule(api *cloudflare.API, ZoneId string, Mode string, Configuration string, Description string, Paused bool) (resp interface{}, err error) { 1020 | var c cloudflare.UserAgentRuleConfig 1021 | u := cloudflare.UserAgentRule{ 1022 | Mode: Mode, 1023 | Paused: Paused, 1024 | } 1025 | err = json.Unmarshal([]byte(Configuration), &c) 1026 | if err != nil { 1027 | return 1028 | } 1029 | u.Configuration = c 1030 | if Description != "" { 1031 | u.Description = Description 1032 | } 1033 | resp, err = api.CreateUserAgentRule(ZoneId, u) 1034 | return 1035 | } 1036 | 1037 | func UpdateUserAgentRule(api *cloudflare.API, ZoneId string, UserAgentId string, Mode string, Configuration string, Description string, Paused bool) (resp interface{}, err error) { 1038 | var c cloudflare.UserAgentRuleConfig 1039 | u := cloudflare.UserAgentRule{ 1040 | Mode: Mode, 1041 | Paused: Paused, 1042 | } 1043 | err = json.Unmarshal([]byte(Configuration), &c) 1044 | if err != nil { 1045 | return 1046 | } 1047 | u.Configuration = c 1048 | if Description != "" { 1049 | u.Description = Description 1050 | } 1051 | resp, err = api.UpdateUserAgentRule(ZoneId, UserAgentId, u) 1052 | return 1053 | } 1054 | 1055 | func UpdateCustomHostnameSSL(api *cloudflare.API, ZoneId string, CustomHostnameId string, Method string, Type string) (resp interface{}, err error) { 1056 | h := cloudflare.CustomHostnameSSL{ 1057 | Method: Method, 1058 | Type: Type, 1059 | } 1060 | resp, err = api.UpdateCustomHostnameSSL(ZoneId, CustomHostnameId, h) 1061 | return 1062 | } 1063 | 1064 | func CustomHostnames(api *cloudflare.API, ZoneId string, Hostname string, Page int) (resp interface{}, err error) { 1065 | page := 1 1066 | if Page > 0 { 1067 | page = Page 1068 | } 1069 | filter := cloudflare.CustomHostname{} 1070 | if Hostname != "" { 1071 | filter.Hostname = Hostname 1072 | } 1073 | resp, _, err = api.CustomHostnames(ZoneId, page, filter) 1074 | return 1075 | } 1076 | 1077 | func ReprioritizeSSL(api *cloudflare.API, ZoneId string, PriorityList string) (resp interface{}, err error) { 1078 | 1079 | var p []cloudflare.ZoneCustomSSLPriority 1080 | err = json.Unmarshal([]byte(PriorityList), &p) 1081 | if err != nil { 1082 | return 1083 | } 1084 | resp, err = api.ReprioritizeSSL(ZoneId, p) 1085 | return 1086 | } 1087 | 1088 | func ModifyLoadBalancerMonitor(api *cloudflare.API, MonitorId string, ExpectedCodes string, Method string, Header string, Timeout int, Path string, Interval int, Retries int, ExpectedBody string, Type string, Description string) (resp interface{}, err error) { 1089 | l := cloudflare.LoadBalancerMonitor{ 1090 | ID: MonitorId, 1091 | ExpectedCodes: ExpectedCodes, 1092 | } 1093 | if Method != "" { 1094 | l.Method = Method 1095 | } 1096 | if Timeout > 0 { 1097 | l.Timeout = Timeout 1098 | } 1099 | if Header != "" { 1100 | h := make(map[string][]string) 1101 | err = json.Unmarshal([]byte(Header), &h) 1102 | if err != nil { 1103 | return nil, err 1104 | } 1105 | l.Header = h 1106 | } 1107 | if Path != "" { 1108 | l.Path = Path 1109 | } 1110 | if Interval > 0 { 1111 | l.Interval = Interval 1112 | } 1113 | if Retries > 0 { 1114 | l.Retries = Retries 1115 | } 1116 | if Type != "" { 1117 | l.Type = Type 1118 | } 1119 | if Description != "" { 1120 | l.Description = Description 1121 | } 1122 | resp, err = api.ModifyLoadBalancerMonitor(l) 1123 | return 1124 | } 1125 | 1126 | func ModifyLoadBalancer(api *cloudflare.API, ZoneId string, LoadbalancerId string, Name string, FallbackPool string, DefaultPools string, Proxied bool, Ttl int) (resp interface{}, err error) { 1127 | d := strings.Split(DefaultPools, ",") 1128 | l := cloudflare.LoadBalancer{ 1129 | ID: LoadbalancerId, 1130 | Name: Name, 1131 | FallbackPool: FallbackPool, 1132 | DefaultPools: d, 1133 | Proxied: Proxied, 1134 | } 1135 | if Ttl > 0 { 1136 | l.TTL = Ttl 1137 | } 1138 | resp, err = api.ModifyLoadBalancer(ZoneId, l) 1139 | return 1140 | } 1141 | 1142 | func CreateWorkerRoute(api *cloudflare.API, ZoneId string, Pattern string, Disabled bool) (resp interface{}, err error) { 1143 | resp, err = api.CreateWorkerRoute(ZoneId, cloudflare.WorkerRoute{ 1144 | Pattern: Pattern, 1145 | Enabled: !Disabled, 1146 | }) 1147 | return 1148 | } 1149 | 1150 | func UpdateWorkerRoute(api *cloudflare.API, ZoneId string, RouteId string, Pattern string, Disabled bool) (resp interface{}, err error) { 1151 | resp, err = api.UpdateWorkerRoute(ZoneId, RouteId, cloudflare.WorkerRoute{ 1152 | Pattern: Pattern, 1153 | Enabled: !Disabled, 1154 | }) 1155 | return 1156 | } 1157 | 1158 | func ListWorkerRoutes(api *cloudflare.API, ZoneId string) (resp interface{}, err error) { 1159 | resp, err = api.ListWorkerRoutes(ZoneId) 1160 | return 1161 | } 1162 | 1163 | func UploadWorker(api *cloudflare.API, ZoneId, Script, ScriptName string) (resp interface{}, err error) { 1164 | s := Script 1165 | if len(Script) != 0 { 1166 | if Script[0] == '@' { 1167 | scriptFile := Script[1:] 1168 | fileScript, err := ioutil.ReadFile(scriptFile) 1169 | if err != nil { 1170 | return resp, err 1171 | } 1172 | s = string(fileScript) 1173 | } else if Script == "-" { 1174 | fileScript, err := ioutil.ReadAll(os.Stdin) 1175 | if err != nil { 1176 | return resp, err 1177 | } 1178 | s = string(fileScript) 1179 | } 1180 | } 1181 | wrp := &cloudflare.WorkerRequestParams{ 1182 | ZoneID: ZoneId, 1183 | } 1184 | if ScriptName != "" { 1185 | wrp.ScriptName = ScriptName 1186 | } 1187 | resp, err = api.UploadWorker(wrp, s) 1188 | return 1189 | } 1190 | 1191 | func DeleteWorker(api *cloudflare.API, ZoneId string) (resp interface{}, err error) { 1192 | resp, err = api.DeleteWorker(&cloudflare.WorkerRequestParams{ 1193 | ZoneID: ZoneId, 1194 | }) 1195 | return 1196 | } 1197 | 1198 | func ListWorkerScripts(api *cloudflare.API, OrganizationId string) (resp interface{}, err error) { 1199 | resp, err = api.ListWorkerScripts() 1200 | return 1201 | } 1202 | 1203 | func DownloadWorker(api *cloudflare.API, ZoneId string) (resp interface{}, err error) { 1204 | resp, err = api.DownloadWorker(&cloudflare.WorkerRequestParams{ 1205 | ZoneID: ZoneId, 1206 | }) 1207 | return 1208 | } 1209 | 1210 | func DownloadOrganizationWorker(api *cloudflare.API, OrganizationId string, Name string) (resp interface{}, err error) { 1211 | resp, err = api.DownloadWorker(&cloudflare.WorkerRequestParams{ 1212 | ScriptName: Name, 1213 | }) 1214 | return 1215 | } 1216 | 1217 | func DeleteOrganizationWorker(api *cloudflare.API, OrganizationId string, Name string) (resp interface{}, err error) { 1218 | resp, err = api.DeleteWorker(&cloudflare.WorkerRequestParams{ 1219 | ScriptName: Name, 1220 | }) 1221 | return 1222 | } 1223 | 1224 | func GetOrganizationAuditLogs(api *cloudflare.API, OrganizationId string) (resp interface{}, err error) { 1225 | // api.GetOrganizationAuditLogs(OrganizationId) 1226 | // return 1227 | return 1228 | } 1229 | func GetUserAuditLogs(api *cloudflare.API, ActorIP string, ActorEmail string, ZoneName string, Since string, ID string, Direction string, Before string, Page int, PerPage int) (resp interface{}, err error) { 1230 | resp, err = api.GetUserAuditLogs(cloudflare.AuditLogFilter{ 1231 | ID: ID, 1232 | ActorIP: ActorIP, 1233 | ActorEmail: ActorEmail, 1234 | Direction: Direction, 1235 | ZoneName: ZoneName, 1236 | Since: Since, 1237 | Before: Before, 1238 | PerPage: PerPage, 1239 | Page: Page, 1240 | }) 1241 | return 1242 | } 1243 | 1244 | func ListWorkersKVNamespaces(api *cloudflare.API, OrganizationId string) (resp interface{}, err error) { 1245 | resp, err = api.ListWorkersKVNamespaces(context.TODO()) 1246 | return 1247 | } 1248 | 1249 | func DeleteWorkersKVNamespace(api *cloudflare.API, OrganizationId string, NamespaceId string) (resp interface{}, err error) { 1250 | resp, err = api.DeleteWorkersKVNamespace(context.TODO(), NamespaceId) 1251 | return 1252 | } 1253 | 1254 | func ListWorkersKVs(api *cloudflare.API, OrganizationId string, NamespaceId string) (resp interface{}, err error) { 1255 | resp, err = api.ListWorkersKVs(context.TODO(), NamespaceId) 1256 | return 1257 | } 1258 | 1259 | func ReadWorkersKV(api *cloudflare.API, OrganizationId string, NamespaceId string, Key string) (resp interface{}, err error) { 1260 | resp, err = api.ReadWorkersKV(context.TODO(), NamespaceId, Key) 1261 | return 1262 | } 1263 | 1264 | func DeleteWorkersKV(api *cloudflare.API, OrganizationId string, NamespaceId string, Key string) (resp interface{}, err error) { 1265 | resp, err = api.DeleteWorkersKV(context.TODO(), NamespaceId, Key) 1266 | return 1267 | } 1268 | 1269 | func UpdateWorkersKVNamespace(api *cloudflare.API, OrganizationId string, NamespaceId string, Name string) (resp interface{}, err error) { 1270 | resp, err = api.UpdateWorkersKVNamespace(context.TODO(), NamespaceId, &cloudflare.WorkersKVNamespaceRequest{Title: Name}) 1271 | return 1272 | } 1273 | 1274 | func CreateWorkersKVNamespace(api *cloudflare.API, OrganizationId string, Name string) (resp interface{}, err error) { 1275 | resp, err = api.CreateWorkersKVNamespace(context.TODO(), &cloudflare.WorkersKVNamespaceRequest{Title: Name}) 1276 | return 1277 | } 1278 | 1279 | func WriteWorkersKV(api *cloudflare.API, OrganizationId string, NamespaceId string, Key string, Value string) (resp interface{}, err error) { 1280 | v := Value 1281 | if len(Value) != 0 { 1282 | if Value[0] == '@' { 1283 | valueFile := Value[1:] 1284 | fileValue, err := ioutil.ReadFile(valueFile) 1285 | if err != nil { 1286 | return resp, err 1287 | } 1288 | v = string(fileValue) 1289 | } else if Value == "-" { 1290 | fileValue, err := ioutil.ReadAll(os.Stdin) 1291 | if err != nil { 1292 | return resp, err 1293 | } 1294 | v = string(fileValue) 1295 | } 1296 | } 1297 | resp, err = api.WriteWorkersKV(context.TODO(), NamespaceId, Key, []byte(v)) 1298 | return 1299 | } 1300 | 1301 | func UploadOrganizationWorker(api *cloudflare.API, ZoneId string, OrganizationId, Name string, Script string) (resp interface{}, err error) { 1302 | s := Script 1303 | if len(Script) != 0 { 1304 | if Script[0] == '@' { 1305 | scriptFile := Script[1:] 1306 | fileScript, err := ioutil.ReadFile(scriptFile) 1307 | if err != nil { 1308 | return resp, err 1309 | } 1310 | s = string(fileScript) 1311 | } else if Script == "-" { 1312 | fileScript, err := ioutil.ReadAll(os.Stdin) 1313 | if err != nil { 1314 | return resp, err 1315 | } 1316 | s = string(fileScript) 1317 | } 1318 | } 1319 | resp, err = api.UploadWorker(&cloudflare.WorkerRequestParams{ 1320 | ScriptName: Name, 1321 | }, s) 1322 | return 1323 | } 1324 | -------------------------------------------------------------------------------- /cmd/autogenerate/autogenerate.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "os/exec" 6 | 7 | "github.com/ejcx/cf/definitions" 8 | ) 9 | 10 | func main() { 11 | err := definitions.GenerateFile("definitions/definitions.toml", "cmd/autogenerated.go") 12 | if err != nil { 13 | log.Fatalf("Could not generate file: %s", err) 14 | } 15 | err = exec.Command("goimports", "-w", "cmd/autogenerated.go").Run() 16 | if err != nil { 17 | log.Fatalf("Could not run goimports on autogenerated file: %s", err) 18 | } 19 | err = exec.Command("go", "fmt", "cmd/autogenerated.go").Run() 20 | if err != nil { 21 | log.Fatalf("Could not run go fmt on autogenerated file: %s", err) 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /cmd/configure.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io/ioutil" 7 | "log" 8 | "os" 9 | 10 | "github.com/99designs/keyring" 11 | cloudflare "github.com/cloudflare/cloudflare-go" 12 | cflib "github.com/ejcx/cf/lib" 13 | "github.com/segmentio/aws-okta/lib" 14 | "github.com/spf13/cobra" 15 | ) 16 | 17 | var ( 18 | ConfigureCmd = &cobra.Command{ 19 | Use: "configure", 20 | Short: "A command for configuring your cloudflare api credentials", 21 | Run: func(cmd *cobra.Command, args []string) { 22 | err := Configure(cmd, args) 23 | if err != nil { 24 | log.Fatalf("Could not configure cf cli: %s", err) 25 | } 26 | }, 27 | } 28 | noKeychain bool 29 | ) 30 | 31 | func init() { 32 | ConfigureCmd.Flags().BoolVar(&noKeychain, "no-keychain", false, "Do not attempt to store cloudflare api credentials in the keychain. Just use plaintext file.") 33 | RootCmd.AddCommand(ConfigureCmd) 34 | } 35 | 36 | func Configure(cmd *cobra.Command, args []string) error { 37 | email, err := lib.Prompt("Cloudflare Email", false) 38 | if err != nil { 39 | return err 40 | } 41 | 42 | apiKey, err := lib.Prompt("Cloudflare APIKey", true) 43 | if err != nil { 44 | return err 45 | } 46 | 47 | // Add a newline at the beginning and end because sensitive 48 | // prompts all end up on one line. 49 | serviceKey, err := lib.Prompt("\nOrigin CA APIKey", true) 50 | if err != nil { 51 | return err 52 | } 53 | fmt.Println("") 54 | 55 | // Now that we have the credentials, validate that the apikey and the email 56 | // are real by calling the User Details API. 57 | creds := &cflib.Credentials{ 58 | Email: email, 59 | Key: apiKey, 60 | UserServiceKey: serviceKey, 61 | } 62 | creds.SetEnv() 63 | 64 | api, err := cloudflare.New(os.Getenv("CF_API_KEY"), os.Getenv("CF_API_EMAIL")) 65 | if err != nil { 66 | return fmt.Errorf("Could not initialize api object: %s", err) 67 | } 68 | 69 | _, err = api.UserDetails() 70 | if err != nil { 71 | return fmt.Errorf("Invalid user credentials: %s", err) 72 | } 73 | 74 | if !noKeychain { 75 | // Now marshal the data to store in the keychain and set a cloudflare creds 76 | // file that has keychain set to true and nothing else 77 | encoded, err := json.Marshal(creds) 78 | if err != nil { 79 | return err 80 | } 81 | kr, err := cflib.GetKeyring() 82 | if err != nil { 83 | return err 84 | } 85 | err = kr.Set(keyring.Item{ 86 | Key: "cloudflare-creds", 87 | Data: encoded, 88 | Label: "cloudflare credentials", 89 | KeychainNotTrustApplication: false, 90 | }) 91 | if err != nil { 92 | return err 93 | } 94 | creds = &cflib.Credentials{ 95 | Keychain: true, 96 | } 97 | } 98 | 99 | // Write a creds file. It can either be a dumby creds file that only 100 | // says to look in the keychain, or the real keychain file. 101 | buf, err := json.Marshal(creds) 102 | if err != nil { 103 | return err 104 | } 105 | home, err := cflib.GetHomeDir() 106 | if err != nil { 107 | return err 108 | } 109 | // Ignore the error. If it worked or didn't, both cases are already handled. 110 | os.Mkdir(home+"/.cf", 0755) 111 | outfile := home + "/.cf/credentials" 112 | err = ioutil.WriteFile(outfile, buf, 0600) 113 | 114 | return err 115 | } 116 | -------------------------------------------------------------------------------- /cmd/root.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "log" 7 | "os" 8 | 9 | cloudflare "github.com/cloudflare/cloudflare-go" 10 | "github.com/ejcx/cf/lib" 11 | "github.com/spf13/cobra" 12 | ) 13 | 14 | var cfgFile string 15 | 16 | type Credentials struct { 17 | Email string 18 | } 19 | 20 | var RootCmd = &cobra.Command{ 21 | Use: "cf", 22 | Short: "A CLI for interacting with Cloudflare's V4 API", 23 | } 24 | 25 | func Execute() { 26 | if err := RootCmd.Execute(); err != nil { 27 | log.Fatal(err) 28 | } 29 | } 30 | 31 | // Main is where the high level program execution takes place. 32 | // The first thing that happens is the credentials are attempted 33 | // to be loaded from a file or your environment. If the creds are 34 | // loaded from a file then they are set as env vars to be used 35 | // by cloudflare-go. 36 | // Next, `root` is called, which is where API calls are made to 37 | // the cloudflare v4 API by using the `cloudflare-go` library. 38 | // Finally, the results are outputted to stdout (or stderr if 39 | // something disasterous happens). 40 | func Main(cmd *cobra.Command, args []string, name string) { 41 | err := lib.DefaultCredentialProvider.ConfigureEnvironment() 42 | if err != nil { 43 | log.Fatalf("No set of credentials to use: %s", err) 44 | } 45 | 46 | var ( 47 | opts []cloudflare.Option 48 | ) 49 | if OrganizationId != "" { 50 | opts = append(opts, cloudflare.UsingOrganization(OrganizationId)) 51 | } 52 | api, err := cloudflare.New(os.Getenv("CF_API_KEY"), os.Getenv("CF_API_EMAIL"), opts...) 53 | if err != nil { 54 | log.Fatalf("Could not initialize api object: %s", err) 55 | } 56 | if serviceKey, ok := os.LookupEnv("CF_USER_SERVICE_KEY"); ok { 57 | api.APIUserServiceKey = serviceKey 58 | } 59 | 60 | r, err := Run(cmd, args, name, api) 61 | if err != nil { 62 | log.Fatalf("Could not make cloudflare request: %s", err) 63 | } 64 | buf, err := json.MarshalIndent(r, " ", " ") 65 | if err != nil { 66 | log.Fatalf("Could not make print resp: %s", err) 67 | } 68 | if string(buf) != "null" { 69 | fmt.Println(string(buf)) 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /definitions/README.md: -------------------------------------------------------------------------------- 1 | # definitions 2 | Definitions is the guts and description of all commands and subcommands 3 | that are used in `cf`. 4 | 5 | ## Program Design 6 | ### Auto-generated Code 7 | It is important to understand the relationship between the `definitions.toml` 8 | file that resides in the `definitions` directory, and the `autogenerated.go` 9 | file that resides in the `cmd` directory. 10 | 11 | **definitions.toml** -- Contains a hand-written definition of each command-line command, their arguments, and their sub-commands. 12 | 13 | **autogenerated.go** -- Contains golang code that does two things. First, it creates all Variables passed to the program using the command-line. Second, it generates the command and subcommand structure of the CLI. 14 | 15 | **definitions.go** - Generates the go code using a series of templates. It is not pretty at all, but it converts the toml to definitions of [cobra](https://github.com/spf13/cobra), which provides a robust framework for CLI tools. 16 | 17 | ### Where are the API calls made? 18 | `cmd/root.go` has a large switch-statement where all API calls to `cloudflare-go` are made. 19 | When necessary, this switch statement does any massaging necessary to 20 | make the arguments from the command line fit in to the expected method signature. 21 | 22 | 23 | -------------------------------------------------------------------------------- /definitions/definitions.go: -------------------------------------------------------------------------------- 1 | package definitions 2 | 3 | // definitions is used to auto-generate the cmd/autogenerated.go file. 4 | // It makes heavy use of Golang templates and uses the definitions.tom 5 | // file in order to generate the golang code. 6 | 7 | import ( 8 | "bytes" 9 | "fmt" 10 | "io/ioutil" 11 | "strings" 12 | "text/template" 13 | 14 | "github.com/BurntSushi/toml" 15 | ) 16 | 17 | const ( 18 | // goTemplate is a high level template for the autogenerated.go file 19 | goTemplate = ` 20 | package cmd 21 | 22 | var ( 23 | {{ .Variables }} 24 | ) 25 | 26 | func init() { 27 | {{ .Commands }} 28 | } 29 | 30 | func Run(cmd *cobra.Command, args []string, name string, api *cloudflare.API) (resp interface{}, err error) { 31 | {{ .SwitchList }} 32 | return 33 | } 34 | ` 35 | 36 | switchTemplate = `switch name { 37 | {{ range . }} 38 | case "{{.Name}}": 39 | resp, err = {{.Name}}(api, {{.ArgList}}){{ end }} 40 | default: 41 | break 42 | }` 43 | // varTemplate is the template used by each subcommand to declare 44 | // their command line flags as Golang code. 45 | varTemplate = `{{ range .}}{{ .Name }} {{ .Type }} 46 | {{ end }}` 47 | 48 | // cmdTemplate is very hairy, and used to declare 49 | // top-level cli commands and their subcommands. 50 | // Top level commands are added to the root command 51 | // while subcommands will call the `Main` function 52 | // and pass their subcommand name, which is used 53 | // to route to the proper case within the switch. 54 | cmdTemplate = `var {{.VariableName}} = &cobra.Command{ 55 | Use: "{{- .Name -}}", 56 | Short: "{{- .ShortDescription -}}", 57 | Long: ` + "`" + `{{- .Description -}}` + "`" + `, 58 | {{ if .V4APIName}}Run: func(cmd *cobra.Command, args []string) { 59 | Main(cmd, args, "{{- .V4APIName}}") 60 | },{{ end}} 61 | } 62 | {{- $varName := .VariableName }} 63 | {{range .Subcommands}}{{$varName}}.AddCommand({{.}}) 64 | {{end}} 65 | {{ if .TopLevel }}RootCmd.AddCommand({{.VariableName}}) 66 | {{ end }} 67 | {{range .Option}} 68 | {{$varName}}.Flags().{{.TypeCap}}Var(&{{.ArgName}}, "{{.Name}}", {{.Default}}, "{{.Description}}") 69 | {{if .Required}}{{$varName}}.MarkFlagRequired("{{.Name}}") 70 | {{end}} 71 | {{end}} 72 | ` 73 | ) 74 | 75 | var ( 76 | // declaredVariables keeps track of which variables have already 77 | // been declared in our Go file. It will cause a compile time 78 | // issue if the same variable is declared twice. 79 | declaredVariables = make(map[string]bool) 80 | ) 81 | 82 | // Option is a command line option that can be passed to 83 | // the program. Commands "have a" set of Options. 84 | type Option struct { 85 | Name string 86 | Type string 87 | Description string 88 | Required bool 89 | } 90 | 91 | type OptionTemplateValue struct { 92 | TypeCap string 93 | ArgName string 94 | Name string 95 | Default string 96 | Description string 97 | Required bool 98 | } 99 | 100 | type SwitchTemplateEntry struct { 101 | Name string 102 | ArgList string 103 | } 104 | 105 | // Command is a toplevel or subcommand. 106 | // They have a set of subcommands if they are toplevel 107 | // and V4APIName will be set to the name of the Switch 108 | // case that is associated with the subcommand name. 109 | // For Example: list-zones will have a switch case named 110 | // ListZones, and ListZones should call the cloudflare-go 111 | // method api.ListZones. 112 | type Command struct { 113 | Name string 114 | Description string 115 | ShortDescription string 116 | V4APIName string 117 | Option []Option 118 | Subcommands []string 119 | TopLevel bool 120 | } 121 | 122 | type CommandTemplateValues struct { 123 | Name string 124 | VariableName string 125 | V4APIName string 126 | Description string 127 | ShortDescription string 128 | Option []OptionTemplateValue 129 | 130 | Subcommands []string 131 | TopLevel bool 132 | } 133 | 134 | type FileTemplateValues struct { 135 | Commands string 136 | Variables string 137 | SwitchList string 138 | } 139 | 140 | func fileText(commands, variables, switchList string) (string, error) { 141 | var ( 142 | buff bytes.Buffer 143 | ) 144 | tmpl, err := template.New("gofile").Parse(goTemplate) 145 | if err != nil { 146 | return "", err 147 | } 148 | err = tmpl.Execute(&buff, &FileTemplateValues{ 149 | Commands: commands, 150 | Variables: variables, 151 | SwitchList: switchList, 152 | }) 153 | if err != nil { 154 | return "", err 155 | } 156 | return buff.String(), nil 157 | } 158 | 159 | func (o Option) ToOptionTemplateValue() OptionTemplateValue { 160 | // When declaring an int, bool, or string is golang it is 161 | // important to ensure that the data type default value 162 | // is initialized properly. An integer literal should not 163 | // be wrapped in quotes for example. 164 | defaultType := "\"\"" 165 | if o.Type == "int" { 166 | defaultType = "0" 167 | } else if o.Type == "bool" { 168 | defaultType = "false" 169 | } 170 | return OptionTemplateValue{ 171 | TypeCap: hyphenDelimToCamel(o.Type), 172 | ArgName: hyphenDelimToCamel(o.Name), 173 | Name: o.Name, 174 | Default: defaultType, 175 | Description: o.Description, 176 | Required: o.Required, 177 | } 178 | } 179 | 180 | func ToSwitch(cmds []*Command) (string, error) { 181 | var ( 182 | switchList []SwitchTemplateEntry 183 | buff bytes.Buffer 184 | ) 185 | for _, cmd := range cmds { 186 | if cmd.V4APIName == "" { 187 | continue 188 | } 189 | argList := cmd.ToArgList() 190 | switchList = append(switchList, SwitchTemplateEntry{ 191 | Name: cmd.V4APIName, 192 | ArgList: argList, 193 | }) 194 | } 195 | tmpl, err := template.New("switch").Parse(switchTemplate) 196 | if err != nil { 197 | return "", err 198 | } 199 | err = tmpl.Execute(&buff, switchList) 200 | if err != nil { 201 | return "", err 202 | } 203 | return buff.String(), nil 204 | } 205 | 206 | func (c *Command) ToVariables() (string, error) { 207 | var ( 208 | buff bytes.Buffer 209 | options []Option 210 | ) 211 | 212 | // We need to do a pass to convert the variable names from cmd flags 213 | // to Go variable names. 214 | for _, opt := range c.Option { 215 | if _, ok := declaredVariables[opt.Name]; ok { 216 | continue 217 | } 218 | options = append(options, Option{ 219 | Name: hyphenDelimToCamel(opt.Name), 220 | Type: opt.Type, 221 | }) 222 | declaredVariables[opt.Name] = true 223 | } 224 | 225 | tmpl, err := template.New("option").Parse(varTemplate) 226 | if err != nil { 227 | return "", err 228 | } 229 | err = tmpl.Execute(&buff, options) 230 | if err != nil { 231 | return "", err 232 | } 233 | return buff.String(), nil 234 | } 235 | func (c *Command) ToGo() (string, error) { 236 | var ( 237 | buff bytes.Buffer 238 | subcommandVarNames []string 239 | ) 240 | for _, subcmd := range c.Subcommands { 241 | subcommandVarNames = append(subcommandVarNames, hyphenDelimToCamel(subcmd)) 242 | } 243 | 244 | // Convert the options to OptionTemplateValues 245 | var optionTemplateValueList []OptionTemplateValue 246 | for _, opt := range c.Option { 247 | optionTemplateValueList = append(optionTemplateValueList, opt.ToOptionTemplateValue()) 248 | } 249 | 250 | tmpl, err := template.New("command").Parse(cmdTemplate) 251 | if err != nil { 252 | return "", err 253 | } 254 | err = tmpl.Execute(&buff, &CommandTemplateValues{ 255 | Name: c.Name, 256 | TopLevel: c.TopLevel, 257 | Subcommands: subcommandVarNames, 258 | VariableName: hyphenDelimToCamel(c.Name), 259 | V4APIName: c.V4APIName, 260 | ShortDescription: c.ShortDescription, 261 | Description: c.Description, 262 | Option: optionTemplateValueList, 263 | }) 264 | if err != nil { 265 | return "", err 266 | } 267 | return buff.String(), nil 268 | } 269 | 270 | func LoadDefinitions(fname string) ([]*Command, error) { 271 | c := map[string][]*Command{} 272 | _, err := toml.DecodeFile(fname, &c) 273 | if err != nil { 274 | return nil, err 275 | } 276 | return c["command"], nil 277 | } 278 | 279 | // hyphenDelimToCamel will convert names like 280 | // list-zones to ListZones, where the hyphen 281 | // is removed and the first letter of each word 282 | // is properly camel cased. Be aware that abbrvs 283 | // like 'ttl' will be transformmed to 'Ttl'. 284 | func hyphenDelimToCamel(s string) string { 285 | parts := strings.Split(s, "-") 286 | 287 | // Capitalize the first letter of each part and return the 288 | // concatenation of them. 289 | for i, part := range parts { 290 | parts[i] = strings.ToUpper(string(part[0])) + part[1:] 291 | } 292 | return strings.Join(parts, "") 293 | } 294 | 295 | func GenerateFile(fname string, outfile string) error { 296 | cmds, err := LoadDefinitions(fname) 297 | if err != nil { 298 | return err 299 | } 300 | commandsGo := "" 301 | variablesGo := "" 302 | // Do two passes. First we want to generate all code that is 303 | // not a top level command. Next we want to generate all top 304 | // level commands. This is because of the variable ordering 305 | // and avoiding undefined variable issues. 306 | for _, cmd := range cmds { 307 | if !cmd.TopLevel { 308 | s, err := cmd.ToGo() 309 | if err != nil { 310 | return err 311 | } 312 | commandsGo += s 313 | } 314 | } 315 | 316 | // While we do this second pass, create all the variables while 317 | // we are also creating all of the commands. 318 | for _, cmd := range cmds { 319 | v, err := cmd.ToVariables() 320 | if err != nil { 321 | return err 322 | } 323 | variablesGo += v 324 | if cmd.TopLevel { 325 | s, err := cmd.ToGo() 326 | if err != nil { 327 | return err 328 | } 329 | commandsGo += s 330 | } 331 | } 332 | 333 | switchList, err := ToSwitch(cmds) 334 | if err != nil { 335 | return err 336 | } 337 | 338 | t, err := fileText(commandsGo, variablesGo, switchList) 339 | if err != nil { 340 | return err 341 | } 342 | err = ioutil.WriteFile(outfile, []byte(t), 0644) 343 | if err != nil { 344 | return err 345 | } 346 | return nil 347 | } 348 | 349 | func (c *Command) ToArgList() string { 350 | s := "" 351 | for _, opt := range c.Option { 352 | if s == "" { 353 | s = hyphenDelimToCamel(opt.Name) 354 | } else { 355 | s += ", " + hyphenDelimToCamel(opt.Name) 356 | } 357 | } 358 | return s 359 | } 360 | 361 | func (c *Command) ToArgListWithTypes() string { 362 | s := "" 363 | for _, opt := range c.Option { 364 | s += ", " + hyphenDelimToCamel(opt.Name) + " " + opt.Type 365 | } 366 | return s 367 | } 368 | 369 | func ToFuncSigs(cmds []*Command) string { 370 | s := "" 371 | for _, cmd := range cmds { 372 | if cmd.TopLevel { 373 | continue 374 | } 375 | s += fmt.Sprintf("func %s(api *cloudflare.API%s) (resp interface{}, err error) {\nreturn}\n", hyphenDelimToCamel(cmd.V4APIName), cmd.ToArgListWithTypes()) 376 | } 377 | return s 378 | } 379 | -------------------------------------------------------------------------------- /definitions/definitions.toml: -------------------------------------------------------------------------------- 1 | [[command]] 2 | name = "zone" 3 | description = """ 4 | A Zone is a domain name along with its subdomains and other identities. Using the zone command to interact with cloudflare zones""" 5 | subcommands = [ 6 | "activation-check", 7 | "analytics-by-colo", 8 | "analytics-dashboard", 9 | "create-custom-hostname", 10 | "create-zone", 11 | "delete-custom-hostname", 12 | "delete-zone", 13 | "delete-zone-access-rule", 14 | "describe-zone", 15 | "edit-zone-paused", 16 | "edit-zone-vanity-ns", 17 | "describe-custom-hostname", 18 | "describe-custom-hostname-by-name", 19 | "get-id-by-name", 20 | "get-zone-settings", 21 | "list-available-rate-plans", 22 | "list-custom-hostnames", 23 | "list-zone-access-rules", 24 | "list-zones", 25 | "set-paused", 26 | "set-vanity-ns", 27 | "update-custom-hostname", 28 | "update-zone-access-rule", 29 | "update-zone-settings", 30 | ] 31 | toplevel = true 32 | shortdescription = "Interact with cloudflare zones" 33 | 34 | [[command]] 35 | name = "worker" 36 | description = """ 37 | Manage your edge workers deployed to your account. 38 | """ 39 | subcommands = [ 40 | "create-worker-route", 41 | "create-kv-namespace", 42 | "delete-kv", 43 | "delete-kv-namespace", 44 | "delete-organization-worker", 45 | "delete-worker", 46 | "download-organization-worker", 47 | "download-worker", 48 | "get-kv", 49 | "list-kvs", 50 | "list-kv-namespaces", 51 | "list-worker-routes", 52 | "list-worker-scripts", 53 | "rename-kv-namespace", 54 | "update-worker-route", 55 | "upload-organization-worker", 56 | "upload-worker", 57 | "write-kv", 58 | ] 59 | toplevel = true 60 | shortdescription = "Interact with cloudflare workers api" 61 | 62 | 63 | [[command]] 64 | name = "dns" 65 | description = """ 66 | Create, read, update, and delete cloudflare dns and virtual dns.""" 67 | subcommands = [ 68 | "create-dns-record", 69 | "create-virtual-dns", 70 | "delete-dns-record", 71 | "delete-virtual-dns", 72 | "describe-virtual-dns", 73 | "edit-dns-record", 74 | "list-dns-records", 75 | "list-virtual-dns", 76 | "show-dns-record", 77 | "update-virtual-dns", 78 | ] 79 | toplevel = true 80 | shortdescription = "Create, read, update, and delete your dns records." 81 | 82 | [[command]] 83 | name = "user" 84 | description = """ 85 | The User subcommand will help you interact with your Cloudflare account.""" 86 | subcommands = [ 87 | "billing-profile", 88 | "create-user-access-rule", 89 | "delete-user-access-rule", 90 | "details", 91 | "edit-user", 92 | "get-user-audit-logs", 93 | "list-user-access-rules", 94 | "update-user-access-rule", 95 | ] 96 | toplevel = true 97 | shortdescription = "Interacting with your Cloudflare account" 98 | 99 | [[command]] 100 | name = "ssl" 101 | description = """ 102 | Fine grained control and deep insights in to your zone's SSL stack, as well as the ability to order new certs.""" 103 | subcommands = [ 104 | "create-origin-cert", 105 | "describe-origin-cert", 106 | "describe-zone-origin-cert", 107 | "delete-custom-cert", 108 | "list-custom-certs", 109 | "list-origin-certs", 110 | "list-zone-ssl-settings", 111 | "reprioritize-certs", 112 | "revoke-origin-cert", 113 | "update-custom-cert", 114 | "upload-custom-cert", 115 | ] 116 | toplevel = true 117 | shortdescription = "Control and insight in to your zone's SSL stack " 118 | 119 | 120 | [[command]] 121 | name = "pagerule" 122 | description = """ 123 | Gives you the ability to control how Cloudflare works on a URL or subdomain basis. Page Rules allow you to customize Cloudflare's functionality to match your domain's unique needs.""" 124 | subcommands = [ 125 | "create-pagerule", 126 | "list-pagerules", 127 | "delete-pagerule", 128 | "describe-pagerule", 129 | "update-pagerule", 130 | ] 131 | toplevel = true 132 | shortdescription = "Change how cloudflare works on a URL or subdomain basis." 133 | 134 | [[command]] 135 | name = "cache" 136 | description = """ 137 | Commands for the management and description of cache technologies.""" 138 | subcommands = [ 139 | "connect-zone-railgun", 140 | "create-railgun", 141 | "delete-railgun", 142 | "describe-railgun", 143 | "describe-zone-railgun", 144 | "disable-railgun", 145 | "disconnect-railgun", 146 | "enable-railgun", 147 | "get-railgun-zones", 148 | "list-railguns", 149 | "list-zone-railguns", 150 | "purge", 151 | "purge-everything", 152 | "test-railgun-connection", 153 | ] 154 | toplevel = true 155 | shortdescription = "Commands for interacting with caching and railgun APIs" 156 | 157 | [[command]] 158 | name = "firewall" 159 | description = """ 160 | The firewall subcommand is used to configure the WAF, user-agent rules, and zone-lockdowns.""" 161 | subcommands = [ 162 | "create-user-agent-rule", 163 | "create-zone-lockdown", 164 | "delete-user-agent-rule", 165 | "delete-zone-lockdown", 166 | "describe-zone-lockdown", 167 | "list-user-agent-rules", 168 | "list-waf-packages", 169 | "list-waf-rules", 170 | "list-zone-lockdowns", 171 | "update-user-agent-rule", 172 | "update-zone-lockdown", 173 | ] 174 | toplevel = true 175 | shortdescription = "Commands to interact with products that block access to your site" 176 | 177 | [[command]] 178 | name = "organization" 179 | description = """ 180 | Organizztions show all information about the organizations and provides the ability to modify access and display information about your specific organizations.""" 181 | subcommands = [ 182 | "create-organization-access-rule", 183 | "delete-organization-access-rule", 184 | "describe-organization", 185 | "get-organization-invites", 186 | "get-organization-members", 187 | "get-organization-roles", 188 | "list-organization-access-rules", 189 | "list-organizations", 190 | "update-organization-access-rule", 191 | "get-organization-audit-logs" 192 | ] 193 | toplevel = true 194 | shortdescription = "Interact with the organizations you own and have access to" 195 | 196 | [[command]] 197 | name = "ratelimit" 198 | description = """ 199 | Cloudflare ratelimits that ensure that the requests to your site are done at a rate you accept.""" 200 | subcommands = [ 201 | "create-ratelimit", 202 | "delete-ratelimit", 203 | "describe-ratelimit", 204 | "list-ratelimits", 205 | "update-ratelimit", 206 | ] 207 | toplevel = true 208 | shortdescription = "Configure, create, and view your zone's ratelimits." 209 | 210 | [[command]] 211 | name = "loadbalancer" 212 | description = """ 213 | The Cloudflare loadbalancer product is an enterprise ready load balancing platform.""" 214 | subcommands = [ 215 | "create-loadbalancer", 216 | "create-loadbalancer-pool", 217 | "create-loadbalancer-monitor", 218 | "delete-loadbalancer", 219 | "delete-loadbalancer-monitor", 220 | "delete-loadbalancer-pool", 221 | "describe-loadbalancer", 222 | "describe-loadbalancer-pool", 223 | "describe-loadbalancer-monitor", 224 | "list-loadbalancer-monitors", 225 | "list-loadbalancer-pools", 226 | "list-loadbalancers", 227 | "update-loadbalancer", 228 | "update-loadbalancer-monitor", 229 | "update-loadbalancer-pool", 230 | ] 231 | toplevel = true 232 | shortdescription = "Manage, create, and describe your loadbalancers, pools, and monitor" 233 | 234 | [[command]] 235 | name = "list-zones" 236 | description = """ 237 | This is a meaty description of the list-zones""" 238 | shortdescription = "Command for listing zones" 239 | v4apiname = "ListZones" 240 | [[command.option]] 241 | name = "zone-name-filter" 242 | type = "string" 243 | description = "string for filtering by name" 244 | required = false 245 | 246 | [[command]] 247 | name = "list-dns-records" 248 | description = """ 249 | List DNS Records associated with a given zone-id""" 250 | shortdescription = "Command for listing dns-records" 251 | v4apiname = "ListDnsRecords" 252 | 253 | [[command.option]] 254 | name = "zone-id" 255 | type = "string" 256 | description = "zone id used for filtering" 257 | required = true 258 | 259 | [[command.option]] 260 | name = "type" 261 | type = "string" 262 | description = "DNS Record type used for filter" 263 | required = false 264 | 265 | [[command.option]] 266 | name = "name" 267 | type = "string" 268 | description = "DNS Record name used for filter" 269 | required = false 270 | 271 | [[command.option]] 272 | name = "content" 273 | type = "string" 274 | description = "DNS Record content used for filter" 275 | required = false 276 | 277 | [[command]] 278 | name = "create-dns-record" 279 | description = """Create DNS record associated with a given zone.""" 280 | shortdescription = "Command DNS Record" 281 | v4apiname = "CreateDnsRecord" 282 | 283 | [[command.option]] 284 | name = "zone-id" 285 | type = "string" 286 | description = "The zone id associated with the new dns record" 287 | required = true 288 | 289 | [[command.option]] 290 | name = "type" 291 | type = "string" 292 | description = "valid values: A, AAAA, CNAME, TXT, SRV, LOC, MX, NS, SPF, CERT, DNSKEY, DS, NAPTR, SMIMEA, SSHFP, TLSA, URI read only" 293 | required = true 294 | 295 | [[command.option]] 296 | name = "name" 297 | type = "string" 298 | description = "DNS Record name (example: example.com), max length: 255" 299 | required = true 300 | 301 | [[command.option]] 302 | name = "content" 303 | type = "string" 304 | description = "DNS Record content used for filter" 305 | required = true 306 | 307 | [[command.option]] 308 | name = "ttl" 309 | type = "int" 310 | description = "Time to live for DNS record. Value of 1 is 'automatic', min value:120 max value:2147483647" 311 | required = false 312 | 313 | [[command.option]] 314 | name = "not-proxied" 315 | type = "bool" 316 | description = "Whether the record is receiving the performance and security benefits of Cloudflare" 317 | required = false 318 | 319 | [[command.option]] 320 | name = "priority" 321 | type = "int" 322 | description = "Used with some records like MX and SRV to determine priority. If you do not supply a priority for an MX record, a default value of 0 will be set. min value:0 max value:65535." 323 | required = false 324 | 325 | [[command]] 326 | name = "delete-dns-record" 327 | description = """Delete DNS record associated with a given zone.""" 328 | shortdescription = "Delete DNS Record" 329 | v4apiname = "DeleteDnsRecord" 330 | 331 | [[command.option]] 332 | name = "zone-id" 333 | type = "string" 334 | description = "The zone id associated with the record you wish to delete" 335 | required = true 336 | 337 | [[command.option]] 338 | name = "record-id" 339 | type = "string" 340 | description = "The record id associated with the dns record you wish to delete" 341 | required = true 342 | 343 | [[command]] 344 | name = "delete-zone" 345 | description = """Delete a zone associated with your account.""" 346 | shortdescription = "Delete zone" 347 | v4apiname = "DeleteZone" 348 | 349 | [[command.option]] 350 | name = "zone-id" 351 | type = "string" 352 | description = "The zone id that will be deleted" 353 | required = true 354 | 355 | [[command]] 356 | name = "create-zone" 357 | description = """Create a zone associated with your account.""" 358 | shortdescription = "Create zone" 359 | v4apiname = "CreateZone" 360 | 361 | [[command.option]] 362 | name = "name" 363 | type = "string" 364 | description = "The zone name that will be added to your account" 365 | required = true 366 | 367 | [[command.option]] 368 | name = "jumpstart" 369 | type = "bool" 370 | description = "Should the zone DNS be pre-populated" 371 | required = false 372 | 373 | [[command.option]] 374 | name = "organization-id" 375 | type = "string" 376 | description = "The organizationID associated with the zone" 377 | required = false 378 | 379 | [[command]] 380 | name = "show-dns-record" 381 | description = """Show a single DNS record associated with a zone ID and record ID.""" 382 | shortdescription = "Show DNS Record" 383 | v4apiname = "DNSRecord" 384 | 385 | [[command.option]] 386 | name = "zone-id" 387 | type = "string" 388 | description = "The zone ID associated with the DNS Record" 389 | required = true 390 | 391 | [[command.option]] 392 | name = "record-id" 393 | type = "string" 394 | description = "*Required:* The recordID associated with the DNS Record" 395 | required = true 396 | 397 | [[command]] 398 | name = "list-ratelimits" 399 | description = """Returns all Rate Limits for a zone""" 400 | shortdescription = "Show Ratelimits" 401 | v4apiname = "ListAllRateLimits" 402 | 403 | [[command.option]] 404 | name = "zone-id" 405 | type = "string" 406 | description = "The zone ID associated with the Ratelimits" 407 | required = true 408 | 409 | [[command]] 410 | name = "list-loadbalancers" 411 | description = """Returns all LoadBalancers for a zone""" 412 | shortdescription = "Show LoadBalancers" 413 | v4apiname = "ListLoadBalancers" 414 | [[command.option]] 415 | name = "zone-id" 416 | type = "string" 417 | description = "The zone ID associated with the Ratelimits" 418 | required = true 419 | 420 | [[command]] 421 | name = "list-organizations" 422 | description = """Returns all Organizations associated with your account""" 423 | shortdescription = "Show Organizations" 424 | v4apiname = "ListOrganizations" 425 | 426 | [[command]] 427 | name = "list-pagerules" 428 | description = """Returns all page rules associated with a given zone ID""" 429 | shortdescription = "Show Page Rules" 430 | v4apiname = "ListPageRules" 431 | [[command.option]] 432 | name = "zone-id" 433 | type = "string" 434 | description = "The zone ID associated with the pagerules" 435 | required = true 436 | 437 | [[command]] 438 | name = "list-custom-certs" 439 | description = """Returns all custom certs for a given zone ID""" 440 | shortdescription = "Show Custom Certs" 441 | v4apiname = "ListCustomCerts" 442 | [[command.option]] 443 | name = "zone-id" 444 | type = "string" 445 | description = "The zone ID associated with the custom certs" 446 | required = true 447 | 448 | [[command]] 449 | name = "list-user-agent-rules" 450 | description = """Returns all User-Agent rules for a specific zone ID""" 451 | shortdescription = "List User-Agent rules" 452 | v4apiname = "ListUserAgentRules" 453 | [[command.option]] 454 | name = "zone-id" 455 | type = "string" 456 | description = "The zone ID associated with the user-agent rule." 457 | required = true 458 | 459 | [[command.option]] 460 | name = "page" 461 | type = "int" 462 | description = "Pagination for user-agent rules" 463 | 464 | [[command]] 465 | name = "list-waf-packages" 466 | description = """Return the WAF Packages associated with a given zone.""" 467 | shortdescription = "List WAF Packages" 468 | v4apiname = "ListWAFPackages" 469 | [[command.option]] 470 | name = "zone-id" 471 | type = "string" 472 | description = "The zone ID associated with the WAF packages." 473 | required = true 474 | 475 | [[command]] 476 | name = "list-waf-rules" 477 | description = """Return the WAF Rules associated with a given zone.""" 478 | shortdescription = "List WAF Rules" 479 | v4apiname = "ListWAFRules" 480 | [[command.option]] 481 | name = "zone-id" 482 | type = "string" 483 | description = "The zone ID associated with the WAF configuration." 484 | required = true 485 | [[command.option]] 486 | name = "package-id" 487 | type = "string" 488 | description = "The package ID associated with the displayed WAF rules." 489 | required = true 490 | 491 | [[command]] 492 | name = "list-zone-lockdowns" 493 | description = """Return the lockdowns associated with a given zone.""" 494 | shortdescription = "List Zone Lockdowns" 495 | v4apiname = "ListZoneLockdowns" 496 | [[command.option]] 497 | name = "zone-id" 498 | type = "string" 499 | description = "The zone ID associated with the WAF configuration." 500 | required = true 501 | [[command.option]] 502 | name = "page" 503 | type = "int" 504 | description = "Pagination for zone lockdowns." 505 | 506 | [[command]] 507 | name = "describe-zone-lockdown" 508 | description = """Return the detailed information about a lockdown associated with a given zone.""" 509 | shortdescription = "Get detailed zone lockdown information" 510 | v4apiname = "ZoneLockdown" 511 | [[command.option]] 512 | name = "zone-id" 513 | type = "string" 514 | description = "The zone ID associated with the zone lockdown." 515 | required = true 516 | [[command.option]] 517 | name = "lockdown-id" 518 | type = "string" 519 | description = "The lockdown ID associated with the lockdown" 520 | required = true 521 | 522 | [[command]] 523 | name = "edit-zone-paused" 524 | description = """Edit a given zone's properties.""" 525 | shortdescription = "Edit a given zone" 526 | v4apiname = "EditZonePaused" 527 | [[command.option]] 528 | name = "zone-id" 529 | type = "string" 530 | description = "The zone ID associated with the zone being updated" 531 | required = true 532 | [[command.option]] 533 | name = "paused" 534 | type = "bool" 535 | description = "Set to pause the zone while editing the zone" 536 | 537 | [[command]] 538 | name = "edit-zone-vanity-ns" 539 | description = """Edit a given zone's properties.""" 540 | shortdescription = "Edit a given zone" 541 | v4apiname = "EditZoneVanityNS" 542 | [[command.option]] 543 | name = "zone-id" 544 | type = "string" 545 | description = "The zone ID associated with the zone being updated" 546 | required = true 547 | [[command.option]] 548 | name = "vanity-ns" 549 | type = "string" 550 | required = true 551 | description = "Comma delimited list of vanity nameservers" 552 | 553 | [[command]] 554 | name = "set-vanity-ns" 555 | description = """Set a given zone's vanity nameservers.""" 556 | shortdescription = "Set zone's vanity nameservers" 557 | v4apiname = "ZoneSetVanityNS" 558 | [[command.option]] 559 | name = "zone-id" 560 | type = "string" 561 | description = "The zone ID associated with the zone being updated" 562 | required = true 563 | [[command.option]] 564 | name = "vanity-ns" 565 | type = "string" 566 | required = true 567 | description = "Comma delimited list of vanity nameservers" 568 | 569 | [[command]] 570 | name = "edit-dns-record" 571 | description = """Edit an individual dns record's proxied status.""" 572 | shortdescription = "Edit proxy status for dns record" 573 | v4apiname = "EditDNSRecord" 574 | [[command.option]] 575 | name = "proxied" 576 | type = "bool" 577 | description = "Set this flag is you wish to proxy through Cloudflare, otherwise do not set" 578 | [[command.option]] 579 | name = "zone-id" 580 | type = "string" 581 | required = true 582 | description = "The zone ID associated with the dns record" 583 | [[command.option]] 584 | name = "record-id" 585 | type = "string" 586 | required = true 587 | description = "The record ID that indicates the dns record" 588 | [[command.option]] 589 | name = "type" 590 | type = "string" 591 | description = "valid values: A, AAAA, CNAME, TXT, SRV, LOC, MX, NS, SPF, CERT, DNSKEY, DS, NAPTR, SMIMEA, SSHFP, TLSA, URI read only" 592 | required = true 593 | [[command.option]] 594 | name = "name" 595 | type = "string" 596 | description = "DNS Record name (example: example.com), max length: 255" 597 | required = true 598 | [[command.option]] 599 | name = "content" 600 | type = "string" 601 | description = "DNS Record content used for filter" 602 | required = true 603 | [[command.option]] 604 | name = "ttl" 605 | type = "int" 606 | description = "Time to live for DNS record. Value of 1 is 'automatic', min value:120 max value:2147483647" 607 | required = false 608 | 609 | [[command]] 610 | name = "list-loadbalancer-monitors" 611 | description = """Returns all LoadBalancer Monitors. Not specific to a zone""" 612 | shortdescription = "Show LoadBalancer Monitors" 613 | v4apiname = "ListLoadBalancerMonitors" 614 | [[command]] 615 | name = "list-loadbalancer-pools" 616 | description = """Returns all LoadBalancer Pools. Not specific to a zone""" 617 | shortdescription = "Show LoadBalancer Pools" 618 | v4apiname = "ListLoadBalancerPools" 619 | 620 | [[command]] 621 | name = "list-organization-access-rules" 622 | description = """Returns all Organizations associated with your account""" 623 | shortdescription = "List Organization Access Rules" 624 | v4apiname = "ListOrganizationAccessRules" 625 | [[command.option]] 626 | name = "organization-id" 627 | type = "string" 628 | description = "The Organization ID" 629 | required = true 630 | [[command.option]] 631 | name = "notes" 632 | type = "string" 633 | description = "Matching any string within previously created access rules with the notes" 634 | required = false 635 | [[command.option]] 636 | name = "mode" 637 | type = "string" 638 | description = "valid values: block, challenge, whitelist, js_challenge" 639 | required = false 640 | [[command.option]] 641 | name = "page" 642 | type = "int" 643 | description = "Requested page within paginated list of results" 644 | required = false 645 | 646 | [[command]] 647 | name = "list-railguns" 648 | description = """Returns all Railguns associated with your account""" 649 | shortdescription = "List Railguns associated with the account" 650 | v4apiname = "ListRailguns" 651 | 652 | [[command]] 653 | name = "list-zone-railguns" 654 | description = """Returns all Railguns associated with a given zone""" 655 | shortdescription = "List all Railguns associated with a zone" 656 | v4apiname = "ListZoneRailguns" 657 | 658 | [[command]] 659 | name = "list-user-access-rules" 660 | description = """Returns all access rules associated with your account""" 661 | shortdescription = "List User Access Rules" 662 | v4apiname = "ListUserAccessRules" 663 | [[command.option]] 664 | name = "notes" 665 | type = "string" 666 | description = "Matching any string within previously created access rules with the notes" 667 | required = false 668 | [[command.option]] 669 | name = "mode" 670 | type = "string" 671 | description = "valid values: block, challenge, whitelist, js_challenge" 672 | required = false 673 | [[command.option]] 674 | name = "page" 675 | type = "int" 676 | description = "Requested page within paginated list of results" 677 | required = false 678 | 679 | [[command]] 680 | name = "list-virtual-dns" 681 | description = """Returns all Virtual DNS clusters associated with an account""" 682 | shortdescription = "List Virtual DNS clusters" 683 | v4apiname = "ListVirtualDns" 684 | 685 | [[command]] 686 | name = "list-available-rate-plans" 687 | description = """List all rate plans the zone can subscribe to.""" 688 | shortdescription = "List all available zone rate plans" 689 | v4apiname = "AvailableZoneRatePlans" 690 | [[command.option]] 691 | name = "zone-id" 692 | type = "string" 693 | description = "The zone ID associated with the rate plans" 694 | required = true 695 | 696 | [[command]] 697 | name = "connect-zone-railgun" 698 | description = """Connect or disconnect a Railgun""" 699 | shortdescription = "Connect or disconnect a Railgun" 700 | v4apiname = "ConnectZoneRailgun" 701 | [[command.option]] 702 | name = "zone-id" 703 | type = "string" 704 | description = "The zone ID to be associated with the railgun" 705 | required = true 706 | [[command.option]] 707 | name = "railgun-id" 708 | type = "string" 709 | description = "The railgun ID to be associated with the zone" 710 | required = true 711 | 712 | [[command]] 713 | name = "create-custom-hostname" 714 | description = """Add a new custom hostname and request that an SSL certificate be issued for it. One of three validation methods—http, cname, email—should be used, with 'http' recommended if the CNAME is already in place (or will be soon). Specifying 'email' will send an email to the WHOIS contacts on file for the base domain plus hostmaster, postmaster, webmaster, admin, administrator. Specifying 'cname' will return a CNAME that needs to be placed. If http is used and the domain is not already pointing to the Managed CNAME host, the PATCH method must be used once it is (to complete validation).""" 715 | shortdescription = "Create a custom hostname for an associated zone." 716 | v4apiname = "CreateCustomHostname" 717 | [[command.option]] 718 | name = "zone-id" 719 | type = "string" 720 | description = "The zone ID associated with the custom hostname" 721 | required = true 722 | [[command.option]] 723 | name = "hostname" 724 | type = "string" 725 | description = "The custom hostname that will point to your hostname via CNAME." 726 | required = true 727 | [[command.option]] 728 | name = "method" 729 | type = "string" 730 | description = "The SSL Verification method. valid values: http, email, cname." 731 | required = true 732 | [[command.option]] 733 | name = "type" 734 | type = "string" 735 | description = "The type of SSL certificate valid values: dv only" 736 | required = true 737 | 738 | [[command]] 739 | name = "create-loadbalancer-monitor" 740 | description = """Create a configured monitor""" 741 | shortdescription = "Create a configured monitor" 742 | v4apiname = "CreateLoadBalancerMonitor" 743 | [[command.option]] 744 | name = "expected-codes" 745 | type = "string" 746 | description = "The expected http response code in the healthcheck" 747 | required = true 748 | [[command.option]] 749 | name = "method" 750 | type = "string" 751 | description = "The HTTP method to use for the health check. default value: GET" 752 | required = false 753 | [[command.option]] 754 | name = "header" 755 | type = "string" 756 | description = "The HTTP request headers to send in the health check. It is recommended you set a Host header by default. The User-Agent header cannot be overridden. Example: {\\\"Host\\\": [\\\"example.com\\\"],\\\"X-App-ID\\\": [\\\"abc123\\\"]}" 757 | required = false 758 | [[command.option]] 759 | name = "timeout" 760 | type = "int" 761 | description = "The timeout (in seconds) before marking the health check as failed. default value: 5" 762 | required = true 763 | [[command.option]] 764 | name = "path" 765 | type = "string" 766 | description = "The endpoint path to health check against. default value: /" 767 | required = true 768 | [[command.option]] 769 | name = "interval" 770 | type = "int" 771 | description = "The interval between each health check. Shorter intervals may improve failover time, but will increase load. default value 60" 772 | required = true 773 | [[command.option]] 774 | name = "retries" 775 | type = "int" 776 | description = "The number of retries to attempt in case of a timeout before marking the origin as unhealthy. default value 2" 777 | required = true 778 | [[command.option]] 779 | name = "expected-body" 780 | type = "string" 781 | description = "A case-insensitive sub-string to look for in the response body. If this string is not found, the origin will be marked as unhealthy." 782 | required = false 783 | [[command.option]] 784 | name = "type" 785 | type = "string" 786 | description = "The protocol to use for the healthcheck. Currently supported protocols are 'HTTP' and 'HTTPS'. default value: http" 787 | required = true 788 | [[command.option]] 789 | name = "description" 790 | type = "string" 791 | description = "Object description" 792 | required = true 793 | 794 | [[command]] 795 | name = "create-loadbalancer" 796 | description = """Create a configured monitor""" 797 | shortdescription = "Create a configured monitor" 798 | v4apiname = "CreateLoadBalancer" 799 | [[command.option]] 800 | name = "zone-id" 801 | type = "string" 802 | description = "The zoneID associated with the loadbalancer" 803 | required = true 804 | [[command.option]] 805 | name = "name" 806 | type = "string" 807 | description = "The DNS hostname to associate with your Load Balancer. If this hostname already exists as a DNS record in Cloudflare's DNS, the Load Balancer will take precedence and the DNS record will not be used." 808 | required = true 809 | [[command.option]] 810 | name = "fallback-pool" 811 | type = "string" 812 | description = "The pool ID to use when all other pools are detected as unhealthy. max length: 32" 813 | required = true 814 | [[command.option]] 815 | name = "default-pools" 816 | type = "string" 817 | description = "A comma separated list of pool IDs ordered by their failover priority. Pools defined here are used by default, or when region_pools are not configured for a given region." 818 | required = true 819 | [[command.option]] 820 | name = "proxied" 821 | type = "bool" 822 | description = "Whether the hostname should be gray clouded (false) or orange clouded (true). default value: false" 823 | required = false 824 | [[command.option]] 825 | name = "ttl" 826 | type = "int" 827 | description = "Time to live (TTL) of the DNS entry for the IP address returned by this load balancer. This only applies to gray-clouded (unproxied) load balancers." 828 | required = false 829 | 830 | [[command]] 831 | name = "purge-everything" 832 | description = """Purge all items in this zones cache.""" 833 | shortdescription = "Purge Everything" 834 | v4apiname = "PurgeEverything" 835 | [[command.option]] 836 | name = "zone-id" 837 | type = "string" 838 | description = "The zoneID that will be purged." 839 | required = true 840 | 841 | [[command]] 842 | name = "activation-check" 843 | description = """Initiates another zone activation check for newly-created zones""" 844 | shortdescription = "Initiate another zone activation check" 845 | v4apiname = "ActivationCheck" 846 | [[command.option]] 847 | name = "zone-id" 848 | type = "string" 849 | description = "The zoneID associated with the activation check" 850 | required = true 851 | 852 | [[command]] 853 | name = "describe-zone" 854 | description = """Fetches information about a zone.""" 855 | shortdescription = "Fetches information about a zone." 856 | v4apiname = "ZoneDetails" 857 | [[command.option]] 858 | name = "zone-id" 859 | type = "string" 860 | description = "The zoneID that will be purged." 861 | required = true 862 | 863 | [[command]] 864 | name = "get-id-by-name" 865 | description = """Get the zone id by the zone name.""" 866 | shortdescription = "Get the zone id by name" 867 | v4apiname = "GetIDByName" 868 | [[command.option]] 869 | name = "zone-name" 870 | type = "string" 871 | description = "The zoneName that you want the ID of" 872 | required = true 873 | 874 | [[command]] 875 | name = "list-zone-ssl-settings" 876 | description = """Get the ssl settings associated with a zone.""" 877 | shortdescription = "Fetch zone ssl settings" 878 | v4apiname = "ZoneSSLSettings" 879 | [[command.option]] 880 | name = "zone-id" 881 | type = "string" 882 | description = "The zoneID you wish to fetch the SSL settings for" 883 | required = true 884 | 885 | [[command]] 886 | name = "get-zone-settings" 887 | description = """Get zone specific settings.""" 888 | shortdescription = "Get zone specific settings" 889 | v4apiname = "ZoneSettings" 890 | [[command.option]] 891 | name = "zone-id" 892 | type = "string" 893 | description = "The zoneID you wish to fetch the zone settings for" 894 | required = true 895 | 896 | [[command]] 897 | name = "details" 898 | description = """Get user specific settings.""" 899 | shortdescription = "Get user specific settings" 900 | v4apiname = "UserDetails" 901 | 902 | [[command]] 903 | name = "billing-profile" 904 | description = """Get the user billing profile.""" 905 | shortdescription = "Get the billing profile" 906 | v4apiname = "UserBillingProfile" 907 | 908 | [[command]] 909 | name = "describe-virtual-dns" 910 | description = """Get the details about a virtual dns instance.""" 911 | shortdescription = "Get virtual dns details" 912 | v4apiname = "VirtualDNS" 913 | [[command.option]] 914 | name = "virtual-dns-id" 915 | type = "string" 916 | description = "The virtualDNS ID you wish to fetch the details of." 917 | required = true 918 | 919 | [[command]] 920 | name = "delete-virtual-dns" 921 | description = """Delete a specific virtual dns instance.""" 922 | shortdescription = "Delete virtual dns instance" 923 | v4apiname = "DeleteVirtualDNS" 924 | [[command.option]] 925 | name = "virtual-dns-id" 926 | type = "string" 927 | description = "The virtualDNS ID you wish to delete." 928 | required = true 929 | 930 | [[command]] 931 | name = "describe-pagerule" 932 | description = """Get the details of a specific page rule""" 933 | shortdescription = "Get page rule details" 934 | v4apiname = "PageRule" 935 | [[command.option]] 936 | name = "zone-id" 937 | type = "string" 938 | description = "The zone ID associated with the page rule" 939 | required = true 940 | [[command.option]] 941 | name = "pagerule-id" 942 | type = "string" 943 | description = "The pagerule ID you wish to fetch the details of." 944 | required = true 945 | 946 | [[command]] 947 | name = "describe-loadbalancer" 948 | description = """Get loadbalancer details.""" 949 | shortdescription = "Get loadbalancer details" 950 | v4apiname = "LoadBalancerDetails" 951 | [[command.option]] 952 | name = "zone-id" 953 | type = "string" 954 | description = "The zone ID associated with the page rule" 955 | required = true 956 | [[command.option]] 957 | name = "loadbalancer-id" 958 | type = "string" 959 | description = "The loadbalancer id that you wish to view the details of." 960 | required = true 961 | 962 | [[command]] 963 | name = "describe-loadbalancer-monitor" 964 | description = """Get loadbalancer monitor details.""" 965 | shortdescription = "Get loadbalancer monitor details" 966 | v4apiname = "LoadBalancerMonitorDetails" 967 | [[command.option]] 968 | name = "monitor-id" 969 | type = "string" 970 | description = "The loadbalancer monitor id that you wish to view the details of." 971 | required = true 972 | 973 | [[command]] 974 | name = "describe-loadbalancer-pool" 975 | description = """Get loadbalancer pool details.""" 976 | shortdescription = "Get loadbalancer pool details" 977 | v4apiname = "LoadBalancerPoolDetails" 978 | [[command.option]] 979 | name = "pool-id" 980 | type = "string" 981 | description = "The loadbalancer pool id that you wish to view the details of." 982 | required = true 983 | 984 | [[command]] 985 | name = "describe-organization" 986 | description = """Get organization details.""" 987 | shortdescription = "Get organization details" 988 | v4apiname = "OrganizationDetails" 989 | [[command.option]] 990 | name = "organization-id" 991 | type = "string" 992 | description = "The organization id that you wish to view the details of." 993 | required = true 994 | 995 | [[command]] 996 | name = "get-organization-invites" 997 | description = """Get organization invites.""" 998 | shortdescription = "Get organization invites" 999 | v4apiname = "OrganizationInvites" 1000 | [[command.option]] 1001 | name = "organization-id" 1002 | type = "string" 1003 | description = "The organization id that you wish to view the invites for." 1004 | required = true 1005 | 1006 | [[command]] 1007 | name = "get-organization-members" 1008 | description = """Get organization members.""" 1009 | shortdescription = "Get organization members" 1010 | v4apiname = "OrganizationMembers" 1011 | [[command.option]] 1012 | name = "organization-id" 1013 | type = "string" 1014 | description = "The organization id that you wish to view the members of" 1015 | required = true 1016 | 1017 | [[command]] 1018 | name = "get-organization-roles" 1019 | description = """Get organization roles.""" 1020 | shortdescription = "Get organization roles" 1021 | v4apiname = "OrganizationRoles" 1022 | [[command.option]] 1023 | name = "organization-id" 1024 | type = "string" 1025 | description = "The organization id that you wish to view the member roles of" 1026 | required = true 1027 | 1028 | [[command]] 1029 | name = "list-origin-certs" 1030 | description = """List Origin Certificates associated with a given zone ID""" 1031 | shortdescription = "List origin certificates" 1032 | v4apiname = "OriginCertificates" 1033 | [[command.option]] 1034 | name = "zone-id" 1035 | type = "string" 1036 | description = "The zone id that you wish to view the origin certs of" 1037 | required = true 1038 | 1039 | [[command]] 1040 | name = "describe-origin-cert" 1041 | description = """Get detailed information about a specific origin certificate""" 1042 | shortdescription = "Get origin cert details" 1043 | v4apiname = "OriginCertificate" 1044 | [[command.option]] 1045 | name = "certificate-id" 1046 | type = "string" 1047 | description = "The origin certificate id that you wish to view detailed information about" 1048 | required = true 1049 | 1050 | [[command]] 1051 | name = "describe-zone-origin-cert" 1052 | description = """Get detailed information about a specific zone's origin certificate""" 1053 | shortdescription = "Get zone's origin cert details" 1054 | v4apiname = "SSLDetails" 1055 | [[command.option]] 1056 | name = "certificate-id" 1057 | type = "string" 1058 | description = "The zone's certificate id that you wish to view detailed information about" 1059 | required = true 1060 | [[command.option]] 1061 | name = "zone-id" 1062 | type = "string" 1063 | description = "The zone id that you wish to view detailed information about" 1064 | required = true 1065 | 1066 | [[command]] 1067 | name = "describe-railgun" 1068 | description = """Get detailed information about a specific railgun""" 1069 | shortdescription = "Get railgun instance details" 1070 | v4apiname = "RailgunDetails" 1071 | [[command.option]] 1072 | name = "railgun-id" 1073 | type = "string" 1074 | description = "The railgun id that you wish to view detailed information about" 1075 | required = true 1076 | 1077 | [[command]] 1078 | name = "get-railgun-zones" 1079 | description = """Get detailed information about a specific railgun's zones""" 1080 | shortdescription = "Get railgun instance zone details" 1081 | v4apiname = "RailgunZones" 1082 | [[command.option]] 1083 | name = "railgun-id" 1084 | type = "string" 1085 | description = "The railgun id that you wish to view associated zones" 1086 | required = true 1087 | 1088 | [[command]] 1089 | name = "describe-ratelimit" 1090 | description = """Get detailed information about a specific zone's ratelimits""" 1091 | shortdescription = "Get detailed information about a zone" 1092 | v4apiname = "RateLimit" 1093 | [[command.option]] 1094 | name = "zone-id" 1095 | type = "string" 1096 | description = "The zone id associated with the ratelimit" 1097 | required = true 1098 | [[command.option]] 1099 | name = "ratelimit-id" 1100 | type = "string" 1101 | description = "The ratelimit id that you wish to view detailed information about" 1102 | required = true 1103 | 1104 | [[command]] 1105 | name = "revoke-origin-cert" 1106 | description = """Revoke a specific origin certificate""" 1107 | shortdescription = "Revoke origin certificate" 1108 | v4apiname = "RevokeOriginCertificate" 1109 | [[command.option]] 1110 | name = "certificate-id" 1111 | type = "string" 1112 | description = "The certificate id that is being revoked" 1113 | required = true 1114 | 1115 | [[command]] 1116 | name = "test-railgun-connection" 1117 | description = """Returns all access rules associated with your account""" 1118 | shortdescription = "List User Access Rules" 1119 | v4apiname = "TestRailgunConnection" 1120 | [[command.option]] 1121 | name = "zone-id" 1122 | type = "string" 1123 | description = "The zone id associated with the railgun connection you wish to test" 1124 | required = true 1125 | [[command.option]] 1126 | name = "railgun-id" 1127 | type = "string" 1128 | description = "The railgun id associated with the railgun connection you wish to test" 1129 | required = true 1130 | 1131 | [[command]] 1132 | name = "describe-zone-railgun" 1133 | description = """Returns all railgun details for an associated zone""" 1134 | shortdescription = "Get zone railgun details" 1135 | v4apiname = "ZoneRailgunDetails" 1136 | [[command.option]] 1137 | name = "zone-id" 1138 | type = "string" 1139 | description = "The zone id associated with the railguns you wish to get" 1140 | required = true 1141 | [[command.option]] 1142 | name = "railgun-id" 1143 | type = "string" 1144 | description = "The railgun id associated with the railguns you wish to get" 1145 | required = true 1146 | 1147 | [[command]] 1148 | name = "describe-custom-hostname" 1149 | description = """Returns details associated with the custom hostname id""" 1150 | shortdescription = "Custom hostname details" 1151 | v4apiname = "CustomHostname" 1152 | [[command.option]] 1153 | name = "zone-id" 1154 | type = "string" 1155 | description = "The zone id associated with the custom hostname being returned" 1156 | required = true 1157 | [[command.option]] 1158 | name = "custom-hostname-id" 1159 | type = "string" 1160 | description = "The custom hostname id associated with the custom hostname you wish to describe" 1161 | required = true 1162 | 1163 | [[command]] 1164 | name = "describe-custom-hostname-by-name" 1165 | description = """Returns details associated with the custom hostname id""" 1166 | shortdescription = "Custom hostname details" 1167 | v4apiname = "CustomHostnameIDByName" 1168 | [[command.option]] 1169 | name = "zone-id" 1170 | type = "string" 1171 | description = "The zone id associated with the custom hostname id being returned" 1172 | required = true 1173 | [[command.option]] 1174 | name = "name" 1175 | type = "string" 1176 | description = "The custom hostname associated with the custom hostname id you wish to return" 1177 | required = true 1178 | 1179 | [[command]] 1180 | name = "set-paused" 1181 | description = """Set or unset a zone from being paused""" 1182 | shortdescription = "Pause or unpause a zone" 1183 | v4apiname = "ZoneSetPaused" 1184 | [[command.option]] 1185 | name = "zone-id" 1186 | type = "string" 1187 | description = "The zone id to either pause or unpause" 1188 | required = true 1189 | [[command.option]] 1190 | name = "paused" 1191 | type = "bool" 1192 | description = "This flag is unset for unpaused. Set for paused." 1193 | required = false 1194 | 1195 | [[command]] 1196 | name = "delete-pagerule" 1197 | description = """Delete a page rule associated with a specific zone and pagerule id""" 1198 | shortdescription = "Delete a specific page rule" 1199 | v4apiname = "DeletePageRule" 1200 | [[command.option]] 1201 | name = "zone-id" 1202 | type = "string" 1203 | description = "The zone ID associated with the page rule" 1204 | required = true 1205 | [[command.option]] 1206 | name = "pagerule-id" 1207 | type = "string" 1208 | description = "The pagerule ID associated with the pagerule you wish to delete" 1209 | required = true 1210 | 1211 | [[command]] 1212 | name = "delete-railgun" 1213 | description = """Delete a railgun associated with a specific railgun id""" 1214 | shortdescription = "Delete a specific railgun by its id" 1215 | v4apiname = "DeleteRailgun" 1216 | [[command.option]] 1217 | name = "railgun-id" 1218 | type = "string" 1219 | description = "The railgun ID associated with the railgun being deleted" 1220 | required = true 1221 | 1222 | [[command]] 1223 | name = "disable-railgun" 1224 | description = """Disable a railgun associated with a specific railgun id""" 1225 | shortdescription = "Delete a specific railgun by its id" 1226 | v4apiname = "DisableRailgun" 1227 | [[command.option]] 1228 | name = "railgun-id" 1229 | type = "string" 1230 | description = "The railgun ID associated with the railgun being disabled" 1231 | required = true 1232 | 1233 | [[command]] 1234 | name = "disconnect-railgun" 1235 | description = """Disconnect a railgun associated with a specific zone""" 1236 | shortdescription = "Disconnect a railgun from a zone" 1237 | v4apiname = "DisconnectZoneRailgun" 1238 | [[command.option]] 1239 | name = "railgun-id" 1240 | type = "string" 1241 | description = "The railgun ID associated with the railgun being disconnected" 1242 | required = true 1243 | [[command.option]] 1244 | name = "zone-id" 1245 | type = "string" 1246 | description = "The zone ID that the railgun instance is being disconnected from" 1247 | required = true 1248 | 1249 | [[command]] 1250 | name = "enable-railgun" 1251 | description = """Enable a railgun associated with a specific railgun id""" 1252 | shortdescription = "Enable a specific disabled railgun by its id" 1253 | v4apiname = "EnableRailgun" 1254 | [[command.option]] 1255 | name = "railgun-id" 1256 | type = "string" 1257 | description = "The railgun ID associated with the railgun being enabled " 1258 | required = true 1259 | 1260 | [[command]] 1261 | name = "delete-ratelimit" 1262 | description = """Delete a ratelimit associated with a specific ratelimit id""" 1263 | shortdescription = "Delete a specific ratelimit by its id" 1264 | v4apiname = "DeleteRateLimit" 1265 | [[command.option]] 1266 | name = "zone-id" 1267 | type = "string" 1268 | description = "The zone ID associated with the ratelimit being deleted" 1269 | required = true 1270 | [[command.option]] 1271 | name = "ratelimit-id" 1272 | type = "string" 1273 | description = "The ratelimit ID associated with the ratelimit being deleted" 1274 | required = true 1275 | 1276 | [[command]] 1277 | name = "delete-custom-cert" 1278 | description = """Delete a custom certificate associated with a specific certificate id""" 1279 | shortdescription = "Delete a specific certificate by its id" 1280 | v4apiname = "DeleteSSL" 1281 | [[command.option]] 1282 | name = "zone-id" 1283 | type = "string" 1284 | description = "The zone ID associated with the certificate being deleted" 1285 | required = true 1286 | [[command.option]] 1287 | name = "certificate-id" 1288 | type = "string" 1289 | description = "The certificate ID associated with the certificate being deleted" 1290 | required = true 1291 | 1292 | [[command]] 1293 | name = "delete-custom-hostname" 1294 | description = """Delete a custom hostname associated with a specific zone id""" 1295 | shortdescription = "Delete a specific custom hostname" 1296 | v4apiname = "DeleteCustomHostname" 1297 | [[command.option]] 1298 | name = "zone-id" 1299 | type = "string" 1300 | description = "The zone ID associated with the custom hostname being deleted" 1301 | required = true 1302 | [[command.option]] 1303 | name = "custom-hostname-id" 1304 | type = "string" 1305 | description = "The custom hostname ID associated with the custom hostname being deleted" 1306 | required = true 1307 | 1308 | [[command]] 1309 | name = "delete-loadbalancer" 1310 | description = """Delete a loadbalancer associated with a specific zone""" 1311 | shortdescription = "Delete a specific loadbalancer" 1312 | v4apiname = "DeleteLoadBalancer" 1313 | [[command.option]] 1314 | name = "zone-id" 1315 | type = "string" 1316 | description = "The zone ID associated with the loadbalancer" 1317 | required = true 1318 | [[command.option]] 1319 | name = "loadbalancer-id" 1320 | type = "string" 1321 | description = "The loadbalancer-id associated with the custom hostname being deleted" 1322 | required = true 1323 | 1324 | [[command]] 1325 | name = "delete-loadbalancer-monitor" 1326 | description = """Delete a specific loadbalancer monitor""" 1327 | shortdescription = "Delete a specific loadbalancer monitor" 1328 | v4apiname = "DeleteLoadBalancerMonitor" 1329 | [[command.option]] 1330 | name = "monitor-id" 1331 | type = "string" 1332 | description = "The load balancer monitor ID associated with the monitor being deleted" 1333 | required = true 1334 | 1335 | [[command]] 1336 | name = "delete-loadbalancer-pool" 1337 | description = """Delete a specific loadbalancer pool""" 1338 | shortdescription = "Delete a specific loadbalancer pool" 1339 | v4apiname = "DeleteLoadBalancerPool" 1340 | [[command.option]] 1341 | name = "pool-id" 1342 | type = "string" 1343 | description = "The load balancer pool ID associated with the pool being deleted" 1344 | required = true 1345 | 1346 | [[command]] 1347 | name = "delete-organization-access-rule" 1348 | description = """Delete an access rule associated with a specific organization""" 1349 | shortdescription = "Delete a specific access rule" 1350 | v4apiname = "DeleteOrganizationAccessRule" 1351 | [[command.option]] 1352 | name = "organization-id" 1353 | type = "string" 1354 | description = "The organization ID associated with the access rule being deleted" 1355 | required = true 1356 | [[command.option]] 1357 | name = "access-rule-id" 1358 | type = "string" 1359 | description = "The access rule ID associated with the access rule being deleted" 1360 | required = true 1361 | 1362 | [[command]] 1363 | name = "create-railgun" 1364 | description = """Create a railgun""" 1365 | shortdescription = "Create a railgun" 1366 | v4apiname = "CreateRailgun" 1367 | [[command.option]] 1368 | name = "name" 1369 | type = "string" 1370 | description = "The name you are assigning to the newly created railgun" 1371 | required = true 1372 | 1373 | [[command]] 1374 | name = "delete-user-access-rule" 1375 | description = """Delete a specific user access rule""" 1376 | shortdescription = "Delete a user access rule" 1377 | v4apiname = "DeleteUserAccessRule" 1378 | [[command.option]] 1379 | name = "access-rule-id" 1380 | type = "string" 1381 | description = "The access rule id associated with the user access rule you are deleting" 1382 | required = true 1383 | 1384 | [[command]] 1385 | name = "delete-user-agent-rule" 1386 | description = """Delete a specific user agent rule""" 1387 | shortdescription = "Delete a user agent rule" 1388 | v4apiname = "DeleteUserAgentRule" 1389 | [[command.option]] 1390 | name = "user-agent-id" 1391 | type = "string" 1392 | description = "The user agent rule id associated with the user agent rule being deleted" 1393 | required = true 1394 | [[command.option]] 1395 | name = "zone-id" 1396 | type = "string" 1397 | description = "The zone id associated with the user agent rule being deleted" 1398 | required = true 1399 | 1400 | [[command]] 1401 | name = "delete-zone-access-rule" 1402 | description = """Delete a specific zone access rule""" 1403 | shortdescription = "Delete a zone access rule" 1404 | v4apiname = "DeleteZoneAccessRule" 1405 | [[command.option]] 1406 | name = "access-rule-id" 1407 | type = "string" 1408 | description = "The zone access rule id associated with the zone access rule being deleted" 1409 | required = true 1410 | [[command.option]] 1411 | name = "zone-id" 1412 | type = "string" 1413 | description = "The zone id associated with the zone access rule being deleted" 1414 | required = true 1415 | 1416 | [[command]] 1417 | name = "delete-zone-lockdown" 1418 | description = """Delete a specific zone lockdown""" 1419 | shortdescription = "Delete a zone lockdown" 1420 | v4apiname = "DeleteZoneLockdown" 1421 | [[command.option]] 1422 | name = "zone-id" 1423 | type = "string" 1424 | description = "The zone id associated with the specific zone lockdown rule" 1425 | required = true 1426 | [[command.option]] 1427 | name = "lockdown-id" 1428 | type = "string" 1429 | description = "The zone lockdown id associated with the zone lockdown being deleted" 1430 | required = true 1431 | 1432 | [[command]] 1433 | name = "analytics-by-colo" 1434 | description = """Retrieve zone analytics structured by colocation""" 1435 | shortdescription = "Get analytics by colo" 1436 | v4apiname = "ZoneAnalyticsByColocation" 1437 | [[command.option]] 1438 | name = "zone-id" 1439 | type = "string" 1440 | description = "The zone id that analytics are being retreived for" 1441 | required = true 1442 | [[command.option]] 1443 | name = "since" 1444 | type = "string" 1445 | description = "String timestamp of the analytics start time" 1446 | required = false 1447 | [[command.option]] 1448 | name = "until" 1449 | type = "string" 1450 | description = "String timestamp of the analytics end time" 1451 | required = false 1452 | [[command.option]] 1453 | name = "continuous" 1454 | type = "bool" 1455 | description = "When continuous is true and since or until is set, the api will only return completely aggregated results" 1456 | required = false 1457 | 1458 | [[command]] 1459 | name = "analytics-dashboard" 1460 | description = """Retrieve zone analytics overview""" 1461 | shortdescription = "Get an analytics overview by zone" 1462 | v4apiname = "ZoneAnalyticsDashboard" 1463 | [[command.option]] 1464 | name = "zone-id" 1465 | type = "string" 1466 | description = "The zone id that analytics are being retreived for" 1467 | required = true 1468 | [[command.option]] 1469 | name = "since" 1470 | type = "string" 1471 | description = "String timestamp of the analytics start time" 1472 | required = false 1473 | [[command.option]] 1474 | name = "until" 1475 | type = "string" 1476 | description = "String timestamp of the analytics end time" 1477 | required = false 1478 | [[command.option]] 1479 | name = "continuous" 1480 | type = "bool" 1481 | description = "When continuous is true and since or until is set, the api will only return completely aggregated results" 1482 | required = false 1483 | 1484 | [[command]] 1485 | name = "edit-user" 1486 | description = """Edit user account details""" 1487 | shortdescription = "Edit user account details" 1488 | v4apiname = "UpdateUser" 1489 | [[command.option]] 1490 | name = "first-name" 1491 | type = "string" 1492 | description = "User's first name, max length 60" 1493 | required = false 1494 | [[command.option]] 1495 | name = "last-name" 1496 | type = "string" 1497 | description = "User's last name, max length 60" 1498 | required = false 1499 | [[command.option]] 1500 | name = "telephone" 1501 | type = "string" 1502 | description = "User's telephone number, max length 20" 1503 | required = false 1504 | [[command.option]] 1505 | name = "country" 1506 | type = "string" 1507 | description = "The country in which the user lives, example US. max length 30" 1508 | required = false 1509 | [[command.option]] 1510 | name = "zipcode" 1511 | type = "string" 1512 | description = "The zip code or postal code in which the user lives, max length 20" 1513 | required = false 1514 | 1515 | [[command]] 1516 | name = "create-loadbalancer-pool" 1517 | description = """Create a new loadbalancer pool""" 1518 | shortdescription = "Create a loadbalancer pool" 1519 | v4apiname = "CreateLoadBalancerPool" 1520 | [[command.option]] 1521 | name = "name" 1522 | type = "string" 1523 | description = "The name of the loadbalancer pool" 1524 | required = true 1525 | [[command.option]] 1526 | name = "origins" 1527 | type = "string" 1528 | description = "The list of origins Example: [{\\\"name\\\": \\\"app-server-1\\\", \\\"address\\\": \\\"0.0.0.0\\\", \\\"enabled\\\": true, \\\"weight\\\": 0.56}]" 1529 | required = true 1530 | [[command.option]] 1531 | name = "description" 1532 | type = "string" 1533 | description = "A human-readable description of the pool." 1534 | [[command.option]] 1535 | name = "disabled" 1536 | type = "bool" 1537 | description = "By default, the pool will be enabled. Specify disabled in order to modify this default" 1538 | [[command.option]] 1539 | name = "minimum-origins" 1540 | type = "int" 1541 | description = "The minimum number of origins that must be healthy for this pool to serve traffic. " 1542 | [[command.option]] 1543 | name = "monitor" 1544 | type = "string" 1545 | description = "The ID of the Monitor to use for health checking origins within this pool." 1546 | [[command.option]] 1547 | name = "notification-email" 1548 | type = "string" 1549 | description = "The email address to send health status notifications to. This can be an individual mailbox or a mailing list." 1550 | 1551 | [[command]] 1552 | name = "update-loadbalancer-pool" 1553 | description = """Edit an existing loadbalancer pool""" 1554 | shortdescription = "Edit an existing loadbalancer pool" 1555 | v4apiname = "ModifyLoadBalancerPool" 1556 | [[command.option]] 1557 | name = "pool-id" 1558 | type = "string" 1559 | description = "The name of the loadbalancer pool" 1560 | required = true 1561 | [[command.option]] 1562 | name = "name" 1563 | type = "string" 1564 | description = "The name of the loadbalancer pool" 1565 | required = true 1566 | [[command.option]] 1567 | name = "origins" 1568 | type = "string" 1569 | description = "The list of origins Example: [{\\\"name\\\": \\\"app-server-1\\\", \\\"address\\\": \\\"0.0.0.0\\\", \\\"enabled\\\": true, \\\"weight\\\": 0.56}]" 1570 | required = true 1571 | [[command.option]] 1572 | name = "description" 1573 | type = "string" 1574 | description = "A human-readable description of the pool." 1575 | [[command.option]] 1576 | name = "disabled" 1577 | type = "bool" 1578 | description = "By default, the pool will be enabled. Specify disabled in order to modify this default" 1579 | [[command.option]] 1580 | name = "minimum-origins" 1581 | type = "int" 1582 | description = "The minimum number of origins that must be healthy for this pool to serve traffic. " 1583 | [[command.option]] 1584 | name = "monitor" 1585 | type = "string" 1586 | description = "The ID of the Monitor to use for health checking origins within this pool." 1587 | [[command.option]] 1588 | name = "notification-email" 1589 | type = "string" 1590 | description = "The email address to send health status notifications to. This can be an individual mailbox or a mailing list." 1591 | 1592 | [[command]] 1593 | name = "update-zone-settings" 1594 | description = """Edit a zones settings""" 1595 | shortdescription = "Edit a zones settings" 1596 | v4apiname = "UpdateZoneSettings" 1597 | [[command.option]] 1598 | name = "zone-id" 1599 | type = "string" 1600 | description = "The zone id associated with the settings being modified" 1601 | required = true 1602 | [[command.option]] 1603 | name = "zone-settings-object" 1604 | type = "string" 1605 | description = "One or more zone setting objects. Must contain an ID and a value. Example: [{\\\"id\\\": \\\"always_online\\\",\\\"value\\\": \\\"on\\\"}]" 1606 | required = true 1607 | 1608 | [[command]] 1609 | name = "update-zone-lockdown" 1610 | description = """Edit an existing zone lockdown""" 1611 | shortdescription = "Edit an existing zone lockdown" 1612 | v4apiname = "UpdateZoneLockdown" 1613 | [[command.option]] 1614 | name = "zone-id" 1615 | type = "string" 1616 | description = "The zone id associated with the zone lockdown" 1617 | required = true 1618 | [[command.option]] 1619 | name = "lockdown-id" 1620 | type = "string" 1621 | description = "The lockdown id associated with the zone lockdown" 1622 | required = true 1623 | [[command.option]] 1624 | name = "configuration" 1625 | type = "string" 1626 | description = "The new configuration associated with the lockdown - Example: [{\\\"target\\\": \\\"ip\\\",\\\"value\\\": \\\"198.51.100.4\\\"}]" 1627 | required = true 1628 | [[command.option]] 1629 | name = "urls" 1630 | type = "string" 1631 | description = "Comma delimited list of URLs associated with the zone lockdown" 1632 | required = true 1633 | [[command.option]] 1634 | name = "paused" 1635 | type = "bool" 1636 | description = "Whether this zone lockdown is currently paused" 1637 | required = false 1638 | [[command.option]] 1639 | name = "description" 1640 | type = "string" 1641 | description = "A note that you can use to describe the reason for a Lockdown rule" 1642 | required = false 1643 | 1644 | [[command]] 1645 | name = "create-zone-lockdown" 1646 | description = """Create a new zone lockdown""" 1647 | shortdescription = "Create a new zone lockdown" 1648 | v4apiname = "CreateZoneLockdown" 1649 | [[command.option]] 1650 | name = "zone-id" 1651 | type = "string" 1652 | description = "The zone id associated with the zone lockdown" 1653 | required = true 1654 | [[command.option]] 1655 | name = "configuration" 1656 | type = "string" 1657 | description = "The new configuration associated with the lockdown - Example: [{\\\"target\\\": \\\"ip\\\",\\\"value\\\": \\\"198.51.100.4\\\"}]" 1658 | required = true 1659 | [[command.option]] 1660 | name = "urls" 1661 | type = "string" 1662 | description = "Comma delimited list of URLs associated with the zone lockdown" 1663 | required = true 1664 | [[command.option]] 1665 | name = "paused" 1666 | type = "bool" 1667 | description = "Whether this zone lockdown is currently paused" 1668 | required = false 1669 | [[command.option]] 1670 | name = "description" 1671 | type = "string" 1672 | description = "A note that you can use to describe the reason for a Lockdown rule" 1673 | required = false 1674 | 1675 | [[command]] 1676 | name = "create-virtual-dns" 1677 | description = """Create a new virtual dns cluster""" 1678 | shortdescription = "Create a new virtual dns cluster" 1679 | v4apiname = "CreateVirtualDNS" 1680 | [[command.option]] 1681 | name = "name" 1682 | type = "string" 1683 | description = "Virtual DNS Cluster Name, max length: 160 characters" 1684 | required = true 1685 | [[command.option]] 1686 | name = "origin-ips" 1687 | type = "string" 1688 | description = "Comma delimited list of origin IP addresses - Example: [\\\"192.0.2.1\\\",\\\"198.51.100.1\\\",\\\"2001:DB8:100::CF\\\"]" 1689 | required = true 1690 | [[command.option]] 1691 | name = "minimum-cache-ttl" 1692 | type = "int" 1693 | description = "Minimum DNS Cache TTL. default value: 60, min value:30, max value:36000" 1694 | required = false 1695 | [[command.option]] 1696 | name = "maximum-cache-ttl" 1697 | type = "int" 1698 | description = "Maximum DNS Cache TTL. default value: 900, min value:30, max value:36000" 1699 | required = false 1700 | [[command.option]] 1701 | name = "deprecate-any-request" 1702 | type = "bool" 1703 | description = "Deprecate the response to ANY requests" 1704 | required = false 1705 | 1706 | [[command]] 1707 | name = "update-virtual-dns" 1708 | description = """Update a virtual dns cluster""" 1709 | shortdescription = "Update a virtual dns cluster" 1710 | v4apiname = "UpdateVirtualDNS" 1711 | [[command.option]] 1712 | name = "virtual-dns-id" 1713 | type = "string" 1714 | description = "The virtual DNS id being modified" 1715 | required = true 1716 | [[command.option]] 1717 | name = "origin-ips" 1718 | type = "string" 1719 | description = "Comma delimited list of origin IP addresses - Example: [\\\"192.0.2.1\\\",\\\"198.51.100.1\\\",\\\"2001:DB8:100::CF\\\"]" 1720 | required = false 1721 | [[command.option]] 1722 | name = "minimum-cache-ttl" 1723 | type = "int" 1724 | description = "Minimum DNS Cache TTL. default value: 60, min value:30, max value:36000" 1725 | required = false 1726 | [[command.option]] 1727 | name = "maximum-cache-ttl" 1728 | type = "int" 1729 | description = "Maximum DNS Cache TTL. default value: 900, min value:30, max value:36000" 1730 | required = false 1731 | [[command.option]] 1732 | name = "deprecate-any-request" 1733 | type = "bool" 1734 | description = "Deprecate the response to ANY requests" 1735 | required = false 1736 | 1737 | [[command]] 1738 | name = "create-pagerule" 1739 | description = """Create a new page rule associated with a zone""" 1740 | shortdescription = "Create a new page rule" 1741 | v4apiname = "CreatePageRule" 1742 | [[command.option]] 1743 | name = "zone-id" 1744 | type = "string" 1745 | description = "The zone id associated with the new page rule" 1746 | required = true 1747 | [[command.option]] 1748 | name = "targets" 1749 | type = "string" 1750 | description = "List of page rule targets. Examples: '[{\\\"target\\\": \\\"url\\\",\\\"constraint\\\": {\\\"operator\\\": \\\"matches\\\",\\\"value\\\": \\\"*example.com/images/*\\\"}}]'" 1751 | required = true 1752 | [[command.option]] 1753 | name = "actions" 1754 | type = "string" 1755 | description = "List of page rule actions. Examples: '[{\\\"id\\\": \\\"always_online\\\",\\\"value\\\": \\\"on\\\"}]'" 1756 | required = true 1757 | [[command.option]] 1758 | name = "priority" 1759 | type = "int" 1760 | description = "A number that indicates the preference for a page rule over another. default value: 1" 1761 | required = false 1762 | [[command.option]] 1763 | name = "status" 1764 | type = "string" 1765 | description = "Status of the page rule. default value: disabled valid values: active, disabled required = false" 1766 | required = true 1767 | 1768 | [[command]] 1769 | name = "update-pagerule" 1770 | description = """Update a new page rule associated with a zone and page rule""" 1771 | shortdescription = "Update a new page rule" 1772 | v4apiname = "ChangePageRule" 1773 | [[command.option]] 1774 | name = "zone-id" 1775 | type = "string" 1776 | description = "The zone id associated with the updated page rule" 1777 | required = true 1778 | [[command.option]] 1779 | name = "pagerule-id" 1780 | type = "string" 1781 | description = "The pagerule id associated with the updated page rule" 1782 | required = true 1783 | [[command.option]] 1784 | name = "targets" 1785 | type = "string" 1786 | description = "List of page rule targets. Examples: '[{\\\"target\\\": \\\"url\\\",\\\"constraint\\\": {\\\"operator\\\": \\\"matches\\\",\\\"value\\\": \\\"*example.com/images/*\\\"}}]'" 1787 | required = true 1788 | [[command.option]] 1789 | name = "actions" 1790 | type = "string" 1791 | description = "List of page rule actions. Examples: '[{\\\"id\\\": \\\"always_online\\\",\\\"value\\\": \\\"on\\\"}]'" 1792 | required = true 1793 | [[command.option]] 1794 | name = "priority" 1795 | type = "int" 1796 | description = "A number that indicates the preference for a page rule over another. default value: 1" 1797 | required = false 1798 | [[command.option]] 1799 | name = "status" 1800 | type = "string" 1801 | description = "Status of the page rule. default value: disabled valid values: active, disabled required = false" 1802 | required = true 1803 | 1804 | [[command]] 1805 | name = "create-organization-access-rule" 1806 | description = """Make a new IP, IP range, or country access rule for all zones owned by the organization. Note: If you would like to create an access rule that applies to a specific zone only, use the zone firewall endpoints.""" 1807 | shortdescription = "Create an organization access rule" 1808 | v4apiname = "CreateOrganizationAccessRule" 1809 | [[command.option]] 1810 | name = "organization-id" 1811 | type = "string" 1812 | description = "The organization id associated with the new access rule" 1813 | required = true 1814 | [[command.option]] 1815 | name = "mode" 1816 | type = "string" 1817 | description = "The action to apply to a matched request valid values: block, challenge, whitelist, js_challenge" 1818 | required = true 1819 | [[command.option]] 1820 | name = "configuration" 1821 | type = "string" 1822 | description = "Rule configuration. Example {\\\"target\\\": \\\"ip\\\",\\\"value\\\": \\\"198.51.100.4\\\"}" 1823 | required = true 1824 | [[command.option]] 1825 | name = "notes" 1826 | type = "string" 1827 | description = "Rule configuration. Example {\\\"target\\\": \\\"ip\\\",\\\"value\\\": \\\"198.51.100.4\\\"}" 1828 | required = false 1829 | 1830 | [[command]] 1831 | name = "create-origin-cert" 1832 | description = """Create a Cloudflare-signed certificate.""" 1833 | shortdescription = "Create a Cloudflare-signed certificate" 1834 | v4apiname = "CreateOriginCertificate" 1835 | [[command.option]] 1836 | name = "hostnames" 1837 | type = "string" 1838 | description = "Comma-delimited list of hostnames or wildcard names (e.g., *.example.com) bound to the certificate" 1839 | required = true 1840 | [[command.option]] 1841 | name = "request-validity" 1842 | type = "int" 1843 | description = "The number of days for which the certificate should be valid. default value: 5475, valid values: 7, 30, 90, 365, 730, 1095, 5475" 1844 | required = true 1845 | [[command.option]] 1846 | name = "request-type" 1847 | type = "string" 1848 | description = "Signature type desired on certificate (\\\"origin-rsa\\\" (rsa), \\\"origin-ecc\\\" (ecdsa), or \\\"keyless-certificate\\\" (for Keyless SSL servers) valid values: origin-rsa, origin-ecc, keyless-certificate" 1849 | required = true 1850 | [[command.option]] 1851 | name = "csr" 1852 | type = "string" 1853 | description = "The Certificate Signing Request (CSR). Must be newline-encoded. -----BEGIN CERTIFICATE REQUEST-----\\nMIICxzCCA...\\n-----END CERTIFICATE REQUEST-----" 1854 | required = true 1855 | 1856 | [[command]] 1857 | name = "create-ratelimit" 1858 | description = """Create a new rate limit for a zone. See the record object definitions for required attributes for each record type""" 1859 | shortdescription = "Creates a new rate limit for a zone." 1860 | v4apiname = "CreateRateLimit" 1861 | [[command.option]] 1862 | name = "zone-id" 1863 | type = "string" 1864 | description = "The zone id associated with the newly created ratelimit" 1865 | required = true 1866 | [[command.option]] 1867 | name = "match" 1868 | type = "string" 1869 | description = "The match object described by https://api.cloudflare.com/#rate-limits-for-a-zone-create-rate-limit" 1870 | required = true 1871 | [[command.option]] 1872 | name = "threshold" 1873 | type = "int" 1874 | description = "The threshold that triggers the rate limit mitigations, combine with period. i.e. threshold per period min value:2 max value:1000000" 1875 | required = true 1876 | [[command.option]] 1877 | name = "period" 1878 | type = "int" 1879 | description = "The time in seconds to count matching traffic. If the count exceeds threshold within this period the action will be performed. min value:1 max value:86400" 1880 | required = true 1881 | [[command.option]] 1882 | name = "action" 1883 | type = "string" 1884 | description = "The action to be performed when the threshold of matched traffic within the period defined is exceeded '{\\\"mode\\\": \\\"challenge\\\",\\\"timeout\\\": 86400,\\\"response\\\": {\\\"content_type\\\": \\\"text/xml\\\",\\\"body\\\": \\\"This request has been rate-limited.\\\"}}'" 1885 | required = true 1886 | [[command.option]] 1887 | name = "enabled" 1888 | type = "bool" 1889 | description = "Whether this ratelimit is currently enabled or not." 1890 | required = false 1891 | [[command.option]] 1892 | name = "description" 1893 | type = "string" 1894 | description = "A note that you can use to describe the reason for a rate limit. This value is sanitized and all tags are removed max length: 1024" 1895 | required = false 1896 | [[command.option]] 1897 | name = "bypass" 1898 | type = "string" 1899 | description = "Criteria that would allow the rate limit to be bypassed, for example to express that you shouldn't apply a rate limit to a given set of URLs '[{\\\"name\\\": \\\"url\\\",\\\"value\\\": \\\"api.example.com/*\\\"}]'" 1900 | required = false 1901 | 1902 | [[command]] 1903 | name = "update-ratelimit" 1904 | description = """Update a specific rate limit.""" 1905 | shortdescription = "Update a rate limit for a zone." 1906 | v4apiname = "UpdateRateLimit" 1907 | [[command.option]] 1908 | name = "zone-id" 1909 | type = "string" 1910 | description = "The zone id associated with the newly created ratelimit" 1911 | required = true 1912 | [[command.option]] 1913 | name = "limit-id" 1914 | type = "string" 1915 | description = "The ratelimit id associated with the newly created ratelimit" 1916 | required = true 1917 | [[command.option]] 1918 | name = "match" 1919 | type = "string" 1920 | description = "The match object described by https://api.cloudflare.com/#rate-limits-for-a-zone-create-rate-limit" 1921 | required = true 1922 | [[command.option]] 1923 | name = "threshold" 1924 | type = "int" 1925 | description = "The threshold that triggers the rate limit mitigations, combine with period. i.e. threshold per period min value:2 max value:1000000" 1926 | required = true 1927 | [[command.option]] 1928 | name = "period" 1929 | type = "int" 1930 | description = "The time in seconds to count matching traffic. If the count exceeds threshold within this period the action will be performed. min value:1 max value:86400" 1931 | required = true 1932 | [[command.option]] 1933 | name = "action" 1934 | type = "string" 1935 | description = "The action to be performed when the threshold of matched traffic within the period defined is exceeded '{\\\"mode\\\": \\\"challenge\\\",\\\"timeout\\\": 86400,\\\"response\\\": {\\\"content_type\\\": \\\"text/xml\\\",\\\"body\\\": \\\"This request has been rate-limited.\\\"}}'" 1936 | required = true 1937 | [[command.option]] 1938 | name = "enabled" 1939 | type = "bool" 1940 | description = "Whether this ratelimit is currently enabled or not." 1941 | required = false 1942 | [[command.option]] 1943 | name = "description" 1944 | type = "string" 1945 | description = "A note that you can use to describe the reason for a rate limit. This value is sanitized and all tags are removed max length: 1024" 1946 | required = false 1947 | [[command.option]] 1948 | name = "bypass" 1949 | type = "string" 1950 | description = "Criteria that would allow the rate limit to be bypassed, for example to express that you shouldn't apply a rate limit to a given set of URLs '[{\\\"name\\\": \\\"url\\\",\\\"value\\\": \\\"api.example.com/*\\\"}]'" 1951 | required = false 1952 | 1953 | [[command]] 1954 | name = "create-user-access-rule" 1955 | description = """Make a new IP, IP range, or country access rule for all zones owned by the user. Note: If you would like to create an access rule that applies to a specific zone only, use the zone firewall endpoints.""" 1956 | shortdescription = "Create a user access rule" 1957 | v4apiname = "CreateUserAccessRule" 1958 | [[command.option]] 1959 | name = "mode" 1960 | type = "string" 1961 | description = "The action to apply to a matched request valid values: block, challenge, whitelist, js_challenge" 1962 | required = true 1963 | [[command.option]] 1964 | name = "configuration" 1965 | type = "string" 1966 | description = "Rule configuration. Example {\\\"target\\\": \\\"ip\\\",\\\"value\\\": \\\"198.51.100.4\\\"}" 1967 | required = true 1968 | [[command.option]] 1969 | name = "notes" 1970 | type = "string" 1971 | description = "Rule configuration. Example {\\\"target\\\": \\\"ip\\\",\\\"value\\\": \\\"198.51.100.4\\\"}" 1972 | required = false 1973 | 1974 | [[command]] 1975 | name = "update-user-access-rule" 1976 | description = """Update an IP, IP range, or country access rule for all zones owned by the user. Note: If you would like to create an access rule that applies to a specific zone only, use the zone firewall endpoints.""" 1977 | shortdescription = "Create a user access rule" 1978 | v4apiname = "UpdateUserAccessRule" 1979 | [[command.option]] 1980 | name = "access-rule-id" 1981 | type = "string" 1982 | description = "The access rule id associated with the rule being updated" 1983 | required = true 1984 | [[command.option]] 1985 | name = "mode" 1986 | type = "string" 1987 | description = "The action to apply to a matched request valid values: block, challenge, whitelist, js_challenge" 1988 | required = true 1989 | [[command.option]] 1990 | name = "configuration" 1991 | type = "string" 1992 | description = "Rule configuration. Example {\\\"target\\\": \\\"ip\\\",\\\"value\\\": \\\"198.51.100.4\\\"}" 1993 | required = true 1994 | [[command.option]] 1995 | name = "notes" 1996 | type = "string" 1997 | description = "Set the access rule's human readable note" 1998 | required = false 1999 | 2000 | [[command]] 2001 | name = "update-zone-access-rule" 2002 | description = """Update an IP, IP range, or country access rule for all zones owned by the user. Note: If you would like to create an access rule that applies to a specific zone only, use the zone firewall endpoints.""" 2003 | shortdescription = "Create a user access rule" 2004 | v4apiname = "UpdateZoneAccessRule" 2005 | [[command.option]] 2006 | name = "zone-id" 2007 | description = "The zone id associated with the rule being updated" 2008 | type = "string" 2009 | required = true 2010 | [[command.option]] 2011 | name = "access-rule-id" 2012 | type = "string" 2013 | description = "The access rule id associated with the rule being updated" 2014 | required = true 2015 | [[command.option]] 2016 | name = "mode" 2017 | type = "string" 2018 | description = "The action to apply to a matched request valid values: block, challenge, whitelist, js_challenge" 2019 | required = true 2020 | [[command.option]] 2021 | name = "configuration" 2022 | type = "string" 2023 | description = "Rule configuration. Example {\\\"target\\\": \\\"ip\\\",\\\"value\\\": \\\"198.51.100.4\\\"}" 2024 | required = true 2025 | [[command.option]] 2026 | name = "notes" 2027 | type = "string" 2028 | description = "Set the access rule's human readable note" 2029 | required = false 2030 | 2031 | [[command]] 2032 | name = "update-organization-access-rule" 2033 | description = """Update an IP, IP range, or country access rule for all zones owned by the user. Note: If you would like to create an access rule that applies to a specific zone only, use the zone firewall endpoints.""" 2034 | shortdescription = "Create a user access rule" 2035 | v4apiname = "UpdateOrganizationAccessRule" 2036 | [[command.option]] 2037 | name = "organization-id" 2038 | description = "The organization id associated with the rule being updated" 2039 | type = "string" 2040 | required = true 2041 | [[command.option]] 2042 | name = "access-rule-id" 2043 | type = "string" 2044 | description = "The access rule id associated with the rule being updated" 2045 | required = true 2046 | [[command.option]] 2047 | name = "mode" 2048 | type = "string" 2049 | description = "The action to apply to a matched request valid values: block, challenge, whitelist, js_challenge" 2050 | required = true 2051 | [[command.option]] 2052 | name = "configuration" 2053 | type = "string" 2054 | description = "Rule configuration. Example {\\\"target\\\": \\\"ip\\\",\\\"value\\\": \\\"198.51.100.4\\\"}" 2055 | required = true 2056 | [[command.option]] 2057 | name = "notes" 2058 | type = "string" 2059 | description = "Set the access rule's human readable note" 2060 | required = false 2061 | 2062 | [[command]] 2063 | name = "list-zone-access-rules" 2064 | description = """Returns all access rules associated with the zone""" 2065 | shortdescription = "List Zone Access Rules" 2066 | v4apiname = "ListZoneAccessRules" 2067 | [[command.option]] 2068 | name = "zone-id" 2069 | type = "string" 2070 | description = "The zone ID associated with the access rule" 2071 | required = true 2072 | [[command.option]] 2073 | name = "notes" 2074 | type = "string" 2075 | description = "Matching any string within previously created access rules with the notes" 2076 | required = false 2077 | [[command.option]] 2078 | name = "mode" 2079 | type = "string" 2080 | description = "valid values: block, challenge, whitelist, js_challenge" 2081 | required = false 2082 | [[command.option]] 2083 | name = "page" 2084 | type = "int" 2085 | description = "Requested page within paginated list of results" 2086 | required = false 2087 | 2088 | [[command]] 2089 | name = "upload-custom-cert" 2090 | description = """Upload a new SSL certificate for a zone""" 2091 | shortdescription = "Upload a custom SSL cert" 2092 | v4apiname = "CreateSSL" 2093 | [[command.option]] 2094 | name = "zone-id" 2095 | type = "string" 2096 | description = "The zone-id associated with the custom cert" 2097 | required = true 2098 | [[command.option]] 2099 | name = "certificate" 2100 | type = "string" 2101 | description = "The zone's SSL certificate or certificate and the intermediate(s)" 2102 | required = true 2103 | [[command.option]] 2104 | name = "private-key" 2105 | type = "string" 2106 | description = "The zone's private key. Example -----BEGIN RSA PRIVATE KEY-----...-----END RSA PRIVATE KEY-----" 2107 | required = true 2108 | [[command.option]] 2109 | name = "bundle-method" 2110 | type = "string" 2111 | description = "A ubiquitous bundle is a bundle that has a higher probability of being verified everywhere, even by clients using outdated or unusual trust stores. default value: ubiquitous; valid values: ubiquitous, optimal, force required = false" 2112 | 2113 | [[command]] 2114 | name = "update-custom-cert" 2115 | description = """Update a new SSL certificate for a zone""" 2116 | shortdescription = "Upload a custom SSL cert" 2117 | v4apiname = "UpdateSSL" 2118 | [[command.option]] 2119 | name = "zone-id" 2120 | type = "string" 2121 | description = "The zone-id associated with the custom cert" 2122 | required = true 2123 | [[command.option]] 2124 | name = "certificate-id" 2125 | type = "string" 2126 | description = "The certificate id associated with the custom cert" 2127 | required = true 2128 | [[command.option]] 2129 | name = "certificate" 2130 | type = "string" 2131 | description = "The zone's SSL certificate or certificate and the intermediate(s)" 2132 | required = true 2133 | [[command.option]] 2134 | name = "private-key" 2135 | type = "string" 2136 | description = "The zone's private key. Example -----BEGIN RSA PRIVATE KEY-----...-----END RSA PRIVATE KEY-----" 2137 | required = true 2138 | [[command.option]] 2139 | name = "bundle-method" 2140 | type = "string" 2141 | description = "A ubiquitous bundle is a bundle that has a higher probability of being verified everywhere, even by clients using outdated or unusual trust stores. default value: ubiquitous; valid values: ubiquitous, optimal, force required = false" 2142 | 2143 | [[command]] 2144 | name = "purge" 2145 | description = """Purge specific items in the cache""" 2146 | shortdescription = "Purge specific items" 2147 | v4apiname = "Purge" 2148 | [[command.option]] 2149 | name = "zone-id" 2150 | type = "string" 2151 | description = "The zone ID that will be purged." 2152 | required = true 2153 | [[command.option]] 2154 | name = "files" 2155 | type = "string" 2156 | description = "The files that will be purged." 2157 | required = false 2158 | [[command.option]] 2159 | name = "tags" 2160 | type = "string" 2161 | description = "The tags that will be purged." 2162 | required = false 2163 | [[command.option]] 2164 | name = "hosts" 2165 | type = "string" 2166 | description = "The hosts that will be purged." 2167 | required = false 2168 | 2169 | [[command]] 2170 | name = "create-user-agent-rule" 2171 | description = """Creates a new User-Agent rule for a specific zone""" 2172 | shortdescription = "Creates a new User-Agent rule" 2173 | v4apiname = "CreateUserAgentRule" 2174 | [[command.option]] 2175 | name = "zone-id" 2176 | type = "string" 2177 | description = "The zone ID associated with the user-agent rule." 2178 | required = true 2179 | [[command.option]] 2180 | name = "mode" 2181 | type = "string" 2182 | description = "The type of action to perform. max length: 12 valid values: block, challenge, js_challenge" 2183 | required = true 2184 | [[command.option]] 2185 | name = "configuration" 2186 | type = "string" 2187 | description = "Target/Value pair to use for this rule. The value is the exact UserAgent to match {\\\"target\\\": \\\"ua\\\", \\\"value\\\": \\\"Mozilla/5.0\\\"}" 2188 | required = true 2189 | [[command.option]] 2190 | name = "description" 2191 | type = "string" 2192 | description = "Some useful information about this rule to help identify the purpose of it." 2193 | required = false 2194 | [[command.option]] 2195 | name = "paused" 2196 | type = "bool" 2197 | description = "Whether this UA rule is currently paused" 2198 | required = false 2199 | 2200 | [[command]] 2201 | name = "update-user-agent-rule" 2202 | description = """Updates a new User-Agent rule for a specific zone""" 2203 | shortdescription = "Updates a new User-Agent rule" 2204 | v4apiname = "UpdateUserAgentRule" 2205 | [[command.option]] 2206 | name = "zone-id" 2207 | type = "string" 2208 | description = "The zone ID associated with the user-agent rule." 2209 | required = true 2210 | [[command.option]] 2211 | name = "user-agent-id" 2212 | type = "string" 2213 | description = "The user agent ID associated with the user-agent rule." 2214 | required = true 2215 | [[command.option]] 2216 | name = "mode" 2217 | type = "string" 2218 | description = "The type of action to perform. max length: 12 valid values: block, challenge, js_challenge" 2219 | required = true 2220 | [[command.option]] 2221 | name = "configuration" 2222 | type = "string" 2223 | description = "Target/Value pair to use for this rule. The value is the exact UserAgent to match {\\\"target\\\": \\\"ua\\\", \\\"value\\\": \\\"Mozilla/5.0\\\"}" 2224 | required = true 2225 | [[command.option]] 2226 | name = "description" 2227 | type = "string" 2228 | description = "Some useful information about this rule to help identify the purpose of it." 2229 | required = false 2230 | [[command.option]] 2231 | name = "paused" 2232 | type = "bool" 2233 | description = "Whether this UA rule is currently paused" 2234 | required = false 2235 | 2236 | [[command]] 2237 | name = "update-custom-hostname" 2238 | description = """Modify SSL configuration for a custom hostname. When sent with SSL config that matches existing config, used to indicate that hostname should pass domain control validation (DCV). Can also be used to change validation type, e.g., from 'http' to 'email'.""" 2239 | shortdescription = "Create a custom hostname for an associated zone." 2240 | v4apiname = "UpdateCustomHostnameSSL" 2241 | [[command.option]] 2242 | name = "zone-id" 2243 | type = "string" 2244 | description = "The zone ID associated with the custom hostname" 2245 | required = true 2246 | [[command.option]] 2247 | name = "custom-hostname-id" 2248 | type = "string" 2249 | description = "The custom hostname id associated with the custom hostname being modified" 2250 | required = true 2251 | [[command.option]] 2252 | name = "method" 2253 | type = "string" 2254 | description = "The SSL Verification method. valid values: http, email, cname." 2255 | required = true 2256 | [[command.option]] 2257 | name = "type" 2258 | type = "string" 2259 | description = "The type of SSL certificate valid values: dv only" 2260 | required = true 2261 | 2262 | 2263 | [[command]] 2264 | name = "list-custom-hostnames" 2265 | description = """List Custom Hostnames fetches custom hostnames for the given zone, by applying filter.Hostname if not empty and scoping the result to page'th 50 items.""" 2266 | shortdescription = "List custom hostnames" 2267 | v4apiname = "CustomHostnames" 2268 | [[command.option]] 2269 | name = "zone-id" 2270 | type = "string" 2271 | description = "The zone ID associated with the custom hostname" 2272 | required = true 2273 | [[command.option]] 2274 | name = "hostname" 2275 | type = "string" 2276 | description = "The custom hostname that you wish to filter by" 2277 | required = false 2278 | [[command.option]] 2279 | name = "page" 2280 | type = "int" 2281 | description = "API supports pagination. Up to 50 results per page. Default is page 1" 2282 | required = false 2283 | 2284 | [[command]] 2285 | name = "reprioritize-certs" 2286 | description = """If a zone has multiple SSL certificates, you can set the order in which they should be used during a request. Higher priority numbers will be tried first.""" 2287 | shortdescription = "Reprioritize SSL certs" 2288 | v4apiname = "ReprioritizeSSL" 2289 | [[command.option]] 2290 | name = "zone-id" 2291 | type = "string" 2292 | description = "The zone ID associated with the certs" 2293 | required = true 2294 | [[command.option]] 2295 | name = "priority-list" 2296 | description = "Array of ordered certificates. [{\\\"id\\\": \\\"5a7805061c76ada191ed06f989cc3dac\\\",\\\"priority\\\": 2},{\\\"id\\\": \\\"9a7806061c88ada191ed06f989cc3dac\\\",\\\"priority\\\": 1}]" 2297 | type = "string" 2298 | required = true 2299 | 2300 | [[command]] 2301 | name = "update-loadbalancer-monitor" 2302 | description = """Update an existing monitor""" 2303 | shortdescription = "Update a configured monitor" 2304 | v4apiname = "ModifyLoadBalancerMonitor" 2305 | [[command.option]] 2306 | name = "monitor-id" 2307 | type = "string" 2308 | description = "The monitor id associated with the existing loadbalancer monitor" 2309 | required = true 2310 | [[command.option]] 2311 | name = "expected-codes" 2312 | type = "string" 2313 | description = "The expected http response code in the healthcheck" 2314 | required = true 2315 | [[command.option]] 2316 | name = "method" 2317 | type = "string" 2318 | description = "The HTTP method to use for the health check. default value: GET" 2319 | required = false 2320 | [[command.option]] 2321 | name = "header" 2322 | type = "string" 2323 | description = "The HTTP request headers to send in the health check. It is recommended you set a Host header by default. The User-Agent header cannot be overridden. Example: {\\\"Host\\\": [\\\"example.com\\\"],\\\"X-App-ID\\\": [\\\"abc123\\\"]}" 2324 | required = false 2325 | [[command.option]] 2326 | name = "timeout" 2327 | type = "int" 2328 | description = "The timeout (in seconds) before marking the health check as failed. default value: 5" 2329 | required = true 2330 | [[command.option]] 2331 | name = "path" 2332 | type = "string" 2333 | description = "The endpoint path to health check against. default value: /" 2334 | required = true 2335 | [[command.option]] 2336 | name = "interval" 2337 | type = "int" 2338 | description = "The interval between each health check. Shorter intervals may improve failover time, but will increase load. default value 60" 2339 | required = true 2340 | [[command.option]] 2341 | name = "retries" 2342 | type = "int" 2343 | description = "The number of retries to attempt in case of a timeout before marking the origin as unhealthy. default value 2" 2344 | required = true 2345 | [[command.option]] 2346 | name = "expected-body" 2347 | type = "string" 2348 | description = "A case-insensitive sub-string to look for in the response body. If this string is not found, the origin will be marked as unhealthy." 2349 | required = false 2350 | [[command.option]] 2351 | name = "type" 2352 | type = "string" 2353 | description = "The protocol to use for the healthcheck. Currently supported protocols are 'HTTP' and 'HTTPS'. default value: http" 2354 | required = true 2355 | [[command.option]] 2356 | name = "description" 2357 | type = "string" 2358 | description = "Object description" 2359 | required = true 2360 | 2361 | [[command]] 2362 | name = "update-loadbalancer" 2363 | description = """Update an existing loadbalancer""" 2364 | shortdescription = "Update an existing loadbalancer" 2365 | v4apiname = "ModifyLoadBalancer" 2366 | [[command.option]] 2367 | name = "zone-id" 2368 | type = "string" 2369 | description = "The zoneID associated with the loadbalancer" 2370 | required = true 2371 | [[command.option]] 2372 | name = "loadbalancer-id" 2373 | type = "string" 2374 | description = "The loadbalancer id associated with the loadbalancer being modified" 2375 | required = true 2376 | [[command.option]] 2377 | name = "name" 2378 | type = "string" 2379 | description = "The DNS hostname to associate with your Load Balancer. If this hostname already exists as a DNS record in Cloudflare's DNS, the Load Balancer will take precedence and the DNS record will not be used." 2380 | required = true 2381 | [[command.option]] 2382 | name = "fallback-pool" 2383 | type = "string" 2384 | description = "The pool ID to use when all other pools are detected as unhealthy. max length: 32" 2385 | required = true 2386 | [[command.option]] 2387 | name = "default-pools" 2388 | type = "string" 2389 | description = "A comma separated list of pool IDs ordered by their failover priority. Pools defined here are used by default, or when region_pools are not configured for a given region." 2390 | required = true 2391 | [[command.option]] 2392 | name = "proxied" 2393 | type = "bool" 2394 | description = "Whether the hostname should be gray clouded (false) or orange clouded (true). default value: false" 2395 | required = false 2396 | [[command.option]] 2397 | name = "ttl" 2398 | type = "int" 2399 | description = "Time to live (TTL) of the DNS entry for the IP address returned by this load balancer. This only applies to gray-clouded (unproxied) load balancers." 2400 | required = false 2401 | 2402 | [[command]] 2403 | name = "create-worker-route" 2404 | description = """Create a new Edge Worker Route Filter""" 2405 | shortdescription = "Create Worker Router" 2406 | v4apiname = "CreateWorkerRoute" 2407 | [[command.option]] 2408 | name = "zone-id" 2409 | type = "string" 2410 | description = "The zoneID associated with the worker route" 2411 | required = true 2412 | [[command.option]] 2413 | name = "pattern" 2414 | type = "string" 2415 | description = "The url pattern for the route, example: example.net/*" 2416 | required = true 2417 | [[command.option]] 2418 | name = "disable" 2419 | type = "bool" 2420 | description = "Set this flag to disable the worker on a given route" 2421 | required = false 2422 | 2423 | [[command]] 2424 | name = "update-worker-route" 2425 | description = """Create a new Edge Worker Route Filter""" 2426 | shortdescription = "Update Worker Route Filter" 2427 | v4apiname = "UpdateWorkerRoute" 2428 | [[command.option]] 2429 | name = "zone-id" 2430 | type = "string" 2431 | description = "The zoneID associated with the worker route" 2432 | required = true 2433 | [[command.option]] 2434 | name = "route-id" 2435 | type = "string" 2436 | description = "The routeId associated with the worker route" 2437 | required = true 2438 | [[command.option]] 2439 | name = "pattern" 2440 | type = "string" 2441 | description = "The url pattern for the route, example: example.net/*" 2442 | required = true 2443 | [[command.option]] 2444 | name = "disable" 2445 | type = "bool" 2446 | description = "Set this flag to disable the worker on a given route" 2447 | required = false 2448 | 2449 | [[command]] 2450 | name = "list-worker-routes" 2451 | description = """List all a new Edge Worker Route Filter""" 2452 | shortdescription = "List Worker Route Filters" 2453 | v4apiname = "ListWorkerRoutes" 2454 | [[command.option]] 2455 | name = "zone-id" 2456 | type = "string" 2457 | description = "The zoneID associated with the worker route filters" 2458 | required = true 2459 | 2460 | [[command]] 2461 | name = "upload-worker" 2462 | description = """Upload a cloudflare worker for your zone""" 2463 | shortdescription = "Upload a Cloudflare Worker for your zone" 2464 | v4apiname = "UploadWorker" 2465 | [[command.option]] 2466 | name = "zone-id" 2467 | type = "string" 2468 | description = "The zoneID associated with the worker" 2469 | required = true 2470 | [[command.option]] 2471 | name = "script" 2472 | type = "string" 2473 | description = "The raw worker code to run at the edge. @ to read code from a file. - to read from stdin" 2474 | required = true 2475 | [[command.option]] 2476 | name = "script-name" 2477 | type = "string" 2478 | description = "The worker script name associated with the worker" 2479 | required = false 2480 | 2481 | [[command]] 2482 | name = "upload-organization-worker" 2483 | description = """Upload an organization's cloudflare worker""" 2484 | shortdescription = "Upload a Cloudflare Worker associated with your Organization" 2485 | v4apiname = "UploadOrganizationWorker" 2486 | [[command.option]] 2487 | name = "zone-id" 2488 | type = "string" 2489 | description = "The zoneID associated with the worker" 2490 | required = false 2491 | [[command.option]] 2492 | name = "organization-id" 2493 | type = "string" 2494 | description = "The organization id associated with the worker" 2495 | required = true 2496 | [[command.option]] 2497 | name = "name" 2498 | type = "string" 2499 | description = "The worker's name" 2500 | required = true 2501 | [[command.option]] 2502 | name = "script" 2503 | type = "string" 2504 | description = "The raw worker code to run at the edge. @ to read code from a file. - to read from stdin" 2505 | required = true 2506 | 2507 | [[command]] 2508 | name = "delete-worker" 2509 | description = """Delete a cloudflare worker""" 2510 | shortdescription = "Delete Worker" 2511 | v4apiname = "DeleteWorker" 2512 | [[command.option]] 2513 | name = "zone-id" 2514 | type = "string" 2515 | description = "The zoneID associated with the worker" 2516 | required = true 2517 | 2518 | [[command]] 2519 | name = "delete-organization-worker" 2520 | description = """Delete an organization's cloudflare worker""" 2521 | shortdescription = "Delete Organization Worker" 2522 | v4apiname = "DeleteOrganizationWorker" 2523 | [[command.option]] 2524 | name = "organization-id" 2525 | type = "string" 2526 | description = "The organization id associated with the worker" 2527 | required = true 2528 | [[command.option]] 2529 | name = "name" 2530 | type = "string" 2531 | description = "The worker's name" 2532 | required = true 2533 | 2534 | [[command]] 2535 | name = "list-worker-scripts" 2536 | description = """List your cloudflare worker scripts""" 2537 | shortdescription = "List your worker scripts" 2538 | v4apiname = "ListWorkerScripts" 2539 | [[command.option]] 2540 | name = "organization-id" 2541 | type = "string" 2542 | description = "The organization id associated with the workers" 2543 | required = true 2544 | 2545 | [[command]] 2546 | name = "download-worker" 2547 | description = """Download your cloudflare worker script""" 2548 | shortdescription = "Download your worker script" 2549 | v4apiname = "DownloadWorker" 2550 | [[command.option]] 2551 | name = "zone-id" 2552 | type = "string" 2553 | description = "The zone id associated with the workers" 2554 | required = true 2555 | 2556 | [[command]] 2557 | name = "download-organization-worker" 2558 | description = """Download a worker associated with your organization""" 2559 | shortdescription = "Download your worker script" 2560 | v4apiname = "DownloadOrganizationWorker" 2561 | [[command.option]] 2562 | name = "organization-id" 2563 | type = "string" 2564 | description = "The organization id associated with the workers" 2565 | required = true 2566 | [[command.option]] 2567 | name = "name" 2568 | type = "string" 2569 | description = "The worker's name" 2570 | required = true 2571 | 2572 | [[command]] 2573 | name = "get-organization-audit-logs" 2574 | description = """Get an organization's audit logs""" 2575 | shortdescription = "Get Organization audit logs" 2576 | v4apiname = "GetOrganizationAuditLogs" 2577 | [[command.option]] 2578 | name = "organization-id" 2579 | type = "string" 2580 | description = "The organization id associated with audit logs you wish to read" 2581 | required = true 2582 | 2583 | [[command]] 2584 | name = "get-user-audit-logs" 2585 | description = """Get a user's audit logs""" 2586 | shortdescription = "Get audit logs associated with a user" 2587 | v4apiname = "GetUserAuditLogs" 2588 | [[command.option]] 2589 | name = "actor-ip" 2590 | type = "string" 2591 | description = "Filter to search by a specific actor ip" 2592 | required = false 2593 | [[command.option]] 2594 | name = "actor-email" 2595 | type = "string" 2596 | description = "Filter by the email address of the actor that made the change 'alice@example.com'" 2597 | required = false 2598 | [[command.option]] 2599 | name = "zone-name" 2600 | type = "string" 2601 | description = "Filter by the name of the zone associated to the change" 2602 | required = false 2603 | [[command.option]] 2604 | name = "since" 2605 | type = "string" 2606 | description = "Limit the returned results to logs newer than the specified date '2017-04-28'" 2607 | required = false 2608 | [[command.option]] 2609 | name = "id" 2610 | type = "string" 2611 | description = "Find a specific log by its ID. Example: 'f174be97-19b1-40d6-954d-70cd5fbd52db'" 2612 | required = false 2613 | [[command.option]] 2614 | name = "direction" 2615 | type = "string" 2616 | description = "Change the direction of the chronological sorting. Must be: 'asc' or 'desc'" 2617 | required = false 2618 | [[command.option]] 2619 | name = "before" 2620 | type = "string" 2621 | description = "Limit the returned results to logs older than the specified date" 2622 | required = false 2623 | [[command.option]] 2624 | name = "page" 2625 | type = "int" 2626 | description = "Which page of results to return" 2627 | required = false 2628 | [[command.option]] 2629 | name = "per_page" 2630 | type = "int" 2631 | description = "How many results to return per page" 2632 | required = false 2633 | 2634 | [[command]] 2635 | name = "list-kv-namespaces" 2636 | description = """Get your account's kv namespaces""" 2637 | shortdescription = "Get account's kv namespaces" 2638 | v4apiname = "ListWorkersKVNamespaces" 2639 | [[command.option]] 2640 | name = "organization-id" 2641 | type = "string" 2642 | description = "The user's organization id" 2643 | required = true 2644 | 2645 | [[command]] 2646 | name = "delete-kv-namespace" 2647 | description = """Get your account's kv namespaces""" 2648 | shortdescription = "Get account's kv namespaces" 2649 | v4apiname = "DeleteWorkersKVNamespace" 2650 | [[command.option]] 2651 | name = "organization-id" 2652 | type = "string" 2653 | description = "The user's organization id" 2654 | required = true 2655 | [[command.option]] 2656 | name = "namespace-id" 2657 | type = "string" 2658 | description = "The namespace id associated with the kv store" 2659 | required = true 2660 | 2661 | [[command]] 2662 | name = "list-kvs" 2663 | description = """List a specific namespaces keys""" 2664 | shortdescription = "List a specific namespaces keys" 2665 | v4apiname = "ListWorkersKVs" 2666 | [[command.option]] 2667 | name = "organization-id" 2668 | type = "string" 2669 | description = "The user's organization id" 2670 | required = true 2671 | [[command.option]] 2672 | name = "namespace-id" 2673 | type = "string" 2674 | description = "The namespace id associated with the kv store" 2675 | required = true 2676 | 2677 | [[command]] 2678 | name = "get-kv" 2679 | description = """Get a specific value given a key""" 2680 | shortdescription = "Get a specific value given a key" 2681 | v4apiname = "ReadWorkersKV" 2682 | [[command.option]] 2683 | name = "organization-id" 2684 | type = "string" 2685 | description = "The user's organization id" 2686 | required = true 2687 | [[command.option]] 2688 | name = "namespace-id" 2689 | type = "string" 2690 | description = "The namespace id associated with the kv store" 2691 | required = true 2692 | [[command.option]] 2693 | name = "key" 2694 | type = "string" 2695 | description = "The key associated with the value you want returned" 2696 | required = true 2697 | 2698 | [[command]] 2699 | name = "delete-kv" 2700 | description = """Delete a specific key value pair""" 2701 | shortdescription = "Delete a specific key value pair" 2702 | v4apiname = "DeleteWorkersKV" 2703 | [[command.option]] 2704 | name = "organization-id" 2705 | type = "string" 2706 | description = "The user's organization id" 2707 | required = true 2708 | [[command.option]] 2709 | name = "namespace-id" 2710 | type = "string" 2711 | description = "The namespace id associated with the kv store" 2712 | required = true 2713 | [[command.option]] 2714 | name = "key" 2715 | type = "string" 2716 | description = "The key associated with the value you to deleted" 2717 | required = true 2718 | 2719 | [[command]] 2720 | name = "write-kv" 2721 | description = """Write a key value pair""" 2722 | shortdescription = "Write a key value pair" 2723 | v4apiname = "WriteWorkersKV" 2724 | [[command.option]] 2725 | name = "organization-id" 2726 | type = "string" 2727 | description = "The user's organization id" 2728 | required = true 2729 | [[command.option]] 2730 | name = "namespace-id" 2731 | type = "string" 2732 | description = "The namespace id associated with the kv store" 2733 | required = true 2734 | [[command.option]] 2735 | name = "key" 2736 | type = "string" 2737 | description = "The key associated with the kv pair" 2738 | required = true 2739 | [[command.option]] 2740 | name = "value" 2741 | type = "string" 2742 | description = "The value associated with the kv pair" 2743 | required = true 2744 | 2745 | [[command]] 2746 | name = "rename-kv-namespace" 2747 | description = """Rename kv namespace""" 2748 | shortdescription = "Rename a kv namespace" 2749 | v4apiname = "UpdateWorkersKVNamespace" 2750 | [[command.option]] 2751 | name = "organization-id" 2752 | type = "string" 2753 | description = "The user's organization id" 2754 | required = true 2755 | [[command.option]] 2756 | name = "namespace-id" 2757 | type = "string" 2758 | description = "The namespace id associated with the kv store" 2759 | required = true 2760 | [[command.option]] 2761 | name = "name" 2762 | type = "string" 2763 | description = "The namespace's new name" 2764 | required = true 2765 | 2766 | [[command]] 2767 | name = "create-kv-namespace" 2768 | description = """Create a kv namespace""" 2769 | shortdescription = "Create a kv namespace" 2770 | v4apiname = "CreateWorkersKVNamespace" 2771 | [[command.option]] 2772 | name = "organization-id" 2773 | type = "string" 2774 | description = "The user's organization id" 2775 | required = true 2776 | [[command.option]] 2777 | name = "name" 2778 | type = "string" 2779 | description = "The namespace's name" 2780 | required = true 2781 | -------------------------------------------------------------------------------- /definitions/definitions_test.go: -------------------------------------------------------------------------------- 1 | package definitions 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestLoadConfiguration(t *testing.T) { 8 | cmds, err := LoadDefinitions("definitions.toml") 9 | if err != nil { 10 | t.Fatalf("Could not load configuration file: %s", err) 11 | } 12 | if cmds[0].Subcommands[0] == "" { 13 | t.Fatalf("Subcommand value is empty") 14 | } 15 | } 16 | 17 | func TestHyphenToCamel(t *testing.T) { 18 | l := "list-zones" 19 | out := hyphenDelimToCamel(l) 20 | if out != "ListZones" { 21 | t.Fatalf("Unexpected camelcase for list-zones: %s", out) 22 | } 23 | } 24 | 25 | func TestRunTemplate(t *testing.T) { 26 | cmds, err := LoadDefinitions("definitions.toml") 27 | if err != nil { 28 | t.Fatalf("Could not load configuration file: %s", err) 29 | } 30 | _, err = cmds[1].ToGo() 31 | if err != nil { 32 | t.Fatalf("Could not convert command to golang: %s", err) 33 | } 34 | _, err = cmds[0].ToGo() 35 | if err != nil { 36 | t.Fatalf("Could not convert command to golang: %s", err) 37 | } 38 | } 39 | 40 | func TestRunVarTemplate(t *testing.T) { 41 | cmds, err := LoadDefinitions("definitions.toml") 42 | if err != nil { 43 | t.Fatalf("Could not load configuration file: %s", err) 44 | } 45 | _, err = cmds[1].ToVariables() 46 | if err != nil { 47 | t.Fatalf("Could not convert command to golang: %s", err) 48 | } 49 | } 50 | 51 | func TestRunSwitch(t *testing.T) { 52 | cmds, err := LoadDefinitions("definitions.toml") 53 | if err != nil { 54 | t.Fatalf("Could not load configuration file: %s", err) 55 | } 56 | _, err = ToSwitch(cmds) 57 | if err != nil { 58 | t.Fatalf("Could not convert command list to switch: %s", err) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /lib/.cf/credentials: -------------------------------------------------------------------------------- 1 | { 2 | "Email":"evan@twiinsen.com", 3 | "Key":"AKIAXXX" 4 | } 5 | -------------------------------------------------------------------------------- /lib/creds.go: -------------------------------------------------------------------------------- 1 | package lib 2 | 3 | import ( 4 | "encoding/json" 5 | "io/ioutil" 6 | "os" 7 | "os/user" 8 | 9 | "github.com/99designs/keyring" 10 | "github.com/segmentio/aws-okta/lib" 11 | ) 12 | 13 | var ( 14 | DefaultCredentialProvider = &CredProvider{} 15 | ) 16 | 17 | type CredProvider struct { 18 | HomeDir string 19 | } 20 | 21 | type Credentials struct { 22 | Email string `json:"Email"` 23 | Key string `json:"Key"` 24 | UserServiceKey string `json:"UserServiceKey"` 25 | Keychain bool `json:"Keychain"` 26 | } 27 | 28 | func GetKeyring() (keyring.Keyring, error) { 29 | var allowedBackends []keyring.BackendType 30 | return keyring.Open(keyring.Config{ 31 | AllowedBackends: allowedBackends, 32 | KeychainTrustApplication: true, 33 | ServiceName: "cloudflare-credentials", 34 | LibSecretCollectionName: "cloudflare", 35 | FileDir: "~/.cf/", 36 | FilePasswordFunc: func(prompt string) (string, error) { 37 | return lib.Prompt("\n"+prompt, true) 38 | }, 39 | }) 40 | } 41 | 42 | func GetHomeDir() (string, error) { 43 | usr, err := user.Current() 44 | if err != nil { 45 | return "", err 46 | } 47 | return usr.HomeDir, nil 48 | } 49 | 50 | func readConfigFile(homedir string) (*Credentials, error) { 51 | filename := homedir + "/.cf/credentials" 52 | buf, err := ioutil.ReadFile(filename) 53 | if err != nil { 54 | return nil, err 55 | } 56 | c := &Credentials{} 57 | err = json.Unmarshal(buf, c) 58 | return c, err 59 | } 60 | 61 | func (c *Credentials) SetEnv() { 62 | os.Setenv("CF_API_KEY", c.Key) 63 | os.Setenv("CF_API_EMAIL", c.Email) 64 | os.Setenv("CF_USER_SERVICE_KEY", c.UserServiceKey) 65 | } 66 | 67 | func isEnvSet() bool { 68 | // If we already have the cloudflare environment variables set that 69 | // are used by the cloudflare-go library then we should just return. 70 | _, keyOk := os.LookupEnv("CF_API_KEY") 71 | _, emailOk := os.LookupEnv("CF_API_EMAIL") 72 | _, serviceOk := os.LookupEnv("CF_USER_SERVICE_KEY") 73 | return keyOk || emailOk || serviceOk 74 | } 75 | 76 | func (c *CredProvider) ConfigureEnvironment() error { 77 | // Nothing to do 78 | if isEnvSet() { 79 | return nil 80 | } 81 | 82 | homedir := c.HomeDir 83 | 84 | // Otherwise, we need to read the ~/.cf/credentials file in the users 85 | // home directory. It would also be nice to store this in the keychain 86 | if c.HomeDir == "" { 87 | h, err := GetHomeDir() 88 | if err != nil { 89 | return err 90 | } 91 | homedir = h 92 | } 93 | 94 | creds, err := readConfigFile(homedir) 95 | if err != nil { 96 | return err 97 | } 98 | 99 | if creds.Keychain { 100 | kr, err := GetKeyring() 101 | if err != nil { 102 | return err 103 | } 104 | keychainCreds, err := kr.Get("cloudflare-creds") 105 | if err != nil { 106 | return err 107 | } 108 | if err = json.Unmarshal(keychainCreds.Data, &creds); err != nil { 109 | return err 110 | } 111 | } 112 | 113 | creds.SetEnv() 114 | return nil 115 | } 116 | -------------------------------------------------------------------------------- /lib/creds_test.go: -------------------------------------------------------------------------------- 1 | package lib 2 | 3 | import ( 4 | "errors" 5 | "log" 6 | "os" 7 | "strings" 8 | "testing" 9 | ) 10 | 11 | func getCredDir() (string, error) { 12 | var ( 13 | gopath string 14 | ) 15 | if p, ok := os.LookupEnv("GOPATH"); ok { 16 | gopath = p 17 | } else { 18 | return "", errors.New("Could not find GOPATH. GOPATH must be set to test.") 19 | } 20 | return gopath + "/src/github.com/ejcx/cf/lib", nil 21 | } 22 | 23 | func TestGetHomeDir(t *testing.T) { 24 | if _, err := getHomeDir(); err != nil { 25 | t.Fatalf("Could not get home dir: %s", err) 26 | } 27 | } 28 | 29 | func TestLoadCredsFile(t *testing.T) { 30 | testPath, err := getCredDir() 31 | if err != nil { 32 | t.Fatalf("Could not load cred dir: %s", err) 33 | } 34 | credentials, err := readConfigFile(testPath) 35 | if err != nil { 36 | t.Fatalf("Could not read file %s: %s", testPath, err) 37 | } 38 | if credentials.Email == "" { 39 | t.Fatal("Unexpected test credential file result") 40 | } 41 | } 42 | 43 | func TestLoadToEnv(t *testing.T) { 44 | var ( 45 | foundKey bool 46 | ) 47 | testPath, err := getCredDir() 48 | if err != nil { 49 | log.Fatalf("Could not load cred dir: %s", err) 50 | } 51 | c := &CredProvider{ 52 | HomeDir: testPath, 53 | } 54 | err = c.ConfigureEnvironment() 55 | if err != nil { 56 | log.Fatalf("Error while configuring env: %s", err) 57 | } 58 | env := os.Environ() 59 | for _, kv := range env { 60 | envParts := strings.Split(kv, "=") 61 | if len(envParts) != 2 { 62 | t.Fatalf("Unexpected result from env %s", kv) 63 | } 64 | if envParts[0] == "CF_API_KEY" { 65 | foundKey = true 66 | if envParts[1] != "AKIAXXX" { 67 | t.Fatalf("Unexpected value loaded from config") 68 | } 69 | } 70 | } 71 | if !foundKey { 72 | t.Fatal("Never found loaded key") 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ejcx/cf/5abf1c03aac87dbb69d1089de7aa1e2f51428a2a/logo.png -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "github.com/ejcx/cf/cmd" 4 | 5 | func main() { 6 | cmd.Execute() 7 | } 8 | --------------------------------------------------------------------------------