mirror of
https://github.com/edgelesssys/constellation.git
synced 2024-12-27 00:19:36 -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 {
|
if err != nil {
|
||||||
return fmt.Errorf("determining initial node image: %w", err)
|
return fmt.Errorf("determining initial node image: %w", err)
|
||||||
}
|
}
|
||||||
imageVersion, err := imageInfo.ImageVersion(imageReference)
|
imageVersion, err := imageInfo.ImageVersion()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// do not fail if the image version cannot be determined
|
// do not fail if the image version cannot be determined
|
||||||
// this is important for backwards compatibility
|
// this is important for backwards compatibility
|
||||||
@ -192,7 +192,7 @@ func createScalingGroup(ctx context.Context, config newScalingGroupConfig) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
type imageInfoGetter interface {
|
type imageInfoGetter interface {
|
||||||
ImageVersion(imageReference string) (string, error)
|
ImageVersion() (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type scalingGroupGetter interface {
|
type scalingGroupGetter interface {
|
||||||
|
@ -393,7 +393,7 @@ type stubImageInfo struct {
|
|||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s stubImageInfo) ImageVersion(_ string) (string, error) {
|
func (s stubImageInfo) ImageVersion() (string, error) {
|
||||||
return s.imageVersion, s.err
|
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.
|
// 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.
|
// 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 version string
|
||||||
var err error
|
var err error
|
||||||
for _, path := range osReleasePaths {
|
for _, path := range osReleasePaths {
|
||||||
@ -38,10 +38,13 @@ func (i *ImageInfo) ImageVersion(imageReference string) (string, error) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if version != "" {
|
if err != nil {
|
||||||
return version, 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).
|
// 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
|
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"
|
const versionKey = "IMAGE_VERSION"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -114,41 +106,4 @@ var (
|
|||||||
"/host/etc/os-release",
|
"/host/etc/os-release",
|
||||||
"/host/usr/lib/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",
|
imageReference: "some-reference",
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
"fallback version found": {
|
|
||||||
imageReference: "ami-04a87d302e2509aad",
|
|
||||||
wantVersion: "v2.2.0",
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, tc := range testCases {
|
for name, tc := range testCases {
|
||||||
@ -59,7 +55,7 @@ func TestImageVersion(t *testing.T) {
|
|||||||
fs: &afero.Afero{Fs: fs},
|
fs: &afero.Afero{Fs: fs},
|
||||||
}
|
}
|
||||||
|
|
||||||
version, err := imageInfo.ImageVersion(tc.imageReference)
|
version, err := imageInfo.ImageVersion()
|
||||||
if tc.wantErr {
|
if tc.wantErr {
|
||||||
assert.Error(err)
|
assert.Error(err)
|
||||||
return
|
return
|
||||||
@ -124,46 +120,6 @@ func TestParseOSRelease(t *testing.T) {
|
|||||||
assert.Equal(wantMap, osReleaseMap)
|
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 = `
|
const osRelease = `
|
||||||
# Some comment
|
# Some comment
|
||||||
# Some empty lines below
|
# Some empty lines below
|
||||||
|
@ -24,9 +24,10 @@ import (
|
|||||||
"sigs.k8s.io/controller-runtime/pkg/healthz"
|
"sigs.k8s.io/controller-runtime/pkg/healthz"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/log/zap"
|
"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"
|
"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"
|
updatev1alpha1 "github.com/edgelesssys/constellation/operators/constellation-node-operator/v2/api/v1alpha1"
|
||||||
"github.com/edgelesssys/constellation/operators/constellation-node-operator/v2/controllers"
|
"github.com/edgelesssys/constellation/operators/constellation-node-operator/v2/controllers"
|
||||||
@ -100,6 +101,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
setupLog.Info("CSP does not support upgrades", "csp", csp)
|
setupLog.Info("CSP does not support upgrades", "csp", csp)
|
||||||
|
cspClient = &cloudfake.Client{}
|
||||||
}
|
}
|
||||||
|
|
||||||
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
|
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
|
||||||
@ -127,13 +129,13 @@ func main() {
|
|||||||
}
|
}
|
||||||
defer etcdClient.Close()
|
defer etcdClient.Close()
|
||||||
|
|
||||||
// Create Controllers
|
|
||||||
if csp == "azure" || csp == "gcp" {
|
|
||||||
imageInfo := deploy.NewImageInfo()
|
imageInfo := deploy.NewImageInfo()
|
||||||
if err := deploy.InitialResources(context.Background(), k8sClient, imageInfo, cspClient, os.Getenv(constellationUID)); err != nil {
|
if err := deploy.InitialResources(context.Background(), k8sClient, imageInfo, cspClient, os.Getenv(constellationUID)); err != nil {
|
||||||
setupLog.Error(err, "Unable to deploy initial resources")
|
setupLog.Error(err, "Unable to deploy initial resources")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
// Create Controllers
|
||||||
|
if csp == "azure" || csp == "gcp" {
|
||||||
if err = controllers.NewNodeVersionReconciler(
|
if err = controllers.NewNodeVersionReconciler(
|
||||||
cspClient, etcdClient, mgr.GetClient(), mgr.GetScheme(),
|
cspClient, etcdClient, mgr.GetClient(), mgr.GetScheme(),
|
||||||
).SetupWithManager(mgr); err != nil {
|
).SetupWithManager(mgr); err != nil {
|
||||||
@ -204,7 +206,7 @@ type cspAPI interface {
|
|||||||
SetScalingGroupImage(ctx context.Context, scalingGroupID, imageURI string) error
|
SetScalingGroupImage(ctx context.Context, scalingGroupID, imageURI string) error
|
||||||
// GetScalingGroupName retrieves the name of a scaling group.
|
// GetScalingGroupName retrieves the name of a scaling group.
|
||||||
GetScalingGroupName(scalingGroupID string) (string, error)
|
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)
|
GetAutoscalingGroupName(scalingGroupID string) (string, error)
|
||||||
// ListScalingGroups retrieves a list of scaling groups for the cluster.
|
// ListScalingGroups retrieves a list of scaling groups for the cluster.
|
||||||
ListScalingGroups(ctx context.Context, uid string) (controlPlaneGroupIDs []string, workerGroupIDs []string, err error)
|
ListScalingGroups(ctx context.Context, uid string) (controlPlaneGroupIDs []string, workerGroupIDs []string, err error)
|
||||||
|
Loading…
Reference in New Issue
Block a user