mirror of
https://github.com/cirruslabs/orchard.git
synced 2026-09-30 03:51:43 +02:00
Introduce service accounts and bootstrap tokens (#22)
This commit is contained in:
+18
-5
@@ -23,6 +23,9 @@ type Client struct {
|
||||
|
||||
httpClient *http.Client
|
||||
baseURL *url.URL
|
||||
|
||||
serviceAccountName string
|
||||
serviceAccountToken string
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
@@ -51,6 +54,8 @@ func New(opts ...Option) (*Client, error) {
|
||||
}
|
||||
|
||||
client.address = defaultContext.URL
|
||||
client.serviceAccountName = defaultContext.ServiceAccountName
|
||||
client.serviceAccountToken = defaultContext.ServiceAccountToken
|
||||
|
||||
tlsConfig, err := defaultContext.TLSConfig()
|
||||
if err != nil {
|
||||
@@ -60,7 +65,7 @@ func New(opts ...Option) (*Client, error) {
|
||||
}
|
||||
|
||||
// Instantiate client
|
||||
httpClient := &http.Client{
|
||||
client.httpClient = &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: client.tlsConfig,
|
||||
},
|
||||
@@ -70,11 +75,9 @@ func New(opts ...Option) (*Client, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client.baseURL = url
|
||||
|
||||
return &Client{
|
||||
httpClient: httpClient,
|
||||
baseURL: url,
|
||||
}, nil
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func (client *Client) request(
|
||||
@@ -120,6 +123,10 @@ func (client *Client) request(
|
||||
return fmt.Errorf("%w instantiate a request: %v", ErrFailed, err)
|
||||
}
|
||||
|
||||
if client.serviceAccountName != "" && client.serviceAccountToken != "" {
|
||||
request.SetBasicAuth(client.serviceAccountName, client.serviceAccountToken)
|
||||
}
|
||||
|
||||
response, err := client.httpClient.Do(request)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w to make a request: %v", ErrFailed, err)
|
||||
@@ -162,3 +169,9 @@ func (client *Client) VMs() *VMsService {
|
||||
client: client,
|
||||
}
|
||||
}
|
||||
|
||||
func (client *Client) ServiceAccounts() *ServiceAccountsService {
|
||||
return &ServiceAccountsService{
|
||||
client: client,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,3 +15,10 @@ func WithTLSConfig(tlsConfig *tls.Config) Option {
|
||||
client.tlsConfig = tlsConfig
|
||||
}
|
||||
}
|
||||
|
||||
func WithCredentials(serviceAccountName string, serviceAccountToken string) Option {
|
||||
return func(client *Client) {
|
||||
client.serviceAccountName = serviceAccountName
|
||||
client.serviceAccountToken = serviceAccountToken
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
//nolint:dupl // maybe we'll figure out how to make client API accessors generic in the future
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/cirruslabs/orchard/pkg/resource/v1"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type ServiceAccountsService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
func (service *ServiceAccountsService) Create(ctx context.Context, serviceAccount *v1.ServiceAccount) error {
|
||||
err := service.client.request(ctx, http.MethodPost, "service-accounts",
|
||||
serviceAccount, nil, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (service *ServiceAccountsService) List(ctx context.Context) ([]v1.ServiceAccount, error) {
|
||||
var serviceAccounts []v1.ServiceAccount
|
||||
|
||||
err := service.client.request(ctx, http.MethodGet, "service-accounts",
|
||||
nil, &serviceAccounts, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return serviceAccounts, nil
|
||||
}
|
||||
|
||||
func (service *ServiceAccountsService) Get(ctx context.Context, name string) (*v1.ServiceAccount, error) {
|
||||
var serviceAccount v1.ServiceAccount
|
||||
|
||||
err := service.client.request(ctx, http.MethodGet, fmt.Sprintf("service-accounts/%s", name),
|
||||
nil, &serviceAccount, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &serviceAccount, nil
|
||||
}
|
||||
|
||||
func (service *ServiceAccountsService) Update(ctx context.Context, serviceAccount *v1.ServiceAccount) error {
|
||||
err := service.client.request(ctx, http.MethodPut, fmt.Sprintf("service-accounts/%s", serviceAccount.Name),
|
||||
serviceAccount, nil, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (service *ServiceAccountsService) Delete(ctx context.Context, name string, force bool) error {
|
||||
params := map[string]string{}
|
||||
|
||||
if force {
|
||||
params["force"] = "true"
|
||||
}
|
||||
|
||||
err := service.client.request(ctx, http.MethodDelete, fmt.Sprintf("service-accounts/%s", name),
|
||||
nil, nil, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
//nolint:dupl // maybe we'll figure out how to make client API accessors generic in the future
|
||||
package client
|
||||
|
||||
import (
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package v1
|
||||
|
||||
type ServiceAccount struct {
|
||||
Token string
|
||||
Roles []ServiceAccountRole
|
||||
|
||||
Meta
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var ErrUnsupportedServiceAccountRole = errors.New("unsupported service account role")
|
||||
|
||||
type ServiceAccountRole string
|
||||
|
||||
const (
|
||||
ServiceAccountRoleWorker ServiceAccountRole = "worker"
|
||||
ServiceAccountRoleComputeRead ServiceAccountRole = "compute:read"
|
||||
ServiceAccountRoleComputeWrite ServiceAccountRole = "compute:write"
|
||||
ServiceAccountRoleAdminRead ServiceAccountRole = "admin:read"
|
||||
ServiceAccountRoleAdminWrite ServiceAccountRole = "admin:write"
|
||||
)
|
||||
|
||||
func NewServiceAccountRole(name string) (ServiceAccountRole, error) {
|
||||
switch name {
|
||||
case string(ServiceAccountRoleWorker):
|
||||
return ServiceAccountRoleWorker, nil
|
||||
case string(ServiceAccountRoleComputeRead):
|
||||
return ServiceAccountRoleComputeRead, nil
|
||||
case string(ServiceAccountRoleComputeWrite):
|
||||
return ServiceAccountRoleComputeWrite, nil
|
||||
case string(ServiceAccountRoleAdminRead):
|
||||
return ServiceAccountRoleAdminRead, nil
|
||||
case string(ServiceAccountRoleAdminWrite):
|
||||
return ServiceAccountRoleAdminWrite, nil
|
||||
default:
|
||||
return "", fmt.Errorf("%w: %s", ErrUnsupportedServiceAccountRole, name)
|
||||
}
|
||||
}
|
||||
|
||||
func AllServiceAccountRoles() []ServiceAccountRole {
|
||||
return []ServiceAccountRole{
|
||||
ServiceAccountRoleWorker,
|
||||
ServiceAccountRoleComputeRead,
|
||||
ServiceAccountRoleComputeWrite,
|
||||
ServiceAccountRoleAdminRead,
|
||||
ServiceAccountRoleAdminWrite,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user