cloudflare / cloudflare-go Goto Github PK
View Code? Open in Web Editor NEWThe official Go library for the Cloudflare API
Home Page: https://developers.cloudflare.com/api
License: BSD 3-Clause "New" or "Revised" License
The official Go library for the Cloudflare API
Home Page: https://developers.cloudflare.com/api
License: BSD 3-Clause "New" or "Revised" License
Per example
docker run -it --rm --env-file $HOME/.cloudflare/env solidnerd/cloudflare \
dns create --zone hillmama.com --name hillmama.com --proxy --type A --content 111.222.333.233
Currently we have a couple of different ways of invoking the functions the library provides. For instance the DNS related functions all take the related zone as a string in the input, the WAF related functions take a zone ID as input and the cache purge and ZoneDetails()
methods take a Zone
struct as input.
We should probably come to some conclusion of how we want users to interact with the library, and make sure the functions follow that. It will also make it more clear how the function signatures of future functions will look as we get them implemented.
I am suggesting we take a Zone
struct as input where possible, it will put the load of looking up the zone on the user, but also means the user is able to cache it however they want, keeping the library leaner and "less magical". Another approach would be to always work on the zone ID, since that is the bare minimum we would need in order to interact with the API. Thoughts?
I'm seeing a similar issue to #52 but with PageRules, in which they are actually created and I can retrieve fine with curl et al. - but an error is returned:
error unmarshalling the JSON response: json: cannot unmarshal string into Go value of type int
Some features are tied to the zone, and others can be added at a single-user or organization level. Having different API functions for each use-case is messy and often not desirable.
We should look at:
// This would create objects on the org (if the object supports it), else against the zone (if it does not)
client, err := cloudflare.New("key", "email", cloudflare.OrgID("ad81388e"))
Open to suggestions.
I am not sure why DNSRecord
is requried as an argument of DNSRecords
, because the zone identifier seems to be enough to specify DNS records which you want to fetch and the use-cases are not documented.
So I always have to pass an empty DNSRecord to acquire DNSRecords of a zone. Could you please let me know why does DNSRecords
require DNSRecord
? or it can be removed?
As title says. This is important because we can't get access to the ID of the created record.
I wanted to discuss these before pushing anything, but I'd like to make some (minor) breaking changes.
These would be caught on compile for those not vendoring the library, and should be easy fixes, but they'll still 'break' things.
New()
to return (*API, error)
and enforce non-empty key/email.New
so that you can change the underlying http.Client
, global pagination options, and other options in the future - e.g. func New(key, email string, option ...Option)
where Option
is a func (*API) error
(see here for examples)[]*DNSRecord
- where relevant.Any changes would also include updating flarectl
in the same PR.
Crashes when performing multiple api calls using same *cloudflare.API
client
Safely perform multiple api calls using the same client in parallel
*cloudflare.API.request
is not thread safe and will crash when multiple api requests are made from different goroutines . (This obviously holds true for all of the higher level methods that call it).
The problem happens because we reuse the same http.Header
struct across all requests, and http.Header.Set
are essentially writes to the underlaying map[string][]string
which are not thread safe.
Currently, pagerules.go:
waf
and mirage
not supported by the API*automatic_https_rewrites
and opportunistic_encryption
supported by the APII'm trying to add page rules to Terraform (hashicorp/terraform/#11249) because I'd like to use them, and found these missing. (Unfortunately for me automatic_https_rewrites
was one I personally wanted to use...)
*(Though also, heads-up that if you provide waf
as the ID, but give it nonsense as the value, it'll tell you it can only be on
or off
- as well as the error about it being an invalid setting altogether.)
Exposing XXXResponse
types clutters the public API and offers minimal (if any) benefit to consumers of the package.
Discussion with @jamesog and @saljam internally leads to this proposal:
XXXResponse
types should be made privateResponse.Result
- which will be a *DNSRecord
or *PageRule
Response.Errors
and return them.In addition we should look to standardize on returning/using pointer types, but that could also be tackled in a separate PR/issue.
I am trying implementing a dns add service function in my go program so I referred to flarectl and dns.go
record := cf.DNSRecord{
Name: r.Name,
Type: strings.ToUpper(r.Type),
Content: r.Content,
TTL: int(r.TTL),
Proxied: r.Proxy,
}
if res, err := d.api.CreateDNSRecord(zoneId, record); err != nil { return nil, err
I get Error unmarshalling JSON: json: Unmarshal(nil *cloudflare.DNSRecordResponse)
when running a unit test. I double-checked that I am passing everything correctly by looking at flarectl.go.
DNS record is actually created. Verified by using curl api.
Any help or insights are greatly appreciated!
Summary: Re-factor flarectl to make adding new sub-commands more straightforward.
Open to suggestions/feedback.
When I run "flarectl ips" this warning comes out:
DEPRECATED Action signature. Must be
cli.ActionFunc
. This is an error in the application. Please contact the distributor of this application if this is not you. See
https://github.com/codegangsta/cli/blob/master/CHANGELOG.md#deprecated-cli-app-action-signature
As mentioned in #20 we want to have the structs moved to the file where they are relevant.
https://docs.travis-ci.com/user/deployment/releases
As noted in #85, it would be good if we had a contribution guide on the repository. GitHub has a bit of documentation about it on the blog, but I'm sure we can find some examples from other projects.
The need that prompted this issue to be created, was that we currently don't have any documentation on the tests being run on all PRs, and suggestions for why they may fail.
vet used to be at golang.org/x/tools/cmd/vet but I think is now part of Go in 1.6.
@elithrar can you own this? I'm not sure how to make Travis do one thing for <1.6 and another for >= 1.6.
In the Zone
type, use time.Time
instead of string
for the CreatedOn
and ModifiedOn
fields.
Current:
CreatedOn string `json:"created_on"`
ModifiedOn string `json:"modified_on"`
Proposed:
CreatedOn time.Time `json:"created_on"`
ModifiedOn time.Time `json:"modified_on"`
This would make the Zone
type similar to ZoneCustomSSL
, KeylessSSL
, PageRule
, etc. that use time.Time
for time fields.
Hey there, I'm looking into hashicorp/terraform#7690, and trying to determine if the issue is in the terraform code or in the Cloudflare library.
I'm having issues updating a record using cloudflare-go
directly (I can create it ok). Wondering if someone can point out if I'm doing something incorrectly, or if this is actually a bug in the library.
I'm pretty new to golang, so not surprised if I'm doing something incorrectly here.
package main
import (
"fmt"
"log"
"os"
"github.com/cloudflare/cloudflare-go"
)
func main() {
// Construct a new API object
api, err := cloudflare.New(os.Getenv("CF_API_KEY"), os.Getenv("CF_API_EMAIL"))
if err != nil {
log.Fatal(err)
}
domain := os.Getenv("CF_DOMAIN")
// Fetch the zone ID
zoneId, err := api.ZoneIDByName(domain)
if err != nil {
log.Fatal(err)
}
newRecord := cloudflare.DNSRecord{
Type: "A",
Name: "CFAPI",
Content: "127.0.0.1",
Proxied: false,
ZoneName: domain,
ZoneID: zoneId,
TTL: 3600,
}
log.Printf("[DEBUG] CloudFlare Record create configuration: %#v", newRecord)
r, err := api.CreateDNSRecord(zoneId, newRecord)
if err != nil {
fmt.Errorf("Failed to create record: %s", err)
}
recordId := r.Result.ID
// In the Event that the API returns an empty DNS Record, we verify that the
// ID returned is not the default ""
if recordId == "" {
fmt.Errorf("Failed to find record in Create response; Record was empty")
}
log.Printf("[INFO] CloudFlare Record ID: %s", recordId)
updatedRecord := cloudflare.DNSRecord{
ID: recordId,
Type: "A",
Name: "CFAPI-modified",
Content: "192.168.10.10",
Proxied: true,
ZoneName: domain,
ZoneID: zoneId,
TTL: 120,
}
log.Printf("[DEBUG] CloudFlare Record update configuration: %#v", updatedRecord)
err = api.UpdateDNSRecord(zoneId, recordId, updatedRecord)
if err != nil {
fmt.Errorf("Failed to update record: %s", err)
}
}
CF_API_KEY=*** CF_API_EMAIL=*** CF_DOMAIN=wave-juno.com go run cloudflare.go
2016/12/20 15:30:28 [DEBUG] CloudFlare Record create configuration: cloudflare.DNSRecord{ID:"", Type:"A", Name:"CFAPI", Content:"127.0.0.1", Proxiable:false, Proxied:false, TTL:3600, Locked:false, ZoneID:"5058354498babe04ef58c4168949b099", ZoneName:"wave-juno.com", CreatedOn:time.Time{sec:0, nsec:0, loc:(*time.Location)(nil)}, ModifiedOn:time.Time{sec:0, nsec:0, loc:(*time.Location)(nil)}, Data:interface {}(nil), Meta:interface {}(nil), Priority:0}
2016/12/20 15:30:29 [INFO] CloudFlare Record ID: 2dc525087c2ff8b02289eef8a0ec1d68
2016/12/20 15:30:29 [DEBUG] CloudFlare Record update configuration: cloudflare.DNSRecord{ID:"2dc525087c2ff8b02289eef8a0ec1d68", Type:"A", Name:"CFAPI-modified", Content:"192.168.10.10", Proxiable:false, Proxied:true, TTL:120, Locked:false, ZoneID:"5058354498babe04ef58c4168949b099", ZoneName:"wave-juno.com", CreatedOn:time.Time{sec:0, nsec:0, loc:(*time.Location)(nil)}, ModifiedOn:time.Time{sec:0, nsec:0, loc:(*time.Location)(nil)}, Data:interface {}(nil), Meta:interface {}(nil), Priority:0}
Name=cfapi-modified
Content=192.168.10.10
TTL=120s
Hi cloudflare team.
api, err := cloudflare.New(os.Getenv("CF_API_KEY"), os.Getenv("CF_API_EMAIL"))
if err != nil {
panic(err)
}
res, err := api.DNSRecord("b5b82f8d72414f849bd96a50e6228ece", "645577699")
if err != nil {
panic(err)
}
I executed this code, error occurred.
panic: error from makeRequest: HTTP status 400: content "{\"success\":false,\"errors\":[{\"code\":7003,\"message\":\"Could not route to \\/zones\\/b5b82f8d72414f849bd96a50e6228ece\\/dns_records\\/645577699, perhaps your object identifier is invalid?\"},{\"code\":7000,\"message\":\"No route for that URI\"}],\"messages\":[],\"result\":null}"
I don't know how to solve this.
Go 1.8
OS : Windows 10 / CentOS 7.3
Hello,
How can I add SRV record with this module?
I'm getting:
2016/08/19 12:38:16.224788 dns.go:93: Error creating DNS record: <nil> error from makeRequest: {"success":false,"errors":[{"code":1004,"message":"DNS Validation Error","error_chain":[{"code":9036,"message":""}]}],"messages":[],"result":null}
The error handling made in 586e5a5, means that flarectl
no longer can run without the environment variables with credentials being set to at least something. This doesn't give the best user experience, since neither flarectl --help
or flarectl ips
work any more, even though none of them make API calls which use credentials.
We may have to change flarectl
so cloudflare.New()
only will be called by the functions that actually need the authenticated API to function. A helper method can be introduced in order to minimise the code duplication. Any other suggestions?
Since CreateDNSRecord
now (#28) return the created record when called, we should provide it in the output of flarectl.
Is it possible to an healthcheck
on the DNS a domain is pointing to?
Thank you!
https://github.com/jamesog/cloudflare-go/blob/master/zone.go#L22
} else {
res, err = api.makeRequest("GET", "/zones", nil)
if err != nil {
return []Zone{}, err
}
err = json.Unmarshal(res, &r)
if err != nil {
return []Zone{}, err
}
zones = r.Result
}
In the event that a zone (or zones) exist beyond the first page of results, you may not get all the zones for an account.
Ideally we should look at instead calling /zones?per_page=val&page=num
, inspecting result_info.
in the response and then making additional calls as necessary. Favoring the max. values of per_page
and page
to reduce total HTTP round trips is probably OK, but we could also take custom values as per #4. The issue is that some endpoints take different min/max values.
I'll probably tackle this, but I'll post it here for posterity:
~/.go/src/github.com/jamesog/cloudflare-go(msilverlock/breaking-options โ) golint
cloudflare.go:49:1: comment on exported function NewZone should be of the form "NewZone ..."
cloudflare.go:199:6: exported type ZoneResponse should have comment or be unexported
cloudflare.go:206:6: exported type ZonePlanResponse should have comment or be unexported
cloudflare.go:227:6: exported type ZoneSetting should have comment or be unexported
cloudflare.go:235:6: exported type ZoneSettingResponse should have comment or be unexported
cloudflare.go:242:1: comment on exported type DNSRecord should be of the form "DNSRecord ..." (with optional leading article)
cloudflare.go:261:1: comment on exported type DNSRecordResponse should be of the form "DNSRecordResponse ..." (with optional leading article)
cloudflare.go:269:1: comment on exported type DNSListResponse should be of the form "DNSListResponse ..." (with optional leading article)
cloudflare.go:277:1: comment on exported type ZoneRailgun should be of the form "ZoneRailgun ..." (with optional leading article)
cloudflare.go:285:6: exported type ZoneRailgunResponse should have comment or be unexported
cloudflare.go:292:1: comment on exported type ZoneCustomSSL should be of the form "ZoneCustomSSL ..." (with optional leading article)
cloudflare.go:308:6: exported type ZoneCustomSSLResponse should have comment or be unexported
cloudflare.go:315:6: exported type KeylessSSL should have comment or be unexported
cloudflare.go:327:6: exported type KeylessSSLResponse should have comment or be unexported
cloudflare.go:334:6: exported type Railgun should have comment or be unexported
cloudflare.go:353:6: exported type RailgunResponse should have comment or be unexported
cloudflare.go:360:1: comment on exported type CustomPage should be of the form "CustomPage ..." (with optional leading article)
cloudflare.go:371:6: exported type CustomPageResponse should have comment or be unexported
cloudflare.go:378:1: comment on exported type WAFPackage should be of the form "WAFPackage ..." (with optional leading article)
cloudflare.go:389:6: exported type WAFPackagesResponse should have comment or be unexported
cloudflare.go:400:6: exported type WAFRule should have comment or be unexported
cloudflare.go:414:6: exported type WAFRulesResponse should have comment or be unexported
cloudflare.go:425:6: exported type PurgeCacheRequest should have comment or be unexported
cloudflare.go:431:6: exported type PurgeCacheResponse should have comment or be unexported
dns.go:9:1: comment on exported method API.CreateDNSRecord should be of the form "CreateDNSRecord ..."
dns.go:38:1: comment on exported method API.DNSRecords should be of the form "DNSRecords ..."
dns.go:81:1: comment on exported method API.DNSRecord should be of the form "DNSRecord ..."
dns.go:108:1: comment on exported method API.UpdateDNSRecord should be of the form "UpdateDNSRecord ..."
dns.go:143:1: comment on exported method API.DeleteDNSRecord should be of the form "DeleteDNSRecord ..."
keyless.go:3:1: comment on exported method API.CreateKeyless should be of the form "CreateKeyless ..."
keyless.go:8:1: comment on exported method API.ListKeyless should be of the form "ListKeyless ..."
keyless.go:13:1: comment on exported method API.Keyless should be of the form "Keyless ..."
keyless.go:18:1: comment on exported method API.UpdateKeyless should be of the form "UpdateKeyless ..."
keyless.go:23:1: comment on exported method API.DeleteKeyless should be of the form "DeleteKeyless ..."
railgun.go:5:1: comment on exported method API.CreateRailgun should be of the form "CreateRailgun ..."
railgun.go:24:1: comment on exported method API.Railguns should be of the form "Railguns ..."
railgun.go:29:1: comment on exported method API.Railgun should be of the form "Railgun ..."
railgun.go:34:1: comment on exported method API.ZoneRailgun should be of the form "ZoneRailgun ..."
ssl.go:3:1: comment on exported method API.CreateSSL should be of the form "CreateSSL ..."
ssl.go:8:1: comment on exported method API.ListSSL should be of the form "ListSSL ..."
ssl.go:13:1: comment on exported method API.SSLDetails should be of the form "SSLDetails ..."
ssl.go:18:1: comment on exported method API.UpdateSSL should be of the form "UpdateSSL ..."
ssl.go:23:1: comment on exported method API.ReprioSSL should be of the form "ReprioSSL ..."
ssl.go:28:1: comment on exported method API.DeleteSSL should be of the form "DeleteSSL ..."
user.go:5:1: comment on exported method API.UserDetails should be of the form "UserDetails ..."
user.go:23:1: comment on exported method API.UpdateUser should be of the form "UpdateUser ..."
waf.go:7:1: exported method API.ListWAFPackages should have comment or be unexported
waf.go:23:10: should omit 2nd value from range; this loop is equivalent to `for pi := range ...`
waf.go:29:1: exported method API.ListWAFRules should have comment or be unexported
waf.go:45:10: should omit 2nd value from range; this loop is equivalent to `for ri := range ...`
zone.go:8:1: comment on exported method API.CreateZone should be of the form "CreateZone ..."
zone.go:17:1: comment on exported method API.ListZones should be of the form "ListZones ..."
zone.go:42:12: should omit 2nd value from range; this loop is equivalent to `for zi := range ...`
zone.go:61:1: comment on exported method API.ZoneDetails should be of the form "ZoneDetails ..."
zone.go:92:1: comment on exported function EditZone should be of the form "EditZone ..."
zone.go:97:1: comment on exported method API.PurgeEverything should be of the form "PurgeEverything ..."
zone.go:112:1: comment on exported method API.PurgeCache should be of the form "PurgeCache ..."
zone.go:127:1: comment on exported function DeleteZone should be of the form "DeleteZone ..."
Using this api call from the cloudflare-go package:
api, err := cloudflare.New(cloudflareApiKey, cloudflareApiEmail,
cloudflare.HTTPClient(urlfetch.Client(c)))
resp, err := api.PurgeCache(zoneID, cloudflare.PurgeCacheRequest{
Files: []string{"http://example.com/foo"},
})
the error response is:
error from makeRequest: HTTP status 400: content "{\"success\":false,\"errors\":[{\"code\":1012,\"message\":\"Request must contain one of \\\"purge_everything\\\" or \\\"files\\\", or \\\"tags\"}],\"messages\":[],\"result\":null}"
Could this be a weird interaction with the App Engine urlfetch HTTP client?
I suppose because this library just passes them straight through without validation, and because the documentation is generated, valid values for PageRuleAction.Value
(depending on PageRuleAction.ID
are not given.
The majority of them can be easily guessed from the web UI, but not all of them, and some of them would be guessed incorrectly; for example:
"strict"
"basic"
, 'Ignore Query String' is `"simplified", etc.It's discoverable, but docs would be helpful. (I just set them no the web UI, then curl
ed to see what it should be.)
I suppose they wouldn't even need to be on cloudflare-go docs if the options were fully enumerated on the main API docs - which, as far as I can tell, they're not.
DELETE
request to the custom hostname endpoint(https://api.cloudflare.com/#custom-hostname-for-a-zone-delete-a-custom-hostname-and-any-issued-ssl-certificates-) returns an empty(incorrect JSON) response with the status of 204
. According to the API doc it should return a correct JSON:
{
"id": "<id of deleted custom hostname>"
}
Assuming the API doc for this specific case is outdated, makeRequest
should be able to handle 204
responses instead of returning an error.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.