saclient

package module
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: May 26, 2026 License: Apache-2.0 Imports: 34 Imported by: 38

README

sacloud/saclient-go

Golang binding of Sakura Cloud API client.

Features

  • Automatic authorization / authentication handling
  • Automatic retry handling
  • Client side rate limitter
  • httptest.Server integration for better testing experience

Quick start

The library provides Client struct as its sole public API. All operations are against it. You have to first allocate it:

import "github.com/sacloud/saclient-go"

var theClient saclient.Client

You can pass various flags to the allocated client using environment variables, command line flags, and others. Let's say we are going to accept those two here:

import "os"

func main() {
	fs := theClient.FlagSet()

	// Load settings from the command line arguments
	err := fs.Parse(os.Args[1:])
	if err != nil {
		os.Exit(1)
	}

	// Load settings from the environment variables
	err = theClient.SetEnviron(os.Environ())
	if err != nil {
		os.Exit(1)
	}

	// This is optional (done automatically)
	// but it is a bit polite to do so explicitly
	err = theClient.Populate()
	if err != nil {
		os.Exit(1)
	}
}

After these set up you can use the client like other HTTP clients, by using its Do method.

import (
	"strings"
	"http"
)

func yourLogic() error {
	// Say you want to post something...
	api := "https://secure.sakura.ad.jp/cloud/zone/is1a/api/cloud/1.1/..."
	io := strings.NewReader(`{
	  "parameter": [
	    "values", "values", "..."
	  ]
	}`)

	// Create a request
	req, err := http.NewRequest("POST", api, io);
	if err != nil {
		return err
	}

	// then call it
	res, err := theClient.Do(req)
	if err != nil {
		return err
	}

	// ...
}

Documentation

Index

Constants

View Source
const Version = "0.4.0"

Variables

This section is empty.

Functions

func IsConflictError added in v0.3.7

func IsConflictError(err error) bool

Returns whether the given error is an Error with a 409 status code.

func IsNotFoundError

func IsNotFoundError(err error) bool

Returns whether the given error is an Error with a 404 status code. Provided here for compatibility with sacloud/api-client-go.

func NewError

func NewError(code int, msg string, err error) error

func NewErrorf

func NewErrorf(format string, args ...any) error

func Ptr

func Ptr[T any](t T) *T

Ptr returns pointer of the value. Handy when you need to pass pointer of literal value.

```golang

import "github.com/sacloud/saclient-go"

func main() {
	ret, err := OtherFunc(saclient.Ptr("string literal"))
}

```

func WithBasicAuth added in v0.2.5

func WithBasicAuth(user, pass string) clientOption

func WithBasicAuth1 added in v0.2.5

func WithBasicAuth1(userinfo string) clientOption

func WithBearerToken

func WithBearerToken(bearer string) clientOption

func WithBigInt

func WithBigInt(needed bool) clientOption

func WithCheckRetryFunc

func WithCheckRetryFunc(f retryablehttp.CheckRetry) clientOption

func WithDefaultTimeout added in v0.3.2

func WithDefaultTimeout(t time.Duration) clientOption

WithDefaultTimeout sets default timeout for requests. For each individual request, timeout can also be set using context.

```golang

var client saclient.Client

// This is setting default
client.SetEnviron([]string{"SAKURA_API_REQUEST_TIMEOUT=30"})

// Alternatively, set it via option
client.SetWith(WithDefaultTimeout(30 * time.Second))

// Below sets timeout only for this request
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
req, _ := http.NewRequestWithContext(ctx, "GET", "https://example.com", nil)
resp, err := client.Do(req)

```

func WithFavouringBasicAuthentication

func WithFavouringBasicAuthentication() clientOption

func WithFavouringBearerAuthentication

func WithFavouringBearerAuthentication() clientOption

func WithFavouringRFC7523

func WithFavouringRFC7523() clientOption

func WithFavouringRFC7617

func WithFavouringRFC7617() clientOption

func WithForceAutomaticAuthentication added in v0.2.5

func WithForceAutomaticAuthentication() clientOption

func WithMiddleware

func WithMiddleware(m ...Middleware) clientOption

func WithRootURL

func WithRootURL(url string) clientOption

func WithTestServer

func WithTestServer(svr *httptest.Server) clientOption

func WithTraceMode

func WithTraceMode(mode string) clientOption

this is not strictly necessary because you can set it via env/flag/HCL, but can be handy on occasions.

func WithUserAgent

func WithUserAgent(ua string) clientOption

func WithZone added in v0.3.2

func WithZone(zone string) clientOption

func WithoutRetry

func WithoutRetry() clientOption

disables retries at all

func Wrapf

func Wrapf(err error, format string, args ...any) error

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

impmlementation of ClientAPI

func (*Client) CompatSettingsFromAPIClientOptions deprecated added in v0.2.4

func (c *Client) CompatSettingsFromAPIClientOptions(opts ...*old.Options) error

Deprecated: it does not cover newer settings.

func (*Client) CompatSettingsFromAPIClientParams deprecated added in v0.2.4

func (c *Client) CompatSettingsFromAPIClientParams(url string, params ...old.ClientParam) error

Deprecated: it does not cover newer settings.

func (*Client) Do

func (c *Client) Do(req *http.Request) (*http.Response, error)

func (*Client) Dup

func (c *Client) Dup() ClientAPI

func (*Client) DupWith

func (c *Client) DupWith(opts ...clientOption) (ClientAPI, error)

func (*Client) EndpointConfig added in v0.3.0

func (c *Client) EndpointConfig() (*EndpointConfig, error)

func (*Client) FlagSet

func (c *Client) FlagSet(eh flag.ErrorHandling) *flag.FlagSet

func (*Client) JSON

func (c *Client) JSON() map[string]any

:NODOC: This is mainly for tests. Not stopping you from using it though. Maybe inspection?

func (*Client) Populate

func (c *Client) Populate() error

func (*Client) Profile

func (c *Client) Profile() (*Profile, error)

func (*Client) ProfileName added in v0.2.1

func (c *Client) ProfileName() (dir, name *string)

func (*Client) ProfileOp

func (c *Client) ProfileOp() (ProfileAPI, error)

func (*Client) ServerURL deprecated added in v0.2.4

func (c *Client) ServerURL() (ret string)

Deprecated: for backward compatibility.

func (*Client) SetEnviron

func (c *Client) SetEnviron(env []string) error

func (*Client) SetWith

func (c *Client) SetWith(opts ...clientOption) error

func (*Client) SettingsFromTerraformProvider

func (c *Client) SettingsFromTerraformProvider(p TerraformProviderInterface) error

type ClientAPI

type ClientAPI interface {
	// Populate settings from environment variables and flags
	//
	// Note that once populated, the settings gets immutable.
	// Also note that first call to [Do] implicityly implies population,
	// means you cannot change settings afterwards.
	Populate() error

	// A copy without population.  You can modify settings and repopulate.
	Dup() ClientAPI

	// “`golang
	//
	//	import (
	//		"os"
	//
	//	   "github.com/sacloud/saclient-go"
	//	)
	//
	//	var client saclient.Client
	//
	//	func main() {
	//		client.SetEnviron(os.Environ())
	//		client.Populate()
	//		// ...
	//	}
	// “`
	SetEnviron(env []string) error

	// “`golang
	//
	//	import (
	//		"context"
	//		"os"
	//
	//		"github.com/hashicorp/terraform-plugin-framework/provider"
	//		"github.com/sacloud/saclient-go"
	//	)
	//
	//	type providerModel struct {
	//		// ...
	//	}
	//
	//	var _ saclient.TerraformProviderInterface = (*providerModel)(nil)
	//
	//	func (p *provider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) {
	//		var config providerModel
	//		var client saclient.Client
	//		diags := req.Config.Get(ctx, &config)
	//		resp.Diagnostics.Append(diags...)
	//		if resp.Diagnostics.HasError() {
	//			return
	//		}
	//
	//		client.SetEnviron(os.Environ())
	//		client.SettingsFromTerraformProvider(&config)
	//		client.Populate()
	//	}
	// “`
	SettingsFromTerraformProvider(config TerraformProviderInterface) error

	// Deprecated: This method does not cover all settings.
	//
	// “`golang
	//
	//	import (
	//		old "github.com/sacloud/saclient-go"
	//		current "github.com/sacloud/saclient-go"
	//	)
	//
	//	var client current.Client
	//
	//	func main() {
	//		client.CompatSettingsFromAPIClientParams(
	//			"https://secure.sakura.ad.jp/...",
	//			old.WithApiKeys("your-token", "your-secret"),
	//			// ...
	//		)
	//		client.Populate()
	//		// ...
	//	}
	// “`
	CompatSettingsFromAPIClientParams(url string, params ...old.ClientParam) error

	// Deprecated: This method does not cover all settings.
	//
	// “`golang
	//
	//	import (
	//		old "github.com/sacloud/saclient-go"
	//		current "github.com/sacloud/saclient-go"
	//	)
	//
	//	var client current.Client
	//
	//	func main() {
	//		client.CompatSettingsFromAPIClientOptions(&old.Options{
	//			AccessToken: "your-token",
	//			AccessTokenSecret: "your-secret",
	//			// ...
	//		})
	//		client.Populate()
	//		// ...
	//	}
	// “`
	CompatSettingsFromAPIClientOptions(opts ...*old.Options) error

	// Deprecated: This is a compatibility layer.  Many aspects are missing here,
	// for instance this does not return error.
	ServerURL() string

	// “`golang
	//
	//	import (
	//	   "github.com/spf13/cobra"
	//	   "github.com/spf13/pflag"
	//	   "github.com/sacloud/saclient-go"
	//	)
	//
	//	var client saclient.Client
	//	var command = &cobra.Command{
	//	    RunE: func(cmd *cobra.Command, args []string) error {
	//	        if err := client.Populate(); err != nil {
	//	            return err
	//	        }
	//	        // ...
	//	        return nil
	//	    },
	//	}
	//
	//	func init() {
	//	   client.SetEnviron(os.Environ())
	//	   command.PersistentFlags().AddGoFlagSet(client.FlagSet(flag.PanicOnError))
	//	}
	// “`
	FlagSet(eh flag.ErrorHandling) *flag.FlagSet

	// Returns the currently selected profile, or nil if absent.
	// Profile historically includes much more than client configuration,
	// like usacloud's ArgumentMatchMode.
	//
	// Note that it's completely normal to have nil here.
	// The user can just opt not to have profiles at all.
	// (typical situation for CI environments etc.)
	Profile() (*Profile, error)

	// _Calculated_ name of the current profile.
	//
	// On normal situations this is identical to Profile().Name.  But
	// there are cases when the specified profile does not exist, or
	// is broken.  This method returns something, regardless of such
	// situations.
	//
	// Note however that this can still return nil, in case there is
	// no profile specified at all.
	ProfileName() (dir, name *string)

	// CRUD-style API operator for Profile resource
	ProfileOp() (ProfileAPI, error)

	// HTTP request doer
	Do(req *http.Request) (*http.Response, error)

	// EndpointConfig returns the resolved endpoint configuration.
	// This contains service-specific base endpoints, zone information,
	// and other configuration needed for SDKs to assemble final API URLs.
	EndpointConfig() (*EndpointConfig, error)
}

The API

func NewClient deprecated added in v0.2.4

func NewClient(
	apiUrl string,
	params ...old.ClientParam,
) (
	sa ClientAPI,
	err error,
)

Deprecated: Strongly discouraged to use this function. It lacks newer features and settings. Considered archaic.

func NewFactory deprecated added in v0.2.4

func NewFactory(opts ...*old.Options) ClientAPI

Deprecated: Strongly discouraged to use this function. It for instance has no way to return error.

type ClientOptionAPI

type ClientOptionAPI interface {
	// destructive application of argument options
	SetWith(...clientOption) error

	// duplicative application of argument options;
	// use it when the receiver is already populated (or unknown)
	DupWith(...clientOption) (ClientAPI, error)
}

type EndpointConfig added in v0.3.0

type EndpointConfig struct {
	// Endpoints is the primary information for API routing.
	// The map key identifies a service (e.g. "iaas", "iam") and the value is its base endpoint.
	//
	// saclient-go treats service keys as opaque identifiers.
	// Keys are not interpreted or validated by this package.
	// Their meaning is defined by each SDK.
	Endpoints map[string]string

	// Zone is the currently selected zone.
	Zone string

	// Zones lists all permitted zones.
	//
	// Deprecated: Do not use. Kept only for compatibility.
	Zones []string

	// APIRootURL is the base URL used by iaas-api-go.
	//
	// Deprecated: Do not use. Kept only for compatibility.
	APIRootURL string
}

EndpointConfig contains the resolved input values needed for SDKs to assemble final API endpoint URLs.

type Error

type Error struct {
	// contains filtered or unexported fields
}

Error represents an error within the HTTP client.

func (*Error) Error

func (e *Error) Error() string

Implements the error interface. Returns a stringized representation of the error.

func (*Error) Unwrap

func (e *Error) Unwrap() error

Unwrap returns the underlying error.

type HttpRequestDoer

type HttpRequestDoer interface {
	Do(req *http.Request) (*http.Response, error)
}

type Middleware added in v0.2.1

type Middleware func(*http.Request, func() (Middleware, bool)) (*http.Response, error)

A Middleware is much like http.RoundTripper, but it additionally takes a "pull" function. You might chain middlewares by pulling the next one.

type Profile

type Profile struct {

	// Name (intuitive)
	Name string

	// Profile contents
	//
	// This is intentionally untyped to allow arbitrary key/values
	Attributes map[string]any
	// contains filtered or unexported fields
}

A (loaded) profile

func (*Profile) Get

func (this *Profile) Get(k string) (any, bool)

func (*Profile) GetCacheFilePath

func (this *Profile) GetCacheFilePath(path *string, verbatim *string) (string, error)

func (*Profile) Keys

func (this *Profile) Keys() iter.Seq[string]

func (*Profile) Pathname

func (this *Profile) Pathname() string

Calculated pathname of the configuration file

func (*Profile) Set

func (this *Profile) Set(k string, v any)

type ProfileAPI

type ProfileAPI interface {
	// List the currently known names of profiles
	List() ([]string, error)

	// Load one of profiles, by name
	Read(name string) (*Profile, error)

	// Create a new profile
	Create(profile *Profile) error

	// Update (merge) an existing profile, updated contents returned
	Update(profile *Profile) (*Profile, error)

	// Delete an existing profile
	Delete(name string) error

	// Get the default profile
	GetCurrentName() (string, error)

	// Set the default profile
	SetCurrentName(name string) error

	// The directory where profiles are stored
	Dir() string
}

Profile is a set of options, named.

type ProfileOp

type ProfileOp struct {
	// contains filtered or unexported fields
}

func NewProfileOp

func NewProfileOp(envp []string) (*ProfileOp, error)

Creates a profile operator

func (*ProfileOp) Create

func (this *ProfileOp) Create(p *Profile) error

func (*ProfileOp) Delete

func (this *ProfileOp) Delete(name string) error

func (*ProfileOp) Dir added in v0.2.1

func (this *ProfileOp) Dir() string

func (*ProfileOp) GetCurrentName

func (this *ProfileOp) GetCurrentName() (string, error)

func (*ProfileOp) List

func (this *ProfileOp) List() ([]string, error)

func (*ProfileOp) Read

func (this *ProfileOp) Read(name string) (*Profile, error)

func (*ProfileOp) SetCurrentName

func (this *ProfileOp) SetCurrentName(name string) error

func (*ProfileOp) Update

func (this *ProfileOp) Update(p *Profile) (*Profile, error)

type TerraformProviderInterface

type TerraformProviderInterface interface {
	LookupClientConfigProfileName() (string, bool)

	// Returns if a Service Principal ID is set, and its value
	// (this ID is unformatted)
	LookupClientConfigServicePrincipalID() (string, bool)

	// Returns if a Service Principal Key ID is set, and its value
	// (this ID is unformatted)
	LookupClientConfigServicePrincipalKeyID() (string, bool)

	// Returns if a Service Principal BYOK Private Key's path is set, and its value
	LookupClientConfigPrivateKeyPath() (string, bool)

	// Returns if an API key is set, and its value
	LookupClientConfigAccessToken() (string, bool)

	// Returns if an API secret is set, and its value
	LookupClientConfigAccessTokenSecret() (string, bool)

	// Returns if the IaaS target zone is set, and its value
	LookupClientConfigZone() (string, bool)

	// Returns if the "Default" zone is set, and its value.
	LookupClientConfigDefaultZone() (string, bool)

	// Returns if the available zones are set, and their values
	LookupClientConfigZones() ([]string, bool)

	// Returns if the max number of retries is set, and its value
	LookupClientConfigRetryMax() (int64, bool)

	// Returns if the seconds to wait between retries is set, and its value
	LookupClientConfigRetryWaitMax() (int64, bool)

	// Returns if the seconds to wait between retries is set, and its value
	LookupClientConfigRetryWaitMin() (int64, bool)

	// Returns if the API root URL is set, and its value
	LookupClientConfigAPIRootURL() (string, bool)

	// Returns if the API request timeout (in seconds) is set, and its value
	LookupClientConfigAPIRequestTimeout() (int64, bool)

	// Returns if the API request rate limit (requests per second) is set, and its value
	LookupClientConfigAPIRequestRateLimit() (int64, bool)

	// Returns the mysterious "trace" mode value, if set
	LookupClientConfigTraceMode() (string, bool)
}

Terraform Provider model shall provide these methods in addition.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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