mirror of
https://github.com/edgelesssys/constellation.git
synced 2024-12-26 07:59:37 -05:00
operator: always create initial resources (#858)
* operator: move csp clients to own path * operator: use cloudfake as default csp
This commit is contained in:
parent
f720726074
commit
98316b5248
@ -0,0 +1,91 @@
|
||||
/*
|
||||
Copyright (c) Edgeless Systems GmbH
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
updatev1alpha1 "github.com/edgelesssys/constellation/operators/constellation-node-operator/v2/api/v1alpha1"
|
||||
)
|
||||
|
||||
const (
|
||||
controlPlanesID = "control-planes-id"
|
||||
workersID = "workers-id"
|
||||
)
|
||||
|
||||
// Client is a stub client providing the minimal implementation to set up the initial resources.
|
||||
type Client struct{}
|
||||
|
||||
// GetNodeImage retrieves the image currently used by a node.
|
||||
func (c *Client) GetNodeImage(ctx context.Context, providerID string) (string, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
// GetScalingGroupID retrieves the scaling group that a node is part of.
|
||||
func (c *Client) GetScalingGroupID(ctx context.Context, providerID string) (string, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
// CreateNode creates a new node inside a specified scaling group at the CSP and returns its future name and provider id.
|
||||
func (c *Client) CreateNode(ctx context.Context, scalingGroupID string) (nodeName, providerID string, err error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
// DeleteNode starts the termination of the node at the CSP.
|
||||
func (c *Client) DeleteNode(ctx context.Context, providerID string) error {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
// GetNodeState retrieves the state of a pending node from a CSP.
|
||||
func (c *Client) GetNodeState(ctx context.Context, providerID string) (updatev1alpha1.CSPNodeState, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
// SetScalingGroupImage sets the image to be used by newly created nodes in a scaling group.
|
||||
func (c *Client) SetScalingGroupImage(ctx context.Context, scalingGroupID, image string) error {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
// GetScalingGroupImage retrieves the image currently used by a scaling group.
|
||||
func (c *Client) GetScalingGroupImage(ctx context.Context, scalingGroupID string) (string, error) {
|
||||
return "unsupportedCSP", nil
|
||||
}
|
||||
|
||||
// GetScalingGroupName retrieves the name of a scaling group.
|
||||
func (c *Client) GetScalingGroupName(scalingGroupID string) (string, error) {
|
||||
switch scalingGroupID {
|
||||
case controlPlanesID:
|
||||
return controlPlanesID, nil
|
||||
case workersID:
|
||||
return workersID, nil
|
||||
default:
|
||||
return "", fmt.Errorf("unknown scaling group id %s", scalingGroupID)
|
||||
}
|
||||
}
|
||||
|
||||
// GetAutoscalingGroupName retrieves the name of a scaling group as needed by the cluster-autoscaler.
|
||||
func (c *Client) GetAutoscalingGroupName(scalingGroupID string) (string, error) {
|
||||
switch scalingGroupID {
|
||||
case controlPlanesID:
|
||||
return controlPlanesID, nil
|
||||
case workersID:
|
||||
return workersID, nil
|
||||
default:
|
||||
return "", fmt.Errorf("unknown scaling group id %s", scalingGroupID)
|
||||
}
|
||||
}
|
||||
|
||||
// ListScalingGroups retrieves a list of scaling groups for the cluster.
|
||||
func (c *Client) ListScalingGroups(ctx context.Context, uid string) (controlPlaneGroupIDs []string, workerGroupIDs []string, err error) {
|
||||
return []string{controlPlanesID}, []string{workersID}, nil
|
||||
}
|
||||
|
||||
// AutoscalingCloudProvider returns the cloud-provider name as used by k8s cluster-autoscaler.
|
||||
func (c *Client) AutoscalingCloudProvider() string {
|
||||
return "unsupportedCSP"
|
||||
}
|
@ -44,7 +44,7 @@ func InitialResources(ctx context.Context, k8sClient client.Client, imageInfo im
|
||||
if err != nil {
|
||||
return fmt.Errorf("determining initial node image: %w", err)
|
||||
}
|
||||
imageVersion, err := imageInfo.ImageVersion(imageReference)
|
||||
imageVersion, err := imageInfo.ImageVersion()
|
||||
if err != nil {
|
||||
// do not fail if the image version cannot be determined
|
||||
// this is important for backwards compatibility
|
||||
@ -192,7 +192,7 @@ func createScalingGroup(ctx context.Context, config newScalingGroupConfig) error
|
||||
}
|
||||
|
||||
type imageInfoGetter interface {
|
||||
ImageVersion(imageReference string) (string, error)
|
||||
ImageVersion() (string, error)
|
||||
}
|
||||
|
||||
type scalingGroupGetter interface {
|
||||
|
@ -393,7 +393,7 @@ type stubImageInfo struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func (s stubImageInfo) ImageVersion(_ string) (string, error) {
|
||||
func (s stubImageInfo) ImageVersion() (string, error) {
|
||||
return s.imageVersion, s.err
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ func NewImageInfo() *ImageInfo {
|
||||
|
||||
// ImageVersion tries to parse the image version from the host mounted os-release file.
|
||||
// If the file is not present or does not contain the version, a fallback lookup is performed.
|
||||
func (i *ImageInfo) ImageVersion(imageReference string) (string, error) {
|
||||
func (i *ImageInfo) ImageVersion() (string, error) {
|
||||
var version string
|
||||
var err error
|
||||
for _, path := range osReleasePaths {
|
||||
@ -38,10 +38,13 @@ func (i *ImageInfo) ImageVersion(imageReference string) (string, error) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if version != "" {
|
||||
return version, nil
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return imageVersionFromFallback(imageReference)
|
||||
if version == "" {
|
||||
return "", fmt.Errorf("IMAGE_VERSION not found in %s", strings.Join(osReleasePaths, ", "))
|
||||
}
|
||||
return version, nil
|
||||
}
|
||||
|
||||
// getOSReleaseImageVersion reads the os-release file and returns the image version (if present).
|
||||
@ -94,17 +97,6 @@ func parseOSRelease(osRelease *bufio.Scanner) (map[string]string, error) {
|
||||
return osReleaseMap, nil
|
||||
}
|
||||
|
||||
// imageVersionFromFallback tries to guess the image version from the image reference.
|
||||
// It is a fallback mechanism in case the os-release file is not present or does not contain the version.
|
||||
// This was the case for older images (< v2.3.0).
|
||||
func imageVersionFromFallback(imageReference string) (string, error) {
|
||||
version, ok := fallbackLookup[strings.ToLower(imageReference)]
|
||||
if !ok {
|
||||
return "", fmt.Errorf("image version not found in fallback lookup")
|
||||
}
|
||||
return version, nil
|
||||
}
|
||||
|
||||
const versionKey = "IMAGE_VERSION"
|
||||
|
||||
var (
|
||||
@ -114,41 +106,4 @@ var (
|
||||
"/host/etc/os-release",
|
||||
"/host/usr/lib/os-release",
|
||||
}
|
||||
|
||||
fallbackLookup = map[string]string{
|
||||
// AWS
|
||||
"ami-06b8cbf4837a0a57c": "v2.2.2",
|
||||
"ami-02e96dc04a9e438cd": "v2.2.2",
|
||||
"ami-028ead928a9034b2f": "v2.2.2",
|
||||
"ami-032ac10dd8d8266e3": "v2.2.1",
|
||||
"ami-032e0d57cc4395088": "v2.2.1",
|
||||
"ami-053c3e49e19b96bdd": "v2.2.1",
|
||||
"ami-0e27ebcefc38f648b": "v2.2.0",
|
||||
"ami-098cd37f66523b7c3": "v2.2.0",
|
||||
"ami-04a87d302e2509aad": "v2.2.0",
|
||||
|
||||
// Azure
|
||||
"/communitygalleries/constellationcvm-b3782fa0-0df7-4f2f-963e-fc7fc42663df/images/constellation/versions/2.2.2": "v2.2.2",
|
||||
"/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourcegroups/constellation-images/providers/microsoft.compute/galleries/constellation/images/constellation/versions/2.2.2": "v2.2.2",
|
||||
"/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourcegroups/constellation-images/providers/microsoft.compute/galleries/constellation_cvm/images/constellation/versions/2.2.2": "v2.2.2",
|
||||
"/communitygalleries/constellationcvm-b3782fa0-0df7-4f2f-963e-fc7fc42663df/images/constellation/versions/2.2.1": "v2.2.1",
|
||||
"/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourcegroups/constellation-images/providers/microsoft.compute/galleries/constellation/images/constellation/versions/2.2.1": "v2.2.1",
|
||||
"/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourcegroups/constellation-images/providers/microsoft.compute/galleries/constellation_cvm/images/constellation/versions/2.2.1": "v2.2.1",
|
||||
"/communitygalleries/constellationcvm-b3782fa0-0df7-4f2f-963e-fc7fc42663df/images/constellation/versions/2.2.0": "v2.2.0",
|
||||
"/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourcegroups/constellation-images/providers/microsoft.compute/galleries/constellation/images/constellation/versions/2.2.0": "v2.2.0",
|
||||
"/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourcegroups/constellation-images/providers/microsoft.compute/galleries/constellation_cvm/images/constellation/versions/2.2.0": "v2.2.0",
|
||||
"/communitygalleries/constellationcvm-b3782fa0-0df7-4f2f-963e-fc7fc42663df/images/constellation/versions/2.1.0": "v2.1.0",
|
||||
"/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourcegroups/constellation-images/providers/microsoft.compute/galleries/constellation/images/constellation/versions/2.1.0": "v2.1.0",
|
||||
"/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourcegroups/constellation-images/providers/microsoft.compute/galleries/constellation_cvm/images/constellation/versions/2.1.0": "v2.1.0",
|
||||
"/communitygalleries/constellationcvm-b3782fa0-0df7-4f2f-963e-fc7fc42663df/images/constellation/versions/2.0.0": "v2.0.0",
|
||||
"/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourcegroups/constellation-images/providers/microsoft.compute/galleries/constellation/images/constellation/versions/2.0.0": "v2.0.0",
|
||||
"/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourcegroups/constellation-images/providers/microsoft.compute/galleries/constellation_cvm/images/constellation/versions/2.0.0": "v2.0.0",
|
||||
|
||||
// GCP
|
||||
"projects/constellation-images/global/images/constellation-v2-2-2": "v2.2.2",
|
||||
"projects/constellation-images/global/images/constellation-v2-2-1": "v2.2.1",
|
||||
"projects/constellation-images/global/images/constellation-v2-2-0": "v2.2.0",
|
||||
"projects/constellation-images/global/images/constellation-v2-1-0": "v2.1.0",
|
||||
"projects/constellation-images/global/images/constellation-v2-0-0": "v2.0.0",
|
||||
}
|
||||
)
|
||||
|
@ -38,10 +38,6 @@ func TestImageVersion(t *testing.T) {
|
||||
imageReference: "some-reference",
|
||||
wantErr: true,
|
||||
},
|
||||
"fallback version found": {
|
||||
imageReference: "ami-04a87d302e2509aad",
|
||||
wantVersion: "v2.2.0",
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
@ -59,7 +55,7 @@ func TestImageVersion(t *testing.T) {
|
||||
fs: &afero.Afero{Fs: fs},
|
||||
}
|
||||
|
||||
version, err := imageInfo.ImageVersion(tc.imageReference)
|
||||
version, err := imageInfo.ImageVersion()
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
return
|
||||
@ -124,46 +120,6 @@ func TestParseOSRelease(t *testing.T) {
|
||||
assert.Equal(wantMap, osReleaseMap)
|
||||
}
|
||||
|
||||
func TestImageVersionFromFallback(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
imageReference string
|
||||
wantVersion string
|
||||
wantErr bool
|
||||
}{
|
||||
"AWS reference": {
|
||||
imageReference: "ami-06b8cbf4837a0a57c",
|
||||
wantVersion: "v2.2.2",
|
||||
},
|
||||
"Azure reference": {
|
||||
imageReference: "/subscriptions/0d202bbb-4fa7-4af8-8125-58c269a05435/resourceGroups/constellation-images/providers/Microsoft.Compute/galleries/Constellation/images/constellation/versions/2.1.0",
|
||||
wantVersion: "v2.1.0",
|
||||
},
|
||||
"GCP reference": {
|
||||
imageReference: "projects/constellation-images/global/images/constellation-v2-0-0",
|
||||
wantVersion: "v2.0.0",
|
||||
},
|
||||
"unknown reference": {
|
||||
imageReference: "unknown",
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
require := require.New(t)
|
||||
|
||||
version, err := imageVersionFromFallback(tc.imageReference)
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
assert.Equal(tc.wantVersion, version)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const osRelease = `
|
||||
# Some comment
|
||||
# Some empty lines below
|
||||
|
@ -24,9 +24,10 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/healthz"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log/zap"
|
||||
|
||||
azureclient "github.com/edgelesssys/constellation/operators/constellation-node-operator/v2/internal/azure/client"
|
||||
azureclient "github.com/edgelesssys/constellation/operators/constellation-node-operator/v2/internal/cloud/azure/client"
|
||||
cloudfake "github.com/edgelesssys/constellation/operators/constellation-node-operator/v2/internal/cloud/fake/client"
|
||||
gcpclient "github.com/edgelesssys/constellation/operators/constellation-node-operator/v2/internal/cloud/gcp/client"
|
||||
"github.com/edgelesssys/constellation/operators/constellation-node-operator/v2/internal/deploy"
|
||||
gcpclient "github.com/edgelesssys/constellation/operators/constellation-node-operator/v2/internal/gcp/client"
|
||||
|
||||
updatev1alpha1 "github.com/edgelesssys/constellation/operators/constellation-node-operator/v2/api/v1alpha1"
|
||||
"github.com/edgelesssys/constellation/operators/constellation-node-operator/v2/controllers"
|
||||
@ -100,6 +101,7 @@ func main() {
|
||||
}
|
||||
default:
|
||||
setupLog.Info("CSP does not support upgrades", "csp", csp)
|
||||
cspClient = &cloudfake.Client{}
|
||||
}
|
||||
|
||||
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
|
||||
@ -127,13 +129,13 @@ func main() {
|
||||
}
|
||||
defer etcdClient.Close()
|
||||
|
||||
imageInfo := deploy.NewImageInfo()
|
||||
if err := deploy.InitialResources(context.Background(), k8sClient, imageInfo, cspClient, os.Getenv(constellationUID)); err != nil {
|
||||
setupLog.Error(err, "Unable to deploy initial resources")
|
||||
os.Exit(1)
|
||||
}
|
||||
// Create Controllers
|
||||
if csp == "azure" || csp == "gcp" {
|
||||
imageInfo := deploy.NewImageInfo()
|
||||
if err := deploy.InitialResources(context.Background(), k8sClient, imageInfo, cspClient, os.Getenv(constellationUID)); err != nil {
|
||||
setupLog.Error(err, "Unable to deploy initial resources")
|
||||
os.Exit(1)
|
||||
}
|
||||
if err = controllers.NewNodeVersionReconciler(
|
||||
cspClient, etcdClient, mgr.GetClient(), mgr.GetScheme(),
|
||||
).SetupWithManager(mgr); err != nil {
|
||||
@ -204,7 +206,7 @@ type cspAPI interface {
|
||||
SetScalingGroupImage(ctx context.Context, scalingGroupID, imageURI string) error
|
||||
// GetScalingGroupName retrieves the name of a scaling group.
|
||||
GetScalingGroupName(scalingGroupID string) (string, error)
|
||||
// GetScalingGroupName retrieves the name of a scaling group as needed by the cluster-autoscaler.
|
||||
// GetAutoscalingGroupName retrieves the name of a scaling group as needed by the cluster-autoscaler.
|
||||
GetAutoscalingGroupName(scalingGroupID string) (string, error)
|
||||
// ListScalingGroups retrieves a list of scaling groups for the cluster.
|
||||
ListScalingGroups(ctx context.Context, uid string) (controlPlaneGroupIDs []string, workerGroupIDs []string, err error)
|
||||
|
Loading…
Reference in New Issue
Block a user