constellation/operators/constellation-node-operator/internal/gcp/client/client.go

107 lines
2.5 KiB
Go
Raw Normal View History

/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package client
import (
"context"
"math/rand"
"time"
compute "cloud.google.com/go/compute/apiv1"
"github.com/spf13/afero"
"go.uber.org/multierr"
)
// Client is a client for the Google Compute Engine.
type Client struct {
projectID string
projectAPI
instanceAPI
instanceTemplateAPI
instanceGroupManagersAPI
diskAPI
// prng is a pseudo-random number generator seeded with time. Not used for security.
prng
}
// New creates a new client for the Google Compute Engine.
func New(ctx context.Context, configPath string) (*Client, error) {
projectID, err := loadProjectID(afero.NewOsFs(), configPath)
if err != nil {
return nil, err
}
var closers []closer
projectAPI, err := compute.NewProjectsRESTClient(ctx)
if err != nil {
return nil, err
}
closers = append(closers, projectAPI)
insAPI, err := compute.NewInstancesRESTClient(ctx)
if err != nil {
_ = closeAll(closers)
return nil, err
}
closers = append(closers, insAPI)
templAPI, err := compute.NewInstanceTemplatesRESTClient(ctx)
if err != nil {
_ = closeAll(closers)
return nil, err
}
closers = append(closers, templAPI)
groupAPI, err := compute.NewInstanceGroupManagersRESTClient(ctx)
if err != nil {
_ = closeAll(closers)
return nil, err
}
closers = append(closers, groupAPI)
diskAPI, err := compute.NewDisksRESTClient(ctx)
if err != nil {
_ = closeAll(closers)
return nil, err
}
return &Client{
projectID: projectID,
projectAPI: projectAPI,
instanceAPI: insAPI,
instanceTemplateAPI: &instanceTemplateClient{templAPI},
instanceGroupManagersAPI: &instanceGroupManagersClient{groupAPI},
diskAPI: diskAPI,
prng: rand.New(rand.NewSource(int64(time.Now().Nanosecond()))),
}, nil
}
// Close closes the client's connection.
func (c *Client) Close() error {
closers := []closer{
c.projectAPI,
c.instanceAPI,
c.instanceTemplateAPI,
c.instanceGroupManagersAPI,
c.diskAPI,
}
return closeAll(closers)
}
type closer interface {
Close() error
}
// closeAll closes all closers, even if an error occurs.
//
// Errors are collected and a composed error is returned.
func closeAll(closers []closer) error {
// Since this function is intended to be deferred, it will always call all
// close operations, even if a previous operation failed.
var errs error
for _, closer := range closers {
errs = multierr.Append(errs, closer.Close())
}
return errs
}