triton

package
v0.0.0-...-52b58a3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 31, 2022 License: Apache-2.0, MPL-2.0 Imports: 4 Imported by: 0

README

triton-go

triton-go is a client SDK for Go applications using Joyent's Triton Compute and Object Storage (Manta) APIs.

The Triton Go SDK is used in the following open source projects.

Usage

Triton uses HTTP Signature to sign the Date header in each HTTP request made to the Triton API. Currently, requests can be signed using either a private key file loaded from disk (using an authentication.PrivateKeySigner), or using a key stored with the local SSH Agent (using an SSHAgentSigner.

To construct a Signer, use the New* range of methods in the authentication package. In the case of authentication.NewSSHAgentSigner, the parameters are the fingerprint of the key with which to sign, and the account name (normally stored in the TRITON_ACCOUNT environment variable). There is also support for passing in a username, this will allow you to use an account other than the main Triton account. For example:

input := authentication.SSHAgentSignerInput{
    KeyID:       "a4:c6:f3:75:80:27:e0:03:a9:98:79:ef:c5:0a:06:11",
    AccountName: "AccountName",
    Username:    "Username",
}
sshKeySigner, err := authentication.NewSSHAgentSigner(input)
if err != nil {
    log.Fatalf("NewSSHAgentSigner: %s", err)
}

An appropriate key fingerprint can be generated using ssh-keygen.

ssh-keygen -Emd5 -lf ~/.ssh/id_rsa.pub | cut -d " " -f 2 | sed 's/MD5://'

Each top level package, account, compute, identity, network, all have their own separate client. In order to initialize a package client, simply pass the global triton.ClientConfig struct into the client's constructor function.

config := &triton.ClientConfig{
    TritonURL:   os.Getenv("TRITON_URL"),
    MantaURL:    os.Getenv("MANTA_URL"),
    AccountName: accountName,
    Username:    os.Getenv("TRITON_USER"),
    Signers:     []authentication.Signer{sshKeySigner},
}

c, err := compute.NewClient(config)
if err != nil {
    log.Fatalf("compute.NewClient: %s", err)
}

Constructing compute.Client returns an interface which exposes compute API resources. The same goes for all other packages. Reference their unique documentation for more information.

The same triton.ClientConfig will initialize the Manta storage client as well...

c, err := storage.NewClient(config)
if err != nil {
    log.Fatalf("storage.NewClient: %s", err)
}

Error Handling

If an error is returned by the HTTP API, the error returned from the function will contain an instance of errors.APIError in the chain. Error wrapping is performed using the pkg/errors library.

Acceptance Tests

NOTE: The tests are not currently well-structured, and depend on many hard-coded specifics of the Joyent Public Cloud (JPC) which is being shut down in November 2019. It is likely not possible to run the test suite against a local Triton installation at this time, though that is definitely the intended test suite target environment for future development.

Acceptance Tests run directly against the Triton API, so you will need either a local installation of Triton or an account with Joyent's Public Cloud offering in order to run them. The tests create real resources (and thus cost real money)!

In order to run acceptance tests, the following environment variables must be set:

  • TRITON_TEST - must be set to any value in order to indicate desire to create resources
  • TRITON_URL - the base endpoint for the Triton API
  • TRITON_ACCOUNT - the account name for the Triton API
  • TRITON_KEY_ID - the fingerprint of the SSH key identifying the key

Additionally, you may set TRITON_KEY_MATERIAL to the contents of an unencrypted private key. If this is set, the PrivateKeySigner (see above) will be used - if not the SSHAgentSigner will be used. You can also set TRITON_USER to run the tests against an account other than the main Triton account.

Example Run

The verbose output has been removed for brevity here.

$ HTTP_PROXY=http://localhost:8888 \
    TRITON_TEST=1 \
    TRITON_URL=https://us-sw-1.api.joyent.com \
    TRITON_ACCOUNT=AccountName \
    TRITON_KEY_ID=a4:c6:f3:75:80:27:e0:03:a9:98:79:ef:c5:0a:06:11 \
    go test -v -run "TestAccKey"
=== RUN   TestAccKey_Create
--- PASS: TestAccKey_Create (12.46s)
=== RUN   TestAccKey_Get
--- PASS: TestAccKey_Get (4.30s)
=== RUN   TestAccKey_Delete
--- PASS: TestAccKey_Delete (15.08s)
PASS
ok  	github.com/joyent/triton-go	31.861s

Example API

There's an examples/ directory available with sample code setup for many of the APIs within this library. Most of these can be run using go run and referencing your SSH key file use by your active triton CLI profile.

$ eval "$(triton env us-sw-1)"
$ TRITON_KEY_FILE=~/.ssh/triton-id_rsa go run examples/compute/instances.go

The following is a complete example of how to initialize the compute package client and list all instances under an account. More detailed usage of this library follows.



package main

import (
    "context"
    "fmt"
    "io/ioutil"
    "log"
    "os"
    "time"

    triton "github.com/joyent/triton-go"
    "github.com/joyent/triton-go/authentication"
    "github.com/joyent/triton-go/compute"
)

func main() {
    keyID := os.Getenv("TRITON_KEY_ID")
    accountName := os.Getenv("TRITON_ACCOUNT")
    keyMaterial := os.Getenv("TRITON_KEY_MATERIAL")
    userName := os.Getenv("TRITON_USER")

    var signer authentication.Signer
    var err error

    if keyMaterial == "" {
        input := authentication.SSHAgentSignerInput{
            KeyID:       keyID,
            AccountName: accountName,
            Username:    userName,
        }
        signer, err = authentication.NewSSHAgentSigner(input)
        if err != nil {
            log.Fatalf("Error Creating SSH Agent Signer: {{err}}", err)
        }
    } else {
        var keyBytes []byte
        if _, err = os.Stat(keyMaterial); err == nil {
            keyBytes, err = ioutil.ReadFile(keyMaterial)
            if err != nil {
                log.Fatalf("Error reading key material from %s: %s",
                    keyMaterial, err)
            }
            block, _ := pem.Decode(keyBytes)
            if block == nil {
                log.Fatalf(
                    "Failed to read key material '%s': no key found", keyMaterial)
            }

            if block.Headers["Proc-Type"] == "4,ENCRYPTED" {
                log.Fatalf(
                    "Failed to read key '%s': password protected keys are\n"+
                        "not currently supported. Please decrypt the key prior to use.", keyMaterial)
            }

        } else {
            keyBytes = []byte(keyMaterial)
        }

        input := authentication.PrivateKeySignerInput{
            KeyID:              keyID,
            PrivateKeyMaterial: keyBytes,
            AccountName:        accountName,
            Username:           userName,
        }
        signer, err = authentication.NewPrivateKeySigner(input)
        if err != nil {
            log.Fatalf("Error Creating SSH Private Key Signer: {{err}}", err)
        }
    }

    config := &triton.ClientConfig{
        TritonURL:   os.Getenv("TRITON_URL"),
        AccountName: accountName,
        Username:    userName,
        Signers:     []authentication.Signer{signer},
    }

    c, err := compute.NewClient(config)
    if err != nil {
        log.Fatalf("compute.NewClient: %s", err)
    }

    listInput := &compute.ListInstancesInput{}
    instances, err := c.Instances().List(context.Background(), listInput)
    if err != nil {
        log.Fatalf("compute.Instances.List: %v", err)
    }
    numInstances := 0
    for _, instance := range instances {
        numInstances++
        fmt.Println(fmt.Sprintf("-- Instance: %v", instance.Name))
    }
}

Documentation

Index

Constants

View Source
const CloudAPIMajorVersion = "8"

CloudAPIMajorVersion specifies the CloudAPI version compatibility for current release of the Triton-go SDK.

View Source
const Version = "1.7.0"

Version represents main version number of the current release of the Triton-go SDK.

Variables

View Source
var Prerelease = ""

Prerelease adds a pre-release marker to the version.

If this is "" (empty string) then it means that it is a final release. Otherwise, this is a pre-release such as "dev" (in development), "beta", "rc1", etc.

Functions

func GetEnv

func GetEnv(name string) string

GetEnv looks up environment variables using the preferred "TRITON" prefix, but falls back to the retired "SDC" prefix. For example, looking up "USER" will search for "TRITON_USER" followed by "SDC_USER". If the environment variable is not set, an empty string is returned. GetEnv() is used to aid in the transition and deprecation of the "SDC_*" environment variables.

func UserAgent

func UserAgent() string

UserAgent returns a Triton-go characteristic string that allows the network protocol peers to identify the version, release and runtime of the Triton-go client from which the requests originate.

Types

type ClientConfig

type ClientConfig struct {
	TritonURL   string
	MantaURL    string
	AccountName string
	Username    string
	Signers     []authentication.Signer
}

ClientConfig is a placeholder/input struct around the behavior of configuring a client constructor through the implementation's runtime environment (SDC/MANTA env vars).

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL