/packngo

My (t0mk's) fork of packethost/packngo

Primary LanguageGoOtherNOASSERTION

packngo

Maintained Release GoDoc Go Report Card Slack Twitter Follow

A Golang client for the Equinix Metal API. (Packet is now Equinix Metal)

Installation

To import this library into your Go project:

import "github.com/packethost/packngo"

Note: A minimum of Go 1.14 is required for development.

Download module with:

go get github.com/packethost/packngo

Stability and Compatibility

This repository is Maintained meaning that this software is supported by Equinix Metal and its community - available to use in production environments.

Packngo is currently provided with a major version of v0. We'll try to avoid breaking changes to this library, but they will certainly happen as we work towards a stable v1 library. See CHANGELOG.md for details on the latest additions, removals, fixes, and breaking changes.

While packngo provides an interface to most of the Equinix Metal API, the API is regularly adding new features. To request or contribute support for more API end-points or added fields, create an issue.

See SUPPORT.md for any other issues.

Usage

To authenticate to the Equinix Metal API, you must have your API token exported in env var PACKET_AUTH_TOKEN.

This code snippet initializes Equinix Metal API client, and lists your Projects:

package main

import (
	"log"

	"github.com/packethost/packngo"
)

func main() {
	c, err := packngo.NewClient()
	if err != nil {
		log.Fatal(err)
	}

	ps, _, err := c.Projects.List(nil)
	if err != nil {
		log.Fatal(err)
	}
	for _, p := range ps {
		log.Println(p.ID, p.Name)
	}
}

This library is used by the official terraform-provider-equinix.

You can also learn a lot from the *_test.go sources. Almost all out tests touch the Equinix Metal API, so you can see how auth, querying and POSTing works. For example devices_test.go.

Linked Resources

Linked resources in Get* and List* functions

The Equinix Metal API includes references to related entities for a wide selection of resource types, indicated by href fields. The Equinix Metal API allows for these entities to be included in the API response, saving the user from making more round-trip API requests. This is useful for linked resources, e.g members of a project, devices in a project. Similarly, by excluding entities that are included by default, you can reduce the API response time and payload size.

Control of this behavior is provided through common attributes that can be used to toggle, by field name, which referenced resources will be included as values in API responses. The API exposes this feature through ?include= and ?exclude= query parameters which accept a comma-separated list of field names. These field names can be dotted to reference nested entities.

Most of the packngo Get functions take references to GetOptions parameters (or ListOptions for List functions). These types include an Include and Exclude slice that will be converted to query parameters upon request.

For example, if you want to list users in a project, you can fetch the project via Projects.Get(pid, nil) call. The result of this call will be a Project which has a Users []User attribute. The items in the []User slice only have a non-zero URL attribute, the rest of the fields will be type defaults. You can then parse the ID of the User resources and fetch them consequently.

Optionally, you can use the ListOptions struct in the project fetch call to include the Users (members JSON tag). Then, every item in the []User slice will have all (not only the Href) attributes populated.

Projects.Get(pid, &packngo.ListOptions{Includes: []{'members'}})

The following is a more comprehensive illustration of Includes and Excludes.

import (
	"log"

	"github.com/packethost/packngo"
)

func listProjectsAndUsers(lo *packngo.ListOptions) {
	c, err := packngo.NewClient()
	if err != nil {
		log.Fatal(err)
	}

	ps, _, err := c.Projects.List(lo)
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("Listing for listOptions %+v\n", lo)
	for _, p := range ps {
		log.Printf("project resource %s has %d users", p.Name, len(p.Users))
		for _, u := range p.Users {
			if u.Email != "" && u.FullName != "" {
				log.Printf("  user %s has email %s\n", u.FullName, u.Email)
			} else {
				log.Printf("  only got user link %s\n", u.URL)
			}
		}
	}
}

func main() {
	loMembers := &packngo.ListOptions{Includes: []string{"members"}}
	loMembersOut := &packngo.ListOptions{Excludes: []string{"members"}}
	listProjectsAndUsers(loMembers)
	listProjectsAndUsers(nil)
	listProjectsAndUsers(loMembersOut)
}

Deprecation and Sunset

If the Equinix Metal API returns a RFC-8594 Deprecation or Sunset header, packngo will log this header to stderr with any accompanied Link headers.

Example:

WARNING: "POST /deprecate-and-sunset" reported deprecation
WARNING: "POST /deprecate-and-sunset" reported sunsetting on Sat, 1 Aug 2020 23:59:59 GMT
WARNING: See <https://api.example.com/deprecation/field-a> for deprecation details
WARNING: See <https://api.example.com/sunset/value-a> for sunset details
WARNING: See <https://api.example.com/sunset> for sunset details
WARNING: See <https://api.example.com/deprecation> for deprecation details

Contributing

See CONTIBUTING.md.