1# linodego
2
3[![Build Status](https://travis-ci.com/linode/linodego.svg?branch=master)](https://travis-ci.com/linode/linodego)
4[![Release](https://img.shields.io/github/v/release/linode/linodego)](https://github.com/linode/linodego/releases/latest)
5[![GoDoc](https://godoc.org/github.com/linode/linodego?status.svg)](https://godoc.org/github.com/linode/linodego)
6[![Go Report Card](https://goreportcard.com/badge/github.com/linode/linodego)](https://goreportcard.com/report/github.com/linode/linodego)
7[![codecov](https://codecov.io/gh/linode/linodego/branch/master/graph/badge.svg)](https://codecov.io/gh/linode/linodego)
8
9Go client for [Linode REST v4 API](https://developers.linode.com/api/v4)
10
11## Installation
12
13```sh
14go get -u github.com/linode/linodego
15```
16
17## API Support
18
19Check [API_SUPPORT.md](API_SUPPORT.md) for current support of the Linode `v4` API endpoints.
20
21** Note: This project will change and break until we release a v1.0.0 tagged version. Breaking changes in v0.x.x will be denoted with a minor version bump (v0.2.4 -> v0.3.0) **
22
23## Documentation
24
25See [godoc](https://godoc.org/github.com/linode/linodego) for a complete reference.
26
27The API generally follows the naming patterns prescribed in the [OpenAPIv3 document for Linode APIv4](https://developers.linode.com/api/v4).
28
29Deviations in naming have been made to avoid using "Linode" and "Instance" redundantly or inconsistently.
30
31A brief summary of the features offered in this API client are shown here.
32
33## Examples
34
35### General Usage
36
37```go
38package main
39
40import (
41	"context"
42	"fmt"
43
44	"github.com/linode/linodego"
45	"golang.org/x/oauth2"
46
47	"log"
48	"net/http"
49	"os"
50)
51
52func main() {
53  apiKey, ok := os.LookupEnv("LINODE_TOKEN")
54  if !ok {
55    log.Fatal("Could not find LINODE_TOKEN, please assert it is set.")
56  }
57  tokenSource := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: apiKey})
58
59  oauth2Client := &http.Client{
60    Transport: &oauth2.Transport{
61      Source: tokenSource,
62    },
63  }
64
65  linodeClient := linodego.NewClient(oauth2Client)
66  linodeClient.SetDebug(true)
67
68  res, err := linodeClient.GetInstance(context.Background(), 4090913)
69  if err != nil {
70    log.Fatal(err)
71  }
72  fmt.Printf("%v", res)
73}
74```
75
76### Pagination
77
78#### Auto-Pagination Requests
79
80```go
81kernels, err := linodego.ListKernels(context.Background(), nil)
82// len(kernels) == 218
83```
84
85Or, use a page value of "0":
86
87```go
88opts := linodego.NewListOptions(0,"")
89kernels, err := linodego.ListKernels(context.Background(), opts)
90// len(kernels) == 218
91```
92
93#### Single Page
94
95```go
96opts := linodego.NewListOptions(2,"")
97// or opts := linodego.ListOptions{PageOptions: &linodego.PageOptions{Page: 2}, PageSize: 500}
98kernels, err := linodego.ListKernels(context.Background(), opts)
99// len(kernels) == 100
100```
101
102ListOptions are supplied as a pointer because the Pages and Results
103values are set in the supplied ListOptions.
104
105```go
106// opts.Results == 218
107```
108
109#### Filtering
110
111```go
112opts := linodego.ListOptions{Filter: "{\"mine\":true}"}
113// or opts := linodego.NewListOptions(0, "{\"mine\":true}")
114stackscripts, err := linodego.ListStackscripts(context.Background(), opts)
115```
116
117### Error Handling
118
119#### Getting Single Entities
120
121```go
122linode, err := linodego.GetInstance(context.Background(), 555) // any Linode ID that does not exist or is not yours
123// linode == nil: true
124// err.Error() == "[404] Not Found"
125// err.Code == "404"
126// err.Message == "Not Found"
127```
128
129#### Lists
130
131For lists, the list is still returned as `[]`, but `err` works the same way as on the `Get` request.
132
133```go
134linodes, err := linodego.ListInstances(context.Background(), linodego.NewListOptions(0, "{\"foo\":bar}"))
135// linodes == []
136// err.Error() == "[400] [X-Filter] Cannot filter on foo"
137```
138
139Otherwise sane requests beyond the last page do not trigger an error, just an empty result:
140
141```go
142linodes, err := linodego.ListInstances(context.Background(), linodego.NewListOptions(9999, ""))
143// linodes == []
144// err = nil
145```
146
147### Writes
148
149When performing a `POST` or `PUT` request, multiple field related errors will be returned as a single error, currently like:
150
151```go
152// err.Error() == "[400] [field1] foo problem; [field2] bar problem; [field3] baz problem"
153```
154
155## Tests
156
157Run `make testunit` to run the unit tests.
158
159Run `make testint` to run the integration tests. The integration tests use fixtures.
160
161To update the test fixtures, run `make fixtures`.  This will record the API responses into the `fixtures/` directory.
162Be careful about committing any sensitive account details.  An attempt has been made to sanitize IP addresses and
163dates, but no automated sanitization will be performed against `fixtures/*Account*.yaml`, for example.
164
165To prevent disrupting unaffected fixtures, target fixture generation like so: `make ARGS="-run TestListVolumes" fixtures`.
166
167## Discussion / Help
168
169Join us at [#linodego](https://gophers.slack.com/messages/CAG93EB2S) on the [gophers slack](https://gophers.slack.com)
170
171## License
172
173[MIT License](LICENSE)
174