mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-05-03 06:44:50 -04:00
Use tags for UID and role parsing (#242)
* Apply tags to all applicable GCP resources * Move GCP UID and role from VM metadata to labels * Adjust Azure tags to be in line with GCP and AWS * Dont rely on resource name to find resources Signed-off-by: Daniel Weiße <dw@edgeless.systems>
This commit is contained in:
parent
c2814aeddb
commit
b35b74b772
34 changed files with 344 additions and 360 deletions
|
@ -135,7 +135,7 @@ func main() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Failed to marshal PCRs")
|
log.With(zap.Error(err)).Fatalf("Failed to marshal PCRs")
|
||||||
}
|
}
|
||||||
cloudControllerManager, err := gcpcloud.NewCloudControllerManager(metadata)
|
cloudControllerManager, err := gcpcloud.NewCloudControllerManager(ctx, metadata)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With(zap.Error(err)).Fatalf("Failed to create cloud controller manager")
|
log.With(zap.Error(err)).Fatalf("Failed to create cloud controller manager")
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,7 +144,7 @@ func (k *KubeWrapper) InitCluster(
|
||||||
zap.String("nodeName", nodeName),
|
zap.String("nodeName", nodeName),
|
||||||
zap.String("providerID", providerID),
|
zap.String("providerID", providerID),
|
||||||
zap.String("nodeIP", nodeIP),
|
zap.String("nodeIP", nodeIP),
|
||||||
zap.String("controlPlaneEndpointEndpoint", controlPlaneEndpoint),
|
zap.String("controlPlaneEndpoint", controlPlaneEndpoint),
|
||||||
zap.String("podCIDR", subnetworkPodCIDR),
|
zap.String("podCIDR", subnetworkPodCIDR),
|
||||||
).Infof("Setting information for node")
|
).Infof("Setting information for node")
|
||||||
|
|
||||||
|
|
|
@ -194,7 +194,7 @@ module "scale_set_control_plane" {
|
||||||
instance_type = var.instance_type
|
instance_type = var.instance_type
|
||||||
confidential_vm = var.confidential_vm
|
confidential_vm = var.confidential_vm
|
||||||
secure_boot = var.secure_boot
|
secure_boot = var.secure_boot
|
||||||
tags = merge(local.tags, { role = "control-plane" })
|
tags = merge(local.tags, { constellation-role = "control-plane" })
|
||||||
image_id = var.image_id
|
image_id = var.image_id
|
||||||
user_assigned_identity = var.user_assigned_identity
|
user_assigned_identity = var.user_assigned_identity
|
||||||
network_security_group_id = azurerm_network_security_group.security_group.id
|
network_security_group_id = azurerm_network_security_group.security_group.id
|
||||||
|
@ -217,7 +217,7 @@ module "scale_set_worker" {
|
||||||
instance_type = var.instance_type
|
instance_type = var.instance_type
|
||||||
confidential_vm = var.confidential_vm
|
confidential_vm = var.confidential_vm
|
||||||
secure_boot = var.secure_boot
|
secure_boot = var.secure_boot
|
||||||
tags = merge(local.tags, { role = "worker" })
|
tags = merge(local.tags, { constellation-role = "worker" })
|
||||||
image_id = var.image_id
|
image_id = var.image_id
|
||||||
user_assigned_identity = var.user_assigned_identity
|
user_assigned_identity = var.user_assigned_identity
|
||||||
network_security_group_id = azurerm_network_security_group.security_group.id
|
network_security_group_id = azurerm_network_security_group.security_group.id
|
||||||
|
|
|
@ -22,7 +22,7 @@ provider "google" {
|
||||||
locals {
|
locals {
|
||||||
uid = random_id.uid.hex
|
uid = random_id.uid.hex
|
||||||
name = "${var.name}-${local.uid}"
|
name = "${var.name}-${local.uid}"
|
||||||
tag = "constellation-${local.uid}"
|
labels = { constellation-uid = local.uid }
|
||||||
ports_node_range = "30000-32767"
|
ports_node_range = "30000-32767"
|
||||||
ports_kubernetes = "6443"
|
ports_kubernetes = "6443"
|
||||||
ports_bootstrapper = "9000"
|
ports_bootstrapper = "9000"
|
||||||
|
@ -138,6 +138,7 @@ module "instance_group_control_plane" {
|
||||||
{ name = "recovery", port = local.ports_recovery },
|
{ name = "recovery", port = local.ports_recovery },
|
||||||
var.debug ? [{ name = "debugd", port = local.ports_debugd }] : [],
|
var.debug ? [{ name = "debugd", port = local.ports_debugd }] : [],
|
||||||
])
|
])
|
||||||
|
labels = local.labels
|
||||||
}
|
}
|
||||||
|
|
||||||
module "instance_group_worker" {
|
module "instance_group_worker" {
|
||||||
|
@ -154,6 +155,7 @@ module "instance_group_worker" {
|
||||||
subnetwork = google_compute_subnetwork.vpc_subnetwork.id
|
subnetwork = google_compute_subnetwork.vpc_subnetwork.id
|
||||||
kube_env = local.kube_env
|
kube_env = local.kube_env
|
||||||
debug = var.debug
|
debug = var.debug
|
||||||
|
labels = local.labels
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_compute_global_address" "loadbalancer_ip" {
|
resource "google_compute_global_address" "loadbalancer_ip" {
|
||||||
|
@ -168,9 +170,7 @@ module "loadbalancer_kube" {
|
||||||
backend_instance_group = module.instance_group_control_plane.instance_group
|
backend_instance_group = module.instance_group_control_plane.instance_group
|
||||||
ip_address = google_compute_global_address.loadbalancer_ip.self_link
|
ip_address = google_compute_global_address.loadbalancer_ip.self_link
|
||||||
port = local.ports_kubernetes
|
port = local.ports_kubernetes
|
||||||
frontend_labels = {
|
frontend_labels = merge(local.labels, { constellation-use = "kubernetes" })
|
||||||
constellation-uid = local.uid
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module "loadbalancer_boot" {
|
module "loadbalancer_boot" {
|
||||||
|
@ -181,6 +181,7 @@ module "loadbalancer_boot" {
|
||||||
backend_instance_group = module.instance_group_control_plane.instance_group
|
backend_instance_group = module.instance_group_control_plane.instance_group
|
||||||
ip_address = google_compute_global_address.loadbalancer_ip.self_link
|
ip_address = google_compute_global_address.loadbalancer_ip.self_link
|
||||||
port = local.ports_bootstrapper
|
port = local.ports_bootstrapper
|
||||||
|
frontend_labels = merge(local.labels, { constellation-use = "bootstrapper" })
|
||||||
}
|
}
|
||||||
|
|
||||||
module "loadbalancer_verify" {
|
module "loadbalancer_verify" {
|
||||||
|
@ -191,6 +192,7 @@ module "loadbalancer_verify" {
|
||||||
backend_instance_group = module.instance_group_control_plane.instance_group
|
backend_instance_group = module.instance_group_control_plane.instance_group
|
||||||
ip_address = google_compute_global_address.loadbalancer_ip.self_link
|
ip_address = google_compute_global_address.loadbalancer_ip.self_link
|
||||||
port = local.ports_verify
|
port = local.ports_verify
|
||||||
|
frontend_labels = merge(local.labels, { constellation-use = "verify" })
|
||||||
}
|
}
|
||||||
|
|
||||||
module "loadbalancer_konnectivity" {
|
module "loadbalancer_konnectivity" {
|
||||||
|
@ -201,6 +203,7 @@ module "loadbalancer_konnectivity" {
|
||||||
backend_instance_group = module.instance_group_control_plane.instance_group
|
backend_instance_group = module.instance_group_control_plane.instance_group
|
||||||
ip_address = google_compute_global_address.loadbalancer_ip.self_link
|
ip_address = google_compute_global_address.loadbalancer_ip.self_link
|
||||||
port = local.ports_konnectivity
|
port = local.ports_konnectivity
|
||||||
|
frontend_labels = merge(local.labels, { constellation-use = "konnectivity" })
|
||||||
}
|
}
|
||||||
|
|
||||||
module "loadbalancer_recovery" {
|
module "loadbalancer_recovery" {
|
||||||
|
@ -211,6 +214,7 @@ module "loadbalancer_recovery" {
|
||||||
backend_instance_group = module.instance_group_control_plane.instance_group
|
backend_instance_group = module.instance_group_control_plane.instance_group
|
||||||
ip_address = google_compute_global_address.loadbalancer_ip.self_link
|
ip_address = google_compute_global_address.loadbalancer_ip.self_link
|
||||||
port = local.ports_recovery
|
port = local.ports_recovery
|
||||||
|
frontend_labels = merge(local.labels, { constellation-use = "recovery" })
|
||||||
}
|
}
|
||||||
|
|
||||||
module "loadbalancer_debugd" {
|
module "loadbalancer_debugd" {
|
||||||
|
@ -222,4 +226,5 @@ module "loadbalancer_debugd" {
|
||||||
backend_instance_group = module.instance_group_control_plane.instance_group
|
backend_instance_group = module.instance_group_control_plane.instance_group
|
||||||
ip_address = google_compute_global_address.loadbalancer_ip.self_link
|
ip_address = google_compute_global_address.loadbalancer_ip.self_link
|
||||||
port = local.ports_debugd
|
port = local.ports_debugd
|
||||||
|
frontend_labels = merge(local.labels, { constellation-use = "debugd" })
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ resource "google_compute_instance_template" "template" {
|
||||||
name = local.name
|
name = local.name
|
||||||
machine_type = var.instance_type
|
machine_type = var.instance_type
|
||||||
tags = ["constellation-${var.uid}"]
|
tags = ["constellation-${var.uid}"]
|
||||||
|
labels = merge(var.labels, { constellation-role = local.role_dashed })
|
||||||
|
|
||||||
confidential_instance_config {
|
confidential_instance_config {
|
||||||
enable_confidential_compute = true
|
enable_confidential_compute = true
|
||||||
|
@ -41,8 +42,6 @@ resource "google_compute_instance_template" "template" {
|
||||||
|
|
||||||
metadata = {
|
metadata = {
|
||||||
kube-env = var.kube_env
|
kube-env = var.kube_env
|
||||||
constellation-uid = var.uid
|
|
||||||
constellation-role = var.role
|
|
||||||
serial-port-enable = var.debug ? "TRUE" : "FALSE"
|
serial-port-enable = var.debug ? "TRUE" : "FALSE"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,12 @@ variable "uid" {
|
||||||
description = "UID of the cluster. This is used for tags."
|
description = "UID of the cluster. This is used for tags."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "labels" {
|
||||||
|
type = map(string)
|
||||||
|
default = {}
|
||||||
|
description = "Labels to apply to the instance group."
|
||||||
|
}
|
||||||
|
|
||||||
variable "instance_type" {
|
variable "instance_type" {
|
||||||
type = string
|
type = string
|
||||||
description = "Instance type for the nodes."
|
description = "Instance type for the nodes."
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
|
"github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
|
||||||
logs "github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs"
|
logs "github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs"
|
||||||
"github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs/types"
|
"github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs/types"
|
||||||
|
"github.com/edgelesssys/constellation/v2/internal/cloud"
|
||||||
"k8s.io/utils/clock"
|
"k8s.io/utils/clock"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -147,7 +148,7 @@ func (l *Logger) createStream(ctx context.Context, imds imdsAPI) error {
|
||||||
l.streamName = name
|
l.streamName = name
|
||||||
|
|
||||||
// find log group with matching Constellation UID
|
// find log group with matching Constellation UID
|
||||||
uid, err := readInstanceTag(ctx, imds, tagUID)
|
uid, err := readInstanceTag(ctx, imds, cloud.TagUID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -162,7 +163,7 @@ func (l *Logger) createStream(ctx context.Context, imds imdsAPI) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue // we may not have permission to read the tags of a log group outside the Constellation scope
|
continue // we may not have permission to read the tags of a log group outside the Constellation scope
|
||||||
}
|
}
|
||||||
if tags.Tags[tagUID] == uid {
|
if tags.Tags[cloud.TagUID] == uid {
|
||||||
l.groupName = *group.LogGroupName
|
l.groupName = *group.LogGroupName
|
||||||
res.NextToken = nil // stop pagination
|
res.NextToken = nil // stop pagination
|
||||||
break
|
break
|
||||||
|
|
|
@ -17,6 +17,7 @@ import (
|
||||||
"github.com/aws/aws-sdk-go-v2/aws"
|
"github.com/aws/aws-sdk-go-v2/aws"
|
||||||
logs "github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs"
|
logs "github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs"
|
||||||
"github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs/types"
|
"github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs/types"
|
||||||
|
"github.com/edgelesssys/constellation/v2/internal/cloud"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"go.uber.org/goleak"
|
"go.uber.org/goleak"
|
||||||
|
@ -41,7 +42,7 @@ func TestCreateStream(t *testing.T) {
|
||||||
imds: &stubIMDS{
|
imds: &stubIMDS{
|
||||||
tags: map[string]string{
|
tags: map[string]string{
|
||||||
tagName: "test-instance",
|
tagName: "test-instance",
|
||||||
tagUID: "uid",
|
cloud.TagUID: "uid",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
logs: &stubLogs{
|
logs: &stubLogs{
|
||||||
|
@ -50,7 +51,7 @@ func TestCreateStream(t *testing.T) {
|
||||||
{LogGroupName: aws.String("test-group")},
|
{LogGroupName: aws.String("test-group")},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
listTags: map[string]map[string]string{"test-group": {tagUID: "uid"}},
|
listTags: map[string]map[string]string{"test-group": {cloud.TagUID: "uid"}},
|
||||||
},
|
},
|
||||||
wantStream: "test-instance",
|
wantStream: "test-instance",
|
||||||
wantGroup: "test-group",
|
wantGroup: "test-group",
|
||||||
|
@ -59,7 +60,7 @@ func TestCreateStream(t *testing.T) {
|
||||||
imds: &stubIMDS{
|
imds: &stubIMDS{
|
||||||
tags: map[string]string{
|
tags: map[string]string{
|
||||||
tagName: "test-instance",
|
tagName: "test-instance",
|
||||||
tagUID: "uid",
|
cloud.TagUID: "uid",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
logs: &stubLogs{
|
logs: &stubLogs{
|
||||||
|
@ -89,13 +90,13 @@ func TestCreateStream(t *testing.T) {
|
||||||
"some-tag": "random-tag",
|
"some-tag": "random-tag",
|
||||||
},
|
},
|
||||||
"other-group": {
|
"other-group": {
|
||||||
tagUID: "other-uid",
|
cloud.TagUID: "other-uid",
|
||||||
},
|
},
|
||||||
"another-group": {
|
"another-group": {
|
||||||
"some-tag": "uid",
|
"some-tag": "uid",
|
||||||
},
|
},
|
||||||
"test-group": {
|
"test-group": {
|
||||||
tagUID: "uid",
|
cloud.TagUID: "uid",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -106,7 +107,7 @@ func TestCreateStream(t *testing.T) {
|
||||||
imds: &stubIMDS{
|
imds: &stubIMDS{
|
||||||
tags: map[string]string{
|
tags: map[string]string{
|
||||||
tagName: "test-instance",
|
tagName: "test-instance",
|
||||||
tagUID: "uid",
|
cloud.TagUID: "uid",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
logs: &stubLogs{
|
logs: &stubLogs{
|
||||||
|
@ -115,7 +116,7 @@ func TestCreateStream(t *testing.T) {
|
||||||
{LogGroupName: aws.String("test-group")},
|
{LogGroupName: aws.String("test-group")},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
listTags: map[string]map[string]string{"test-group": {tagUID: "uid"}},
|
listTags: map[string]map[string]string{"test-group": {cloud.TagUID: "uid"}},
|
||||||
createErr: &types.ResourceAlreadyExistsException{},
|
createErr: &types.ResourceAlreadyExistsException{},
|
||||||
},
|
},
|
||||||
wantStream: "test-instance",
|
wantStream: "test-instance",
|
||||||
|
@ -125,7 +126,7 @@ func TestCreateStream(t *testing.T) {
|
||||||
imds: &stubIMDS{
|
imds: &stubIMDS{
|
||||||
tags: map[string]string{
|
tags: map[string]string{
|
||||||
tagName: "test-instance",
|
tagName: "test-instance",
|
||||||
tagUID: "uid",
|
cloud.TagUID: "uid",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
logs: &stubLogs{
|
logs: &stubLogs{
|
||||||
|
@ -134,7 +135,7 @@ func TestCreateStream(t *testing.T) {
|
||||||
{LogGroupName: aws.String("test-group")},
|
{LogGroupName: aws.String("test-group")},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
listTags: map[string]map[string]string{"test-group": {tagUID: "uid"}},
|
listTags: map[string]map[string]string{"test-group": {cloud.TagUID: "uid"}},
|
||||||
createErr: someErr,
|
createErr: someErr,
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
|
@ -151,14 +152,14 @@ func TestCreateStream(t *testing.T) {
|
||||||
{LogGroupName: aws.String("test-group")},
|
{LogGroupName: aws.String("test-group")},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
listTags: map[string]map[string]string{"test-group": {tagUID: "uid"}},
|
listTags: map[string]map[string]string{"test-group": {cloud.TagUID: "uid"}},
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
"missing name tag": {
|
"missing name tag": {
|
||||||
imds: &stubIMDS{
|
imds: &stubIMDS{
|
||||||
tags: map[string]string{
|
tags: map[string]string{
|
||||||
tagUID: "uid",
|
cloud.TagUID: "uid",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
logs: &stubLogs{
|
logs: &stubLogs{
|
||||||
|
@ -167,7 +168,7 @@ func TestCreateStream(t *testing.T) {
|
||||||
{LogGroupName: aws.String("test-group")},
|
{LogGroupName: aws.String("test-group")},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
listTags: map[string]map[string]string{"test-group": {tagUID: "uid"}},
|
listTags: map[string]map[string]string{"test-group": {cloud.TagUID: "uid"}},
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
|
@ -175,12 +176,12 @@ func TestCreateStream(t *testing.T) {
|
||||||
imds: &stubIMDS{
|
imds: &stubIMDS{
|
||||||
tags: map[string]string{
|
tags: map[string]string{
|
||||||
tagName: "test-instance",
|
tagName: "test-instance",
|
||||||
tagUID: "uid",
|
cloud.TagUID: "uid",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
logs: &stubLogs{
|
logs: &stubLogs{
|
||||||
describeErr: someErr,
|
describeErr: someErr,
|
||||||
listTags: map[string]map[string]string{"test-group": {tagUID: "uid"}},
|
listTags: map[string]map[string]string{"test-group": {cloud.TagUID: "uid"}},
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
|
@ -188,12 +189,12 @@ func TestCreateStream(t *testing.T) {
|
||||||
imds: &stubIMDS{
|
imds: &stubIMDS{
|
||||||
tags: map[string]string{
|
tags: map[string]string{
|
||||||
tagName: "test-instance",
|
tagName: "test-instance",
|
||||||
tagUID: "uid",
|
cloud.TagUID: "uid",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
logs: &stubLogs{
|
logs: &stubLogs{
|
||||||
describeRes1: &logs.DescribeLogGroupsOutput{},
|
describeRes1: &logs.DescribeLogGroupsOutput{},
|
||||||
listTags: map[string]map[string]string{"test-group": {tagUID: "uid"}},
|
listTags: map[string]map[string]string{"test-group": {cloud.TagUID: "uid"}},
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
|
|
|
@ -17,14 +17,13 @@ import (
|
||||||
"github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
|
"github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
|
||||||
"github.com/aws/aws-sdk-go-v2/service/ec2"
|
"github.com/aws/aws-sdk-go-v2/service/ec2"
|
||||||
"github.com/aws/aws-sdk-go-v2/service/ec2/types"
|
"github.com/aws/aws-sdk-go-v2/service/ec2/types"
|
||||||
|
"github.com/edgelesssys/constellation/v2/internal/cloud"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
|
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/role"
|
"github.com/edgelesssys/constellation/v2/internal/role"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
tagName = "Name"
|
tagName = "Name"
|
||||||
tagRole = "constellation-role"
|
|
||||||
tagUID = "constellation-uid"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ec2API interface {
|
type ec2API interface {
|
||||||
|
@ -62,7 +61,7 @@ func (m *Metadata) Supported() bool {
|
||||||
|
|
||||||
// List retrieves all instances belonging to the current Constellation.
|
// List retrieves all instances belonging to the current Constellation.
|
||||||
func (m *Metadata) List(ctx context.Context) ([]metadata.InstanceMetadata, error) {
|
func (m *Metadata) List(ctx context.Context) ([]metadata.InstanceMetadata, error) {
|
||||||
uid, err := readInstanceTag(ctx, m.imds, tagUID)
|
uid, err := readInstanceTag(ctx, m.imds, cloud.TagUID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("retrieving uid tag: %w", err)
|
return nil, fmt.Errorf("retrieving uid tag: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -85,7 +84,7 @@ func (m *Metadata) Self(ctx context.Context) (metadata.InstanceMetadata, error)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return metadata.InstanceMetadata{}, fmt.Errorf("retrieving name tag: %w", err)
|
return metadata.InstanceMetadata{}, fmt.Errorf("retrieving name tag: %w", err)
|
||||||
}
|
}
|
||||||
instanceRole, err := readInstanceTag(ctx, m.imds, tagRole)
|
instanceRole, err := readInstanceTag(ctx, m.imds, cloud.TagRole)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return metadata.InstanceMetadata{}, fmt.Errorf("retrieving role tag: %w", err)
|
return metadata.InstanceMetadata{}, fmt.Errorf("retrieving role tag: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -128,7 +127,7 @@ func (m *Metadata) GetInstance(ctx context.Context, providerID string) (metadata
|
||||||
|
|
||||||
// UID returns the UID of the Constellation.
|
// UID returns the UID of the Constellation.
|
||||||
func (m *Metadata) UID(ctx context.Context) (string, error) {
|
func (m *Metadata) UID(ctx context.Context) (string, error) {
|
||||||
return readInstanceTag(ctx, m.imds, tagUID)
|
return readInstanceTag(ctx, m.imds, cloud.TagUID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SupportsLoadBalancer returns true if the cloud provider supports load balancers.
|
// SupportsLoadBalancer returns true if the cloud provider supports load balancers.
|
||||||
|
@ -151,7 +150,7 @@ func (m *Metadata) getAllInstancesInGroup(ctx context.Context, uid string) ([]ty
|
||||||
instanceReq := &ec2.DescribeInstancesInput{
|
instanceReq := &ec2.DescribeInstancesInput{
|
||||||
Filters: []types.Filter{
|
Filters: []types.Filter{
|
||||||
{
|
{
|
||||||
Name: aws.String("tag:" + tagUID),
|
Name: aws.String("tag:" + cloud.TagUID),
|
||||||
Values: []string{uid},
|
Values: []string{uid},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -199,7 +198,7 @@ func (m *Metadata) convertToMetadataInstance(ec2Instances []types.Instance) ([]m
|
||||||
}
|
}
|
||||||
newInstance.Name = name
|
newInstance.Name = name
|
||||||
|
|
||||||
instanceRole, err := findTag(ec2Instance.Tags, tagRole)
|
instanceRole, err := findTag(ec2Instance.Tags, cloud.TagRole)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("retrieving tag for instance %s: %w", *ec2Instance.InstanceId, err)
|
return nil, fmt.Errorf("retrieving tag for instance %s: %w", *ec2Instance.InstanceId, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ import (
|
||||||
"github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
|
"github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
|
||||||
"github.com/aws/aws-sdk-go-v2/service/ec2"
|
"github.com/aws/aws-sdk-go-v2/service/ec2"
|
||||||
"github.com/aws/aws-sdk-go-v2/service/ec2/types"
|
"github.com/aws/aws-sdk-go-v2/service/ec2/types"
|
||||||
|
"github.com/edgelesssys/constellation/v2/internal/cloud"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
|
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/role"
|
"github.com/edgelesssys/constellation/v2/internal/role"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -42,7 +43,7 @@ func TestSelf(t *testing.T) {
|
||||||
},
|
},
|
||||||
tags: map[string]string{
|
tags: map[string]string{
|
||||||
tagName: "test-instance",
|
tagName: "test-instance",
|
||||||
tagRole: "controlplane",
|
cloud.TagRole: "controlplane",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantSelf: metadata.InstanceMetadata{
|
wantSelf: metadata.InstanceMetadata{
|
||||||
|
@ -63,7 +64,7 @@ func TestSelf(t *testing.T) {
|
||||||
},
|
},
|
||||||
tags: map[string]string{
|
tags: map[string]string{
|
||||||
tagName: "test-instance",
|
tagName: "test-instance",
|
||||||
tagRole: "worker",
|
cloud.TagRole: "worker",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantSelf: metadata.InstanceMetadata{
|
wantSelf: metadata.InstanceMetadata{
|
||||||
|
@ -78,7 +79,7 @@ func TestSelf(t *testing.T) {
|
||||||
getInstanceIdentityDocumentErr: someErr,
|
getInstanceIdentityDocumentErr: someErr,
|
||||||
tags: map[string]string{
|
tags: map[string]string{
|
||||||
tagName: "test-instance",
|
tagName: "test-instance",
|
||||||
tagRole: "controlplane",
|
cloud.TagRole: "controlplane",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
|
@ -106,7 +107,7 @@ func TestSelf(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
tags: map[string]string{
|
tags: map[string]string{
|
||||||
tagRole: "controlplane",
|
cloud.TagRole: "controlplane",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
|
@ -165,11 +166,11 @@ func TestList(t *testing.T) {
|
||||||
Value: aws.String("name-1"),
|
Value: aws.String("name-1"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: aws.String(tagRole),
|
Key: aws.String(cloud.TagRole),
|
||||||
Value: aws.String("controlplane"),
|
Value: aws.String("controlplane"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: aws.String(tagUID),
|
Key: aws.String(cloud.TagUID),
|
||||||
Value: aws.String("uid"),
|
Value: aws.String("uid"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -187,11 +188,11 @@ func TestList(t *testing.T) {
|
||||||
Value: aws.String("name-2"),
|
Value: aws.String("name-2"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: aws.String(tagRole),
|
Key: aws.String(cloud.TagRole),
|
||||||
Value: aws.String("worker"),
|
Value: aws.String("worker"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: aws.String(tagUID),
|
Key: aws.String(cloud.TagUID),
|
||||||
Value: aws.String("uid"),
|
Value: aws.String("uid"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -210,7 +211,7 @@ func TestList(t *testing.T) {
|
||||||
"success single page": {
|
"success single page": {
|
||||||
imds: &stubIMDS{
|
imds: &stubIMDS{
|
||||||
tags: map[string]string{
|
tags: map[string]string{
|
||||||
tagUID: "uid",
|
cloud.TagUID: "uid",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ec2: &stubEC2{
|
ec2: &stubEC2{
|
||||||
|
@ -234,7 +235,7 @@ func TestList(t *testing.T) {
|
||||||
"success multiple pages": {
|
"success multiple pages": {
|
||||||
imds: &stubIMDS{
|
imds: &stubIMDS{
|
||||||
tags: map[string]string{
|
tags: map[string]string{
|
||||||
tagUID: "uid",
|
cloud.TagUID: "uid",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ec2: &stubEC2{
|
ec2: &stubEC2{
|
||||||
|
@ -255,11 +256,11 @@ func TestList(t *testing.T) {
|
||||||
Value: aws.String("name-3"),
|
Value: aws.String("name-3"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: aws.String(tagRole),
|
Key: aws.String(cloud.TagRole),
|
||||||
Value: aws.String("worker"),
|
Value: aws.String("worker"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: aws.String(tagUID),
|
Key: aws.String(cloud.TagUID),
|
||||||
Value: aws.String("uid"),
|
Value: aws.String("uid"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -302,7 +303,7 @@ func TestList(t *testing.T) {
|
||||||
"describe instances fails": {
|
"describe instances fails": {
|
||||||
imds: &stubIMDS{
|
imds: &stubIMDS{
|
||||||
tags: map[string]string{
|
tags: map[string]string{
|
||||||
tagUID: "uid",
|
cloud.TagUID: "uid",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ec2: &stubEC2{
|
ec2: &stubEC2{
|
||||||
|
@ -350,7 +351,7 @@ func TestConvertToMetadataInstance(t *testing.T) {
|
||||||
Value: aws.String("name-1"),
|
Value: aws.String("name-1"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: aws.String(tagRole),
|
Key: aws.String(cloud.TagRole),
|
||||||
Value: aws.String("controlplane"),
|
Value: aws.String("controlplane"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -377,7 +378,7 @@ func TestConvertToMetadataInstance(t *testing.T) {
|
||||||
Value: aws.String("name-1"),
|
Value: aws.String("name-1"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: aws.String(tagRole),
|
Key: aws.String(cloud.TagRole),
|
||||||
Value: aws.String("controlplane"),
|
Value: aws.String("controlplane"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -417,7 +418,7 @@ func TestConvertToMetadataInstance(t *testing.T) {
|
||||||
Value: aws.String("name-1"),
|
Value: aws.String("name-1"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: aws.String(tagRole),
|
Key: aws.String(cloud.TagRole),
|
||||||
Value: aws.String("controlplane"),
|
Value: aws.String("controlplane"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -439,7 +440,7 @@ func TestConvertToMetadataInstance(t *testing.T) {
|
||||||
Value: aws.String("name-1"),
|
Value: aws.String("name-1"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: aws.String(tagRole),
|
Key: aws.String(cloud.TagRole),
|
||||||
Value: aws.String("controlplane"),
|
Value: aws.String("controlplane"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -458,7 +459,7 @@ func TestConvertToMetadataInstance(t *testing.T) {
|
||||||
},
|
},
|
||||||
Tags: []types.Tag{
|
Tags: []types.Tag{
|
||||||
{
|
{
|
||||||
Key: aws.String(tagRole),
|
Key: aws.String(cloud.TagRole),
|
||||||
Value: aws.String("controlplane"),
|
Value: aws.String("controlplane"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/edgelesssys/constellation/v2/internal/cloud"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/role"
|
"github.com/edgelesssys/constellation/v2/internal/role"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -91,7 +92,7 @@ func (c *imdsClient) UID(ctx context.Context) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tag := range c.cache.Compute.Tags {
|
for _, tag := range c.cache.Compute.Tags {
|
||||||
if tag.Name == "constellation-uid" {
|
if tag.Name == cloud.TagUID {
|
||||||
return tag.Value, nil
|
return tag.Value, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,7 +108,7 @@ func (c *imdsClient) Role(ctx context.Context) (role.Role, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tag := range c.cache.Compute.Tags {
|
for _, tag := range c.cache.Compute.Tags {
|
||||||
if tag.Name == "role" {
|
if tag.Name == cloud.TagRole {
|
||||||
return role.FromString(tag.Value), nil
|
return role.FromString(tag.Value), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/edgelesssys/constellation/v2/internal/cloud"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/role"
|
"github.com/edgelesssys/constellation/v2/internal/role"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"google.golang.org/grpc/test/bufconn"
|
"google.golang.org/grpc/test/bufconn"
|
||||||
|
@ -22,8 +23,8 @@ import (
|
||||||
|
|
||||||
func TestIMDSClient(t *testing.T) {
|
func TestIMDSClient(t *testing.T) {
|
||||||
uidTags := []metadataTag{
|
uidTags := []metadataTag{
|
||||||
{Name: "constellation-uid", Value: "uid"},
|
{Name: cloud.TagUID, Value: "uid"},
|
||||||
{Name: "role", Value: "worker"},
|
{Name: cloud.TagRole, Value: "worker"},
|
||||||
}
|
}
|
||||||
response := metadataResponse{
|
response := metadataResponse{
|
||||||
Compute: metadataResponseCompute{
|
Compute: metadataResponseCompute{
|
||||||
|
@ -48,14 +49,14 @@ func TestIMDSClient(t *testing.T) {
|
||||||
Compute: metadataResponseCompute{
|
Compute: metadataResponseCompute{
|
||||||
ResourceID: "resource-id",
|
ResourceID: "resource-id",
|
||||||
ResourceGroup: "resource-group",
|
ResourceGroup: "resource-group",
|
||||||
Tags: []metadataTag{{Name: "role", Value: "worker"}},
|
Tags: []metadataTag{{Name: cloud.TagRole, Value: "worker"}},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
responseWithoutRole := metadataResponse{
|
responseWithoutRole := metadataResponse{
|
||||||
Compute: metadataResponseCompute{
|
Compute: metadataResponseCompute{
|
||||||
ResourceID: "resource-id",
|
ResourceID: "resource-id",
|
||||||
ResourceGroup: "resource-group",
|
ResourceGroup: "resource-group",
|
||||||
Tags: []metadataTag{{Name: "constellation-uid", Value: "uid"}},
|
Tags: []metadataTag{{Name: cloud.TagUID, Value: "uid"}},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ import (
|
||||||
armcomputev2 "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v2"
|
armcomputev2 "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v2"
|
||||||
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork"
|
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork"
|
||||||
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources"
|
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources"
|
||||||
|
"github.com/edgelesssys/constellation/v2/internal/cloud"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
|
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -301,7 +302,7 @@ func (m *Metadata) getAppInsights(ctx context.Context) (*armapplicationinsights.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
tag, ok := component.Tags["constellation-uid"]
|
tag, ok := component.Tags[cloud.TagUID]
|
||||||
if !ok || tag == nil {
|
if !ok || tag == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
|
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
|
||||||
armcomputev2 "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v2"
|
armcomputev2 "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v2"
|
||||||
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork"
|
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork"
|
||||||
|
"github.com/edgelesssys/constellation/v2/internal/cloud"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
|
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/role"
|
"github.com/edgelesssys/constellation/v2/internal/role"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -654,8 +655,8 @@ func newScaleSetsStub() *stubScaleSetsAPI {
|
||||||
list: []armcomputev2.VirtualMachineScaleSet{{
|
list: []armcomputev2.VirtualMachineScaleSet{{
|
||||||
Name: to.Ptr("scale-set-name"),
|
Name: to.Ptr("scale-set-name"),
|
||||||
Tags: map[string]*string{
|
Tags: map[string]*string{
|
||||||
"constellation-uid": to.Ptr("uid"),
|
cloud.TagUID: to.Ptr("uid"),
|
||||||
"role": to.Ptr("worker"),
|
cloud.TagRole: to.Ptr("worker"),
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
|
@ -691,8 +692,8 @@ func newVirtualMachineScaleSetsVMsStub() *stubVirtualMachineScaleSetVMsAPI {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Tags: map[string]*string{
|
Tags: map[string]*string{
|
||||||
"constellation-uid": to.Ptr("uid"),
|
cloud.TagUID: to.Ptr("uid"),
|
||||||
"role": to.Ptr("worker"),
|
cloud.TagRole: to.Ptr("worker"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
pager: &stubVirtualMachineScaleSetVMPager{
|
pager: &stubVirtualMachineScaleSetVMPager{
|
||||||
|
@ -724,8 +725,8 @@ func newVirtualMachineScaleSetsVMsStub() *stubVirtualMachineScaleSetVMsAPI {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Tags: map[string]*string{
|
Tags: map[string]*string{
|
||||||
"constellation-uid": to.Ptr("uid"),
|
cloud.TagUID: to.Ptr("uid"),
|
||||||
"role": to.Ptr("worker"),
|
cloud.TagRole: to.Ptr("worker"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
armcomputev2 "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v2"
|
armcomputev2 "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v2"
|
||||||
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork"
|
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/azureshared"
|
"github.com/edgelesssys/constellation/v2/internal/azureshared"
|
||||||
|
"github.com/edgelesssys/constellation/v2/internal/cloud"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
|
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/role"
|
"github.com/edgelesssys/constellation/v2/internal/role"
|
||||||
)
|
)
|
||||||
|
@ -117,7 +118,7 @@ func extractScaleSetVMRole(tags map[string]*string) role.Role {
|
||||||
if tags == nil {
|
if tags == nil {
|
||||||
return role.Unknown
|
return role.Unknown
|
||||||
}
|
}
|
||||||
roleStr, ok := tags["role"]
|
roleStr, ok := tags[cloud.TagRole]
|
||||||
if !ok {
|
if !ok {
|
||||||
return role.Unknown
|
return role.Unknown
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
|
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
|
||||||
armcomputev2 "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v2"
|
armcomputev2 "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v2"
|
||||||
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork"
|
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork"
|
||||||
|
"github.com/edgelesssys/constellation/v2/internal/cloud"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
|
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/role"
|
"github.com/edgelesssys/constellation/v2/internal/role"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -223,15 +224,15 @@ func TestExtractScaleSetVMRole(t *testing.T) {
|
||||||
wantRole role.Role
|
wantRole role.Role
|
||||||
}{
|
}{
|
||||||
"control-plane role": {
|
"control-plane role": {
|
||||||
tags: map[string]*string{"role": to.Ptr("control-plane")},
|
tags: map[string]*string{cloud.TagRole: to.Ptr("control-plane")},
|
||||||
wantRole: role.ControlPlane,
|
wantRole: role.ControlPlane,
|
||||||
},
|
},
|
||||||
"worker role": {
|
"worker role": {
|
||||||
tags: map[string]*string{"role": to.Ptr("worker")},
|
tags: map[string]*string{cloud.TagRole: to.Ptr("worker")},
|
||||||
wantRole: role.Worker,
|
wantRole: role.Worker,
|
||||||
},
|
},
|
||||||
"unknown role": {
|
"unknown role": {
|
||||||
tags: map[string]*string{"role": to.Ptr("foo")},
|
tags: map[string]*string{cloud.TagRole: to.Ptr("foo")},
|
||||||
wantRole: role.Unknown,
|
wantRole: role.Unknown,
|
||||||
},
|
},
|
||||||
"no role": {
|
"no role": {
|
||||||
|
@ -239,7 +240,7 @@ func TestExtractScaleSetVMRole(t *testing.T) {
|
||||||
wantRole: role.Unknown,
|
wantRole: role.Unknown,
|
||||||
},
|
},
|
||||||
"nil role": {
|
"nil role": {
|
||||||
tags: map[string]*string{"role": nil},
|
tags: map[string]*string{cloud.TagRole: nil},
|
||||||
wantRole: role.Unknown,
|
wantRole: role.Unknown,
|
||||||
},
|
},
|
||||||
"nil tags": {
|
"nil tags": {
|
||||||
|
@ -280,7 +281,7 @@ func newListContainingNilScaleSetVirtualMachinesStub() *stubVirtualMachineScaleS
|
||||||
ID: to.Ptr("/subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/scale-set-name/virtualMachines/instance-id"),
|
ID: to.Ptr("/subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/scale-set-name/virtualMachines/instance-id"),
|
||||||
InstanceID: to.Ptr("instance-id"),
|
InstanceID: to.Ptr("instance-id"),
|
||||||
Tags: map[string]*string{
|
Tags: map[string]*string{
|
||||||
"role": to.Ptr("worker"),
|
cloud.TagRole: to.Ptr("worker"),
|
||||||
},
|
},
|
||||||
Properties: &armcomputev2.VirtualMachineScaleSetVMProperties{
|
Properties: &armcomputev2.VirtualMachineScaleSetVMProperties{
|
||||||
NetworkProfile: &armcomputev2.NetworkProfile{
|
NetworkProfile: &armcomputev2.NetworkProfile{
|
||||||
|
|
14
internal/cloud/cloud.go
Normal file
14
internal/cloud/cloud.go
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) Edgeless Systems GmbH
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cloud
|
||||||
|
|
||||||
|
const (
|
||||||
|
// TagRole is the tag/label key used to identify the role of a node.
|
||||||
|
TagRole = "constellation-role"
|
||||||
|
// TagUID is the tag/label key used to identify the UID of a cluster.
|
||||||
|
TagUID = "constellation-uid"
|
||||||
|
)
|
|
@ -35,6 +35,7 @@ type forwardingRulesAPI interface {
|
||||||
|
|
||||||
type metadataAPI interface {
|
type metadataAPI interface {
|
||||||
InstanceAttributeValue(attr string) (string, error)
|
InstanceAttributeValue(attr string) (string, error)
|
||||||
|
InstanceID() (string, error)
|
||||||
ProjectID() (string, error)
|
ProjectID() (string, error)
|
||||||
Zone() (string, error)
|
Zone() (string, error)
|
||||||
InstanceName() (string, error)
|
InstanceName() (string, error)
|
||||||
|
|
|
@ -26,8 +26,8 @@ type CloudControllerManager struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCloudControllerManager returns an initialized cloud controller manager configuration struct for GCP.
|
// NewCloudControllerManager returns an initialized cloud controller manager configuration struct for GCP.
|
||||||
func NewCloudControllerManager(metadata *Metadata) (*CloudControllerManager, error) {
|
func NewCloudControllerManager(ctx context.Context, metadata *Metadata) (*CloudControllerManager, error) {
|
||||||
uid, err := metadata.api.UID()
|
uid, err := metadata.api.UID(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("getting uid from metadata: %w", err)
|
return nil, fmt.Errorf("getting uid from metadata: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,10 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
compute "cloud.google.com/go/compute/apiv1"
|
compute "cloud.google.com/go/compute/apiv1"
|
||||||
|
"github.com/edgelesssys/constellation/v2/internal/cloud"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
|
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/gcpshared"
|
"github.com/edgelesssys/constellation/v2/internal/gcpshared"
|
||||||
|
"github.com/edgelesssys/constellation/v2/internal/role"
|
||||||
"google.golang.org/api/iterator"
|
"google.golang.org/api/iterator"
|
||||||
computepb "google.golang.org/genproto/googleapis/cloud/compute/v1"
|
computepb "google.golang.org/genproto/googleapis/cloud/compute/v1"
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
|
@ -24,7 +26,6 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
gcpSSHMetadataKey = "ssh-keys"
|
gcpSSHMetadataKey = "ssh-keys"
|
||||||
constellationUIDMetadataKey = "constellation-uid"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var zoneFromRegionRegex = regexp.MustCompile("([a-z]*-[a-z]*[0-9])")
|
var zoneFromRegionRegex = regexp.MustCompile("([a-z]*-[a-z]*[0-9])")
|
||||||
|
@ -61,11 +62,12 @@ func NewClient(ctx context.Context) (*Client, error) {
|
||||||
|
|
||||||
// RetrieveInstances returns list of instances including their ips and metadata.
|
// RetrieveInstances returns list of instances including their ips and metadata.
|
||||||
func (c *Client) RetrieveInstances(ctx context.Context, project, zone string) ([]metadata.InstanceMetadata, error) {
|
func (c *Client) RetrieveInstances(ctx context.Context, project, zone string) ([]metadata.InstanceMetadata, error) {
|
||||||
uid, err := c.UID()
|
uid, err := c.UID(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
req := &computepb.ListInstancesRequest{
|
req := &computepb.ListInstancesRequest{
|
||||||
|
Filter: proto.String(fmt.Sprintf("labels.%s:%s", cloud.TagUID, uid)),
|
||||||
Project: project,
|
Project: project,
|
||||||
Zone: zone,
|
Zone: zone,
|
||||||
}
|
}
|
||||||
|
@ -80,11 +82,6 @@ func (c *Client) RetrieveInstances(ctx context.Context, project, zone string) ([
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("retrieving instance list from compute API client: %w", err)
|
return nil, fmt.Errorf("retrieving instance list from compute API client: %w", err)
|
||||||
}
|
}
|
||||||
metadata := extractInstanceMetadata(resp.Metadata, "", false)
|
|
||||||
// skip instances not belonging to the current constellation
|
|
||||||
if instanceUID, ok := metadata[constellationUIDMetadataKey]; !ok || instanceUID != uid {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
instance, err := convertToCoreInstance(resp, project, zone)
|
instance, err := convertToCoreInstance(resp, project, zone)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -223,7 +220,7 @@ func (c *Client) RetrieveSubnetworkAliasCIDR(ctx context.Context, project, zone,
|
||||||
|
|
||||||
// RetrieveLoadBalancerEndpoint returns the endpoint of the load balancer with the constellation-uid tag.
|
// RetrieveLoadBalancerEndpoint returns the endpoint of the load balancer with the constellation-uid tag.
|
||||||
func (c *Client) RetrieveLoadBalancerEndpoint(ctx context.Context, project string) (string, error) {
|
func (c *Client) RetrieveLoadBalancerEndpoint(ctx context.Context, project string) (string, error) {
|
||||||
uid, err := c.UID()
|
uid, err := c.UID(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -240,7 +237,7 @@ func (c *Client) RetrieveLoadBalancerEndpoint(ctx context.Context, project strin
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("retrieving load balancer IP failed: %w", err)
|
return "", fmt.Errorf("retrieving load balancer IP failed: %w", err)
|
||||||
}
|
}
|
||||||
if resp.Labels["constellation-uid"] == uid {
|
if resp.Labels[cloud.TagUID] == uid && resp.Labels["constellation-use"] == "kubernetes" {
|
||||||
if resp.PortRange == nil {
|
if resp.PortRange == nil {
|
||||||
return "", errors.New("load balancer with searched UID has no ports")
|
return "", errors.New("load balancer with searched UID has no ports")
|
||||||
}
|
}
|
||||||
|
@ -292,13 +289,30 @@ func (c *Client) updateInstanceMetadata(ctx context.Context, project, zone, inst
|
||||||
}
|
}
|
||||||
|
|
||||||
// UID retrieves the current instances uid.
|
// UID retrieves the current instances uid.
|
||||||
func (c *Client) UID() (string, error) {
|
func (c *Client) UID(ctx context.Context) (string, error) {
|
||||||
// API endpoint: http://metadata.google.internal/computeMetadata/v1/instance/attributes/constellation-uid
|
// API endpoint: http://metadata.google.internal/computeMetadata/v1/instance/attributes/constellation-uid
|
||||||
uid, err := c.RetrieveInstanceMetadata(constellationUIDMetadataKey)
|
instanceID, err := c.InstanceID()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("retrieving constellation uid: %w", err)
|
return "", fmt.Errorf("retrieving instance ID: %w", err)
|
||||||
}
|
}
|
||||||
return uid, nil
|
project, err := c.ProjectID()
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("retrieving project ID: %w", err)
|
||||||
|
}
|
||||||
|
zone, err := c.Zone()
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("retrieving zone: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
instance, err := c.instanceAPI.Get(ctx, &computepb.GetInstanceRequest{
|
||||||
|
Project: project,
|
||||||
|
Zone: zone,
|
||||||
|
Instance: instanceID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("retrieving instance labels: %w", err)
|
||||||
|
}
|
||||||
|
return instance.Labels[cloud.TagUID], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// extractVPCIP extracts the primary private IP from a list of interfaces.
|
// extractVPCIP extracts the primary private IP from a list of interfaces.
|
||||||
|
@ -385,7 +399,7 @@ func convertToCoreInstance(in *computepb.Instance, project string, zone string)
|
||||||
return metadata.InstanceMetadata{
|
return metadata.InstanceMetadata{
|
||||||
Name: *in.Name,
|
Name: *in.Name,
|
||||||
ProviderID: gcpshared.JoinProviderID(project, zone, *in.Name),
|
ProviderID: gcpshared.JoinProviderID(project, zone, *in.Name),
|
||||||
Role: extractRole(mdata),
|
Role: role.FromString(in.Labels[cloud.TagRole]),
|
||||||
VPCIP: extractVPCIP(in.NetworkInterfaces),
|
VPCIP: extractVPCIP(in.NetworkInterfaces),
|
||||||
PublicIP: extractPublicIP(in.NetworkInterfaces),
|
PublicIP: extractPublicIP(in.NetworkInterfaces),
|
||||||
AliasIPRanges: extractAliasIPRanges(in.NetworkInterfaces),
|
AliasIPRanges: extractAliasIPRanges(in.NetworkInterfaces),
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
compute "cloud.google.com/go/compute/apiv1"
|
compute "cloud.google.com/go/compute/apiv1"
|
||||||
|
"github.com/edgelesssys/constellation/v2/internal/cloud"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
|
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/role"
|
"github.com/edgelesssys/constellation/v2/internal/role"
|
||||||
gax "github.com/googleapis/gax-go/v2"
|
gax "github.com/googleapis/gax-go/v2"
|
||||||
|
@ -38,6 +39,10 @@ func TestRetrieveInstances(t *testing.T) {
|
||||||
instances: []*computepb.Instance{
|
instances: []*computepb.Instance{
|
||||||
{
|
{
|
||||||
Name: proto.String("someInstance"),
|
Name: proto.String("someInstance"),
|
||||||
|
Labels: map[string]string{
|
||||||
|
cloud.TagRole: role.ControlPlane.String(),
|
||||||
|
cloud.TagUID: uid,
|
||||||
|
},
|
||||||
Metadata: &computepb.Metadata{
|
Metadata: &computepb.Metadata{
|
||||||
Items: []*computepb.Items{
|
Items: []*computepb.Items{
|
||||||
{
|
{
|
||||||
|
@ -48,14 +53,6 @@ func TestRetrieveInstances(t *testing.T) {
|
||||||
Key: proto.String("key-2"),
|
Key: proto.String("key-2"),
|
||||||
Value: proto.String("value-2"),
|
Value: proto.String("value-2"),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Key: proto.String(constellationUIDMetadataKey),
|
|
||||||
Value: proto.String(uid),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: proto.String(roleMetadataKey),
|
|
||||||
Value: proto.String(role.ControlPlane.String()),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
NetworkInterfaces: []*computepb.NetworkInterface{
|
NetworkInterfaces: []*computepb.NetworkInterface{
|
||||||
|
@ -70,6 +67,13 @@ func TestRetrieveInstances(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
instance := &computepb.Instance{
|
||||||
|
Name: proto.String("instance"),
|
||||||
|
Labels: map[string]string{
|
||||||
|
cloud.TagRole: role.ControlPlane.String(),
|
||||||
|
cloud.TagUID: uid,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
client stubInstancesClient
|
client stubInstancesClient
|
||||||
|
@ -80,7 +84,7 @@ func TestRetrieveInstances(t *testing.T) {
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
"retrieve works": {
|
"retrieve works": {
|
||||||
client: stubInstancesClient{},
|
client: stubInstancesClient{GetInstance: instance},
|
||||||
metadata: stubMetadataClient{InstanceValue: uid},
|
metadata: stubMetadataClient{InstanceValue: uid},
|
||||||
instanceIter: newTestIter(),
|
instanceIter: newTestIter(),
|
||||||
wantInstances: []metadata.InstanceMetadata{
|
wantInstances: []metadata.InstanceMetadata{
|
||||||
|
@ -96,14 +100,14 @@ func TestRetrieveInstances(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"instance name is null": {
|
"instance name is null": {
|
||||||
client: stubInstancesClient{},
|
client: stubInstancesClient{GetInstance: instance},
|
||||||
metadata: stubMetadataClient{InstanceValue: uid},
|
metadata: stubMetadataClient{InstanceValue: uid},
|
||||||
instanceIter: newTestIter(),
|
instanceIter: newTestIter(),
|
||||||
instanceIterMutator: func(sii *stubInstanceIterator) { sii.instances[0].Name = nil },
|
instanceIterMutator: func(sii *stubInstanceIterator) { sii.instances[0].Name = nil },
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
"no instance with network ip": {
|
"no instance with network ip": {
|
||||||
client: stubInstancesClient{},
|
client: stubInstancesClient{GetInstance: instance},
|
||||||
metadata: stubMetadataClient{InstanceValue: uid},
|
metadata: stubMetadataClient{InstanceValue: uid},
|
||||||
instanceIter: newTestIter(),
|
instanceIter: newTestIter(),
|
||||||
instanceIterMutator: func(sii *stubInstanceIterator) { sii.instances[0].NetworkInterfaces = nil },
|
instanceIterMutator: func(sii *stubInstanceIterator) { sii.instances[0].NetworkInterfaces = nil },
|
||||||
|
@ -120,7 +124,7 @@ func TestRetrieveInstances(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"network ip is nil": {
|
"network ip is nil": {
|
||||||
client: stubInstancesClient{},
|
client: stubInstancesClient{GetInstance: instance},
|
||||||
metadata: stubMetadataClient{InstanceValue: uid},
|
metadata: stubMetadataClient{InstanceValue: uid},
|
||||||
instanceIter: newTestIter(),
|
instanceIter: newTestIter(),
|
||||||
instanceIterMutator: func(sii *stubInstanceIterator) { sii.instances[0].NetworkInterfaces[0].NetworkIP = nil },
|
instanceIterMutator: func(sii *stubInstanceIterator) { sii.instances[0].NetworkInterfaces[0].NetworkIP = nil },
|
||||||
|
@ -136,24 +140,17 @@ func TestRetrieveInstances(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"constellation id is not set": {
|
|
||||||
client: stubInstancesClient{},
|
|
||||||
metadata: stubMetadataClient{InstanceValue: uid},
|
|
||||||
instanceIter: newTestIter(),
|
|
||||||
instanceIterMutator: func(sii *stubInstanceIterator) { sii.instances[0].Metadata.Items[2].Key = proto.String("") },
|
|
||||||
wantInstances: []metadata.InstanceMetadata{},
|
|
||||||
},
|
|
||||||
"constellation retrieval fails": {
|
"constellation retrieval fails": {
|
||||||
client: stubInstancesClient{},
|
client: stubInstancesClient{GetInstance: instance},
|
||||||
metadata: stubMetadataClient{InstanceErr: someErr},
|
metadata: stubMetadataClient{instanceIDErr: someErr},
|
||||||
instanceIter: newTestIter(),
|
instanceIter: newTestIter(),
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
"role is not set": {
|
"role is not set": {
|
||||||
client: stubInstancesClient{},
|
client: stubInstancesClient{GetInstance: instance},
|
||||||
metadata: stubMetadataClient{InstanceValue: uid},
|
metadata: stubMetadataClient{InstanceValue: uid},
|
||||||
instanceIter: newTestIter(),
|
instanceIter: newTestIter(),
|
||||||
instanceIterMutator: func(sii *stubInstanceIterator) { sii.instances[0].Metadata.Items[3].Key = proto.String("") },
|
instanceIterMutator: func(sii *stubInstanceIterator) { delete(sii.instances[0].Labels, cloud.TagRole) },
|
||||||
wantInstances: []metadata.InstanceMetadata{
|
wantInstances: []metadata.InstanceMetadata{
|
||||||
{
|
{
|
||||||
Name: "someInstance",
|
Name: "someInstance",
|
||||||
|
@ -167,7 +164,7 @@ func TestRetrieveInstances(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"instance iterator Next() errors": {
|
"instance iterator Next() errors": {
|
||||||
client: stubInstancesClient{},
|
client: stubInstancesClient{GetInstance: instance},
|
||||||
metadata: stubMetadataClient{InstanceValue: uid},
|
metadata: stubMetadataClient{InstanceValue: uid},
|
||||||
instanceIter: &stubInstanceIterator{nextErr: someErr},
|
instanceIter: &stubInstanceIterator{nextErr: someErr},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
|
@ -204,6 +201,7 @@ func TestRetrieveInstance(t *testing.T) {
|
||||||
newTestInstance := func() *computepb.Instance {
|
newTestInstance := func() *computepb.Instance {
|
||||||
return &computepb.Instance{
|
return &computepb.Instance{
|
||||||
Name: proto.String("someInstance"),
|
Name: proto.String("someInstance"),
|
||||||
|
Labels: map[string]string{},
|
||||||
Metadata: &computepb.Metadata{
|
Metadata: &computepb.Metadata{
|
||||||
Items: []*computepb.Items{
|
Items: []*computepb.Items{
|
||||||
{
|
{
|
||||||
|
@ -266,8 +264,7 @@ func TestRetrieveInstance(t *testing.T) {
|
||||||
client: stubInstancesClient{},
|
client: stubInstancesClient{},
|
||||||
clientInstance: newTestInstance(),
|
clientInstance: newTestInstance(),
|
||||||
clientInstanceMutator: func(i *computepb.Instance) {
|
clientInstanceMutator: func(i *computepb.Instance) {
|
||||||
i.Metadata.Items[0].Key = proto.String(roleMetadataKey)
|
i.Labels[cloud.TagRole] = role.ControlPlane.String()
|
||||||
i.Metadata.Items[0].Value = proto.String(role.ControlPlane.String())
|
|
||||||
},
|
},
|
||||||
wantInstance: metadata.InstanceMetadata{
|
wantInstance: metadata.InstanceMetadata{
|
||||||
Name: "someInstance",
|
Name: "someInstance",
|
||||||
|
@ -782,22 +779,31 @@ func TestRetrieveSubnetworkAliasCIDR(t *testing.T) {
|
||||||
func TestRetrieveLoadBalancerEndpoint(t *testing.T) {
|
func TestRetrieveLoadBalancerEndpoint(t *testing.T) {
|
||||||
loadBalancerIP := "192.0.2.1"
|
loadBalancerIP := "192.0.2.1"
|
||||||
uid := "uid"
|
uid := "uid"
|
||||||
|
use := "kubernetes"
|
||||||
someErr := errors.New("some error")
|
someErr := errors.New("some error")
|
||||||
|
instance := &computepb.Instance{
|
||||||
|
Labels: map[string]string{
|
||||||
|
cloud.TagUID: uid,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
|
instanceAPI stubInstancesClient
|
||||||
stubForwardingRulesClient stubForwardingRulesClient
|
stubForwardingRulesClient stubForwardingRulesClient
|
||||||
stubMetadataClient stubMetadataClient
|
stubMetadataClient stubMetadataClient
|
||||||
wantLoadBalancerIP string
|
wantLoadBalancerIP string
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
"works": {
|
"works": {
|
||||||
stubMetadataClient: stubMetadataClient{InstanceValue: uid},
|
instanceAPI: stubInstancesClient{GetInstance: instance},
|
||||||
|
stubMetadataClient: stubMetadataClient{},
|
||||||
stubForwardingRulesClient: stubForwardingRulesClient{
|
stubForwardingRulesClient: stubForwardingRulesClient{
|
||||||
ForwardingRuleIterator: &stubForwardingRuleIterator{
|
ForwardingRuleIterator: &stubForwardingRuleIterator{
|
||||||
rules: []*computepb.ForwardingRule{
|
rules: []*computepb.ForwardingRule{
|
||||||
{
|
{
|
||||||
IPAddress: proto.String(loadBalancerIP),
|
IPAddress: proto.String(loadBalancerIP),
|
||||||
PortRange: proto.String("100-100"),
|
PortRange: proto.String("100-100"),
|
||||||
Labels: map[string]string{"constellation-uid": uid},
|
Labels: map[string]string{cloud.TagUID: uid, "constellation-use": use},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -805,7 +811,8 @@ func TestRetrieveLoadBalancerEndpoint(t *testing.T) {
|
||||||
wantLoadBalancerIP: loadBalancerIP,
|
wantLoadBalancerIP: loadBalancerIP,
|
||||||
},
|
},
|
||||||
"fails when no matching load balancers exists": {
|
"fails when no matching load balancers exists": {
|
||||||
stubMetadataClient: stubMetadataClient{InstanceValue: uid},
|
instanceAPI: stubInstancesClient{GetInstance: instance},
|
||||||
|
stubMetadataClient: stubMetadataClient{},
|
||||||
stubForwardingRulesClient: stubForwardingRulesClient{
|
stubForwardingRulesClient: stubForwardingRulesClient{
|
||||||
ForwardingRuleIterator: &stubForwardingRuleIterator{
|
ForwardingRuleIterator: &stubForwardingRuleIterator{
|
||||||
rules: []*computepb.ForwardingRule{
|
rules: []*computepb.ForwardingRule{
|
||||||
|
@ -819,14 +826,15 @@ func TestRetrieveLoadBalancerEndpoint(t *testing.T) {
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
"fails when retrieving uid": {
|
"fails when retrieving uid": {
|
||||||
stubMetadataClient: stubMetadataClient{InstanceErr: someErr},
|
instanceAPI: stubInstancesClient{GetInstance: instance},
|
||||||
|
stubMetadataClient: stubMetadataClient{instanceIDErr: someErr},
|
||||||
stubForwardingRulesClient: stubForwardingRulesClient{
|
stubForwardingRulesClient: stubForwardingRulesClient{
|
||||||
ForwardingRuleIterator: &stubForwardingRuleIterator{
|
ForwardingRuleIterator: &stubForwardingRuleIterator{
|
||||||
rules: []*computepb.ForwardingRule{
|
rules: []*computepb.ForwardingRule{
|
||||||
{
|
{
|
||||||
IPAddress: proto.String(loadBalancerIP),
|
IPAddress: proto.String(loadBalancerIP),
|
||||||
PortRange: proto.String("100-100"),
|
PortRange: proto.String("100-100"),
|
||||||
Labels: map[string]string{"constellation-uid": uid},
|
Labels: map[string]string{cloud.TagUID: uid, "constellation-use": use},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -834,13 +842,14 @@ func TestRetrieveLoadBalancerEndpoint(t *testing.T) {
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
"fails when answer has empty port range": {
|
"fails when answer has empty port range": {
|
||||||
stubMetadataClient: stubMetadataClient{InstanceErr: someErr},
|
instanceAPI: stubInstancesClient{GetInstance: instance},
|
||||||
|
stubMetadataClient: stubMetadataClient{},
|
||||||
stubForwardingRulesClient: stubForwardingRulesClient{
|
stubForwardingRulesClient: stubForwardingRulesClient{
|
||||||
ForwardingRuleIterator: &stubForwardingRuleIterator{
|
ForwardingRuleIterator: &stubForwardingRuleIterator{
|
||||||
rules: []*computepb.ForwardingRule{
|
rules: []*computepb.ForwardingRule{
|
||||||
{
|
{
|
||||||
IPAddress: proto.String(loadBalancerIP),
|
IPAddress: proto.String(loadBalancerIP),
|
||||||
Labels: map[string]string{"constellation-uid": uid},
|
Labels: map[string]string{cloud.TagUID: uid, "constellation-use": use},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -848,6 +857,7 @@ func TestRetrieveLoadBalancerEndpoint(t *testing.T) {
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
"fails when retrieving loadbalancer IP": {
|
"fails when retrieving loadbalancer IP": {
|
||||||
|
instanceAPI: stubInstancesClient{GetInstance: instance},
|
||||||
stubMetadataClient: stubMetadataClient{},
|
stubMetadataClient: stubMetadataClient{},
|
||||||
stubForwardingRulesClient: stubForwardingRulesClient{
|
stubForwardingRulesClient: stubForwardingRulesClient{
|
||||||
ForwardingRuleIterator: &stubForwardingRuleIterator{
|
ForwardingRuleIterator: &stubForwardingRuleIterator{
|
||||||
|
@ -856,7 +866,23 @@ func TestRetrieveLoadBalancerEndpoint(t *testing.T) {
|
||||||
{
|
{
|
||||||
IPAddress: proto.String(loadBalancerIP),
|
IPAddress: proto.String(loadBalancerIP),
|
||||||
PortRange: proto.String("100-100"),
|
PortRange: proto.String("100-100"),
|
||||||
Labels: map[string]string{"constellation-uid": uid},
|
Labels: map[string]string{cloud.TagUID: uid, "constellation-use": use},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
"fails on incorrect use label": {
|
||||||
|
instanceAPI: stubInstancesClient{GetInstance: instance},
|
||||||
|
stubMetadataClient: stubMetadataClient{InstanceValue: uid},
|
||||||
|
stubForwardingRulesClient: stubForwardingRulesClient{
|
||||||
|
ForwardingRuleIterator: &stubForwardingRuleIterator{
|
||||||
|
rules: []*computepb.ForwardingRule{
|
||||||
|
{
|
||||||
|
IPAddress: proto.String(loadBalancerIP),
|
||||||
|
PortRange: proto.String("100-100"),
|
||||||
|
Labels: map[string]string{cloud.TagUID: uid, "constellation-use": "bootstrapper"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -869,7 +895,7 @@ func TestRetrieveLoadBalancerEndpoint(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
require := require.New(t)
|
require := require.New(t)
|
||||||
|
|
||||||
client := Client{forwardingRulesAPI: tc.stubForwardingRulesClient, metadataAPI: tc.stubMetadataClient}
|
client := Client{instanceAPI: tc.instanceAPI, forwardingRulesAPI: tc.stubForwardingRulesClient, metadataAPI: tc.stubMetadataClient}
|
||||||
aliasCIDR, err := client.RetrieveLoadBalancerEndpoint(context.Background(), "project")
|
aliasCIDR, err := client.RetrieveLoadBalancerEndpoint(context.Background(), "project")
|
||||||
|
|
||||||
if tc.wantErr {
|
if tc.wantErr {
|
||||||
|
@ -1049,6 +1075,8 @@ func (s stubForwardingRulesClient) Close() error {
|
||||||
type stubMetadataClient struct {
|
type stubMetadataClient struct {
|
||||||
InstanceValue string
|
InstanceValue string
|
||||||
InstanceErr error
|
InstanceErr error
|
||||||
|
instanceIDValue string
|
||||||
|
instanceIDErr error
|
||||||
ProjectIDValue string
|
ProjectIDValue string
|
||||||
ProjectIDErr error
|
ProjectIDErr error
|
||||||
ZoneValue string
|
ZoneValue string
|
||||||
|
@ -1061,6 +1089,10 @@ func (s stubMetadataClient) InstanceAttributeValue(attr string) (string, error)
|
||||||
return s.InstanceValue, s.InstanceErr
|
return s.InstanceValue, s.InstanceErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s stubMetadataClient) InstanceID() (string, error) {
|
||||||
|
return s.instanceIDValue, s.instanceIDErr
|
||||||
|
}
|
||||||
|
|
||||||
func (s stubMetadataClient) ProjectID() (string, error) {
|
func (s stubMetadataClient) ProjectID() (string, error) {
|
||||||
return s.ProjectIDValue, s.ProjectIDErr
|
return s.ProjectIDValue, s.ProjectIDErr
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ import (
|
||||||
// API handles all GCP API requests.
|
// API handles all GCP API requests.
|
||||||
type API interface {
|
type API interface {
|
||||||
// UID retrieves the current instances uid.
|
// UID retrieves the current instances uid.
|
||||||
UID() (string, error)
|
UID(context.Context) (string, error)
|
||||||
// RetrieveInstances retrieves a list of all accessible GCP instances with their metadata.
|
// RetrieveInstances retrieves a list of all accessible GCP instances with their metadata.
|
||||||
RetrieveInstances(ctx context.Context, project, zone string) ([]metadata.InstanceMetadata, error)
|
RetrieveInstances(ctx context.Context, project, zone string) ([]metadata.InstanceMetadata, error)
|
||||||
// RetrieveInstances retrieves a single GCP instances with its metadata.
|
// RetrieveInstances retrieves a single GCP instances with its metadata.
|
||||||
|
@ -128,7 +128,7 @@ func (m *Metadata) GetLoadBalancerEndpoint(ctx context.Context) (string, error)
|
||||||
|
|
||||||
// UID retrieves the UID of the constellation.
|
// UID retrieves the UID of the constellation.
|
||||||
func (m *Metadata) UID(ctx context.Context) (string, error) {
|
func (m *Metadata) UID(ctx context.Context) (string, error) {
|
||||||
return m.api.UID()
|
return m.api.UID(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Supported is used to determine if metadata API is implemented for this cloud provider.
|
// Supported is used to determine if metadata API is implemented for this cloud provider.
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/edgelesssys/constellation/v2/internal/cloud"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
|
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
@ -41,7 +42,7 @@ func TestList(t *testing.T) {
|
||||||
projectID: "someProjectID",
|
projectID: "someProjectID",
|
||||||
zone: "someZone",
|
zone: "someZone",
|
||||||
retrieveInstanceMetadaValues: map[string]string{
|
retrieveInstanceMetadaValues: map[string]string{
|
||||||
"constellation-uid": uid,
|
cloud.TagUID: uid,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
instancesGenerator: instancesGenerator,
|
instancesGenerator: instancesGenerator,
|
||||||
|
@ -58,7 +59,7 @@ func TestList(t *testing.T) {
|
||||||
projectID: "someProjectID",
|
projectID: "someProjectID",
|
||||||
zone: "someZone",
|
zone: "someZone",
|
||||||
retrieveInstanceMetadaValues: map[string]string{
|
retrieveInstanceMetadaValues: map[string]string{
|
||||||
"constellation-uid": uid,
|
cloud.TagUID: uid,
|
||||||
},
|
},
|
||||||
retrieveInstancesErr: err,
|
retrieveInstancesErr: err,
|
||||||
},
|
},
|
||||||
|
@ -133,7 +134,7 @@ func TestSelf(t *testing.T) {
|
||||||
projectID: "someProjectID",
|
projectID: "someProjectID",
|
||||||
zone: "someZone",
|
zone: "someZone",
|
||||||
retrieveInstanceMetadaValues: map[string]string{
|
retrieveInstanceMetadaValues: map[string]string{
|
||||||
"constellation-uid": uid,
|
cloud.TagUID: uid,
|
||||||
},
|
},
|
||||||
retrieveInstanceErr: err,
|
retrieveInstanceErr: err,
|
||||||
},
|
},
|
||||||
|
@ -297,7 +298,7 @@ func (s *stubGCPClient) RetrieveLoadBalancerEndpoint(ctx context.Context, projec
|
||||||
return s.loadBalancerIP, s.retrieveLoadBalancerErr
|
return s.loadBalancerIP, s.retrieveLoadBalancerErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stubGCPClient) UID() (string, error) {
|
func (s *stubGCPClient) UID(context.Context) (string, error) {
|
||||||
return s.retrieveUIDValue, s.retrieveUIDErr
|
return s.retrieveUIDValue, s.retrieveUIDErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright (c) Edgeless Systems GmbH
|
|
||||||
|
|
||||||
SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
*/
|
|
||||||
|
|
||||||
package gcp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/role"
|
|
||||||
)
|
|
||||||
|
|
||||||
const roleMetadataKey = "constellation-role"
|
|
||||||
|
|
||||||
// extractRole extracts role from cloud provider metadata.
|
|
||||||
func extractRole(metadata map[string]string) role.Role {
|
|
||||||
switch metadata[roleMetadataKey] {
|
|
||||||
case role.ControlPlane.String():
|
|
||||||
return role.ControlPlane
|
|
||||||
case role.Worker.String():
|
|
||||||
return role.Worker
|
|
||||||
default:
|
|
||||||
return role.Unknown
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,53 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright (c) Edgeless Systems GmbH
|
|
||||||
|
|
||||||
SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
*/
|
|
||||||
|
|
||||||
package gcp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/role"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestExtractRole(t *testing.T) {
|
|
||||||
testCases := map[string]struct {
|
|
||||||
metadata map[string]string
|
|
||||||
wantRole role.Role
|
|
||||||
}{
|
|
||||||
"bootstrapper role": {
|
|
||||||
metadata: map[string]string{
|
|
||||||
roleMetadataKey: role.ControlPlane.String(),
|
|
||||||
},
|
|
||||||
wantRole: role.ControlPlane,
|
|
||||||
},
|
|
||||||
"node role": {
|
|
||||||
metadata: map[string]string{
|
|
||||||
roleMetadataKey: role.Worker.String(),
|
|
||||||
},
|
|
||||||
wantRole: role.Worker,
|
|
||||||
},
|
|
||||||
"unknown role": {
|
|
||||||
metadata: map[string]string{
|
|
||||||
roleMetadataKey: "some-unknown-role",
|
|
||||||
},
|
|
||||||
wantRole: role.Unknown,
|
|
||||||
},
|
|
||||||
"no role": {
|
|
||||||
wantRole: role.Unknown,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for name, tc := range testCases {
|
|
||||||
t.Run(name, func(t *testing.T) {
|
|
||||||
assert := assert.New(t)
|
|
||||||
|
|
||||||
role := extractRole(tc.metadata)
|
|
||||||
|
|
||||||
assert.Equal(tc.wantRole, role)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -69,6 +69,10 @@ func (c *metadataClient) InstanceAttributeValue(attr string) (string, error) {
|
||||||
return metadata.InstanceAttributeValue(attr)
|
return metadata.InstanceAttributeValue(attr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *metadataClient) InstanceID() (string, error) {
|
||||||
|
return metadata.InstanceID()
|
||||||
|
}
|
||||||
|
|
||||||
func (c *metadataClient) ProjectID() (string, error) {
|
func (c *metadataClient) ProjectID() (string, error) {
|
||||||
return metadata.ProjectID()
|
return metadata.ProjectID()
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ const (
|
||||||
VerificationImage = "ghcr.io/edgelesssys/constellation/verification-service:v2.1.0@sha256:7a1e6bec4cda270924c3495466fa536a2b6cd2d2f9c0be319fc6368710c255e8"
|
VerificationImage = "ghcr.io/edgelesssys/constellation/verification-service:v2.1.0@sha256:7a1e6bec4cda270924c3495466fa536a2b6cd2d2f9c0be319fc6368710c255e8"
|
||||||
// Check for new versions at https://github.com/GoogleCloudPlatform/guest-agent/releases and update in /.github/workflows/build-gcp-guest-agent.yml.
|
// Check for new versions at https://github.com/GoogleCloudPlatform/guest-agent/releases and update in /.github/workflows/build-gcp-guest-agent.yml.
|
||||||
GcpGuestImage = "ghcr.io/edgelesssys/gcp-guest-agent:20220927.00@sha256:3dea1ae3f162d2353e6584b325f0e325a39cda5f380f41e5a0ee43c6641d3905"
|
GcpGuestImage = "ghcr.io/edgelesssys/gcp-guest-agent:20220927.00@sha256:3dea1ae3f162d2353e6584b325f0e325a39cda5f380f41e5a0ee43c6641d3905"
|
||||||
NodeOperatorCatalogImage = "ghcr.io/edgelesssys/constellation/node-operator-catalog:v2.2.0-pre.0.20221012150059-4b2dd1317a77@sha256:f840435fe3a7669afe78aa12b0ba7f36a0087dc6d86d4fe3f3e340395f002e3f"
|
NodeOperatorCatalogImage = "ghcr.io/edgelesssys/constellation/node-operator-catalog:v2.2.0-pre.0.20221021130530-c6623f2ebd72@sha256:f2750cb3c0f8368808686ffd5835b6d7152ae2845e35ee9891e910738dc26718"
|
||||||
// TODO: switch node maintenance operator catalog back to upstream quay.io/medik8s/node-maintenance-operator-catalog
|
// TODO: switch node maintenance operator catalog back to upstream quay.io/medik8s/node-maintenance-operator-catalog
|
||||||
// once https://github.com/medik8s/node-maintenance-operator/issues/49 is resolved.
|
// once https://github.com/medik8s/node-maintenance-operator/issues/49 is resolved.
|
||||||
NodeMaintenanceOperatorCatalogImage = "ghcr.io/edgelesssys/constellation/node-maintenance-operator-catalog:v0.13.1-alpha1@sha256:d382c3aaf9bc470cde6f6c05c2c6ff5c9dcfd90540d5b11f9cf69c4e1dd1ca9d"
|
NodeMaintenanceOperatorCatalogImage = "ghcr.io/edgelesssys/constellation/node-maintenance-operator-catalog:v0.13.1-alpha1@sha256:d382c3aaf9bc470cde6f6c05c2c6ff5c9dcfd90540d5b11f9cf69c4e1dd1ca9d"
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright (c) Edgeless Systems GmbH
|
|
||||||
|
|
||||||
SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
*/
|
|
||||||
|
|
||||||
package client
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// getScaleSets retrieves the IDs of all scale sets of a resource group.
|
|
||||||
func (c *Client) getScaleSets(ctx context.Context) ([]string, error) {
|
|
||||||
pager := c.scaleSetsAPI.NewListPager(c.config.ResourceGroup, nil)
|
|
||||||
var scaleSets []string
|
|
||||||
|
|
||||||
for pager.More() {
|
|
||||||
page, err := pager.NextPage(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("paging scale sets: %w", err)
|
|
||||||
}
|
|
||||||
for _, scaleSet := range page.Value {
|
|
||||||
if scaleSet == nil || scaleSet.ID == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
scaleSets = append(scaleSets, *scaleSet.ID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return scaleSets, nil
|
|
||||||
}
|
|
|
@ -1,62 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright (c) Edgeless Systems GmbH
|
|
||||||
|
|
||||||
SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
*/
|
|
||||||
|
|
||||||
package client
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
|
|
||||||
armcomputev2 "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v2"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGetScaleSets(t *testing.T) {
|
|
||||||
testCases := map[string]struct {
|
|
||||||
scaleSet armcomputev2.VirtualMachineScaleSet
|
|
||||||
fetchPageErr error
|
|
||||||
wantScaleSets []string
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
"fetching scale sets works": {
|
|
||||||
scaleSet: armcomputev2.VirtualMachineScaleSet{
|
|
||||||
ID: to.Ptr("/subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/scale-set-name"),
|
|
||||||
},
|
|
||||||
wantScaleSets: []string{"/subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/scale-set-name"},
|
|
||||||
},
|
|
||||||
"fetching scale sets fails": {
|
|
||||||
fetchPageErr: errors.New("fetch page error"),
|
|
||||||
wantErr: true,
|
|
||||||
},
|
|
||||||
"scale set is invalid": {},
|
|
||||||
}
|
|
||||||
|
|
||||||
for name, tc := range testCases {
|
|
||||||
t.Run(name, func(t *testing.T) {
|
|
||||||
assert := assert.New(t)
|
|
||||||
require := require.New(t)
|
|
||||||
|
|
||||||
client := Client{
|
|
||||||
scaleSetsAPI: &stubScaleSetsAPI{
|
|
||||||
pager: &stubVMSSPager{
|
|
||||||
list: []armcomputev2.VirtualMachineScaleSet{tc.scaleSet},
|
|
||||||
fetchErr: tc.fetchPageErr,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
gotScaleSets, err := client.getScaleSets(context.Background())
|
|
||||||
if tc.wantErr {
|
|
||||||
assert.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
require.NoError(err)
|
|
||||||
assert.ElementsMatch(tc.wantScaleSets, gotScaleSets)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -80,34 +80,35 @@ func (c *Client) 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.
|
||||||
func (c *Client) ListScalingGroups(ctx context.Context, uid string) (controlPlaneGroupIDs []string, workerGroupIDs []string, err error) {
|
func (c *Client) ListScalingGroups(ctx context.Context, uid string) (controlPlaneGroupIDs []string, workerGroupIDs []string, err error) {
|
||||||
scaleSetIDs, err := c.getScaleSets(ctx)
|
pager := c.scaleSetsAPI.NewListPager(c.config.ResourceGroup, nil)
|
||||||
|
|
||||||
|
for pager.More() {
|
||||||
|
page, err := pager.NextPage(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("listing scaling groups: %w", err)
|
return nil, nil, fmt.Errorf("paging scale sets: %w", err)
|
||||||
}
|
}
|
||||||
for _, scaleSetID := range scaleSetIDs {
|
for _, scaleSet := range page.Value {
|
||||||
_, _, scaleSet, err := splitVMSSID(scaleSetID)
|
if scaleSet == nil || scaleSet.ID == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if scaleSet.Tags == nil || scaleSet.Tags["constellation-uid"] == nil || *scaleSet.Tags["constellation-uid"] != uid {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("getting scaling group name: %w", err)
|
return nil, nil, fmt.Errorf("getting scaling group name: %w", err)
|
||||||
}
|
}
|
||||||
if isControlPlaneInstanceGroup(scaleSet) {
|
switch *scaleSet.Tags["constellation-role"] {
|
||||||
controlPlaneGroupIDs = append(controlPlaneGroupIDs, scaleSetID)
|
case "control-plane", "controlplane":
|
||||||
} else if isWorkerInstanceGroup(scaleSet) {
|
controlPlaneGroupIDs = append(controlPlaneGroupIDs, *scaleSet.ID)
|
||||||
workerGroupIDs = append(workerGroupIDs, scaleSetID)
|
case "worker":
|
||||||
|
workerGroupIDs = append(workerGroupIDs, *scaleSet.ID)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return controlPlaneGroupIDs, workerGroupIDs, nil
|
return controlPlaneGroupIDs, workerGroupIDs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// isControlPlaneInstanceGroup returns true if the instance group is a control plane instance group.
|
|
||||||
func isControlPlaneInstanceGroup(instanceGroupName string) bool {
|
|
||||||
return strings.Contains(instanceGroupName, "control-plane")
|
|
||||||
}
|
|
||||||
|
|
||||||
// isWorkerInstanceGroup returns true if the instance group is a worker instance group.
|
|
||||||
func isWorkerInstanceGroup(instanceGroupName string) bool {
|
|
||||||
return strings.Contains(instanceGroupName, "worker")
|
|
||||||
}
|
|
||||||
|
|
||||||
func imageReferenceFromImage(img string) *armcompute.ImageReference {
|
func imageReferenceFromImage(img string) *armcompute.ImageReference {
|
||||||
ref := &armcompute.ImageReference{}
|
ref := &armcompute.ImageReference{}
|
||||||
|
|
||||||
|
|
|
@ -193,15 +193,33 @@ func TestListScalingGroups(t *testing.T) {
|
||||||
"listing control-plane works": {
|
"listing control-plane works": {
|
||||||
scaleSet: armcomputev2.VirtualMachineScaleSet{
|
scaleSet: armcomputev2.VirtualMachineScaleSet{
|
||||||
ID: to.Ptr("/subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/constellation-scale-set-control-planes-uid"),
|
ID: to.Ptr("/subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/constellation-scale-set-control-planes-uid"),
|
||||||
|
Tags: map[string]*string{
|
||||||
|
"constellation-uid": to.Ptr("uid"),
|
||||||
|
"constellation-role": to.Ptr("control-plane"),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
wantControlPlanes: []string{"/subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/constellation-scale-set-control-planes-uid"},
|
wantControlPlanes: []string{"/subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/constellation-scale-set-control-planes-uid"},
|
||||||
},
|
},
|
||||||
"listing worker works": {
|
"listing worker works": {
|
||||||
scaleSet: armcomputev2.VirtualMachineScaleSet{
|
scaleSet: armcomputev2.VirtualMachineScaleSet{
|
||||||
ID: to.Ptr("/subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/constellation-scale-set-workers-uid"),
|
ID: to.Ptr("/subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/constellation-scale-set-workers-uid"),
|
||||||
|
Tags: map[string]*string{
|
||||||
|
"constellation-uid": to.Ptr("uid"),
|
||||||
|
"constellation-role": to.Ptr("worker"),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
wantWorkers: []string{"/subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/constellation-scale-set-workers-uid"},
|
wantWorkers: []string{"/subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/constellation-scale-set-workers-uid"},
|
||||||
},
|
},
|
||||||
|
"listing is not dependent on resource name": {
|
||||||
|
scaleSet: armcomputev2.VirtualMachineScaleSet{
|
||||||
|
ID: to.Ptr("/subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/some-scale-set"),
|
||||||
|
Tags: map[string]*string{
|
||||||
|
"constellation-uid": to.Ptr("uid"),
|
||||||
|
"constellation-role": to.Ptr("control-plane"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantControlPlanes: []string{"/subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/some-scale-set"},
|
||||||
|
},
|
||||||
"listing other works": {
|
"listing other works": {
|
||||||
scaleSet: armcomputev2.VirtualMachineScaleSet{
|
scaleSet: armcomputev2.VirtualMachineScaleSet{
|
||||||
ID: to.Ptr("/subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/other"),
|
ID: to.Ptr("/subscriptions/subscription-id/resourceGroups/resource-group/providers/Microsoft.Compute/virtualMachineScaleSets/other"),
|
||||||
|
|
|
@ -10,7 +10,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var instanceGroupIDRegex = regexp.MustCompile(`^projects/([^/]+)/zones/([^/]+)/instanceGroupManagers/([^/]+)$`)
|
var instanceGroupIDRegex = regexp.MustCompile(`^projects/([^/]+)/zones/([^/]+)/instanceGroupManagers/([^/]+)$`)
|
||||||
|
@ -36,16 +35,6 @@ func splitInstanceGroupID(instanceGroupID string) (project, zone, instanceGroup
|
||||||
return matches[1], matches[2], matches[3], nil
|
return matches[1], matches[2], matches[3], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// isControlPlaneInstanceGroup returns true if the instance group is a control plane instance group.
|
|
||||||
func isControlPlaneInstanceGroup(instanceGroupName string) bool {
|
|
||||||
return strings.Contains(instanceGroupName, "control-plane")
|
|
||||||
}
|
|
||||||
|
|
||||||
// isWorkerInstanceGroup returns true if the instance group is a worker instance group.
|
|
||||||
func isWorkerInstanceGroup(instanceGroupName string) bool {
|
|
||||||
return strings.Contains(instanceGroupName, "worker")
|
|
||||||
}
|
|
||||||
|
|
||||||
// generateInstanceName generates a random instance name.
|
// generateInstanceName generates a random instance name.
|
||||||
func generateInstanceName(baseInstanceName string, random prng) string {
|
func generateInstanceName(baseInstanceName string, random prng) string {
|
||||||
letters := []byte("abcdefghijklmnopqrstuvwxyz0123456789")
|
letters := []byte("abcdefghijklmnopqrstuvwxyz0123456789")
|
||||||
|
|
|
@ -10,10 +10,10 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"google.golang.org/api/iterator"
|
"google.golang.org/api/iterator"
|
||||||
computepb "google.golang.org/genproto/googleapis/cloud/compute/v1"
|
computepb "google.golang.org/genproto/googleapis/cloud/compute/v1"
|
||||||
"google.golang.org/protobuf/proto"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetScalingGroupImage returns the image URI of the scaling group.
|
// GetScalingGroupImage returns the image URI of the scaling group.
|
||||||
|
@ -108,7 +108,6 @@ func (c *Client) 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.
|
||||||
func (c *Client) ListScalingGroups(ctx context.Context, uid string) (controlPlaneGroupIDs []string, workerGroupIDs []string, err error) {
|
func (c *Client) ListScalingGroups(ctx context.Context, uid string) (controlPlaneGroupIDs []string, workerGroupIDs []string, err error) {
|
||||||
iter := c.instanceGroupManagersAPI.AggregatedList(ctx, &computepb.AggregatedListInstanceGroupManagersRequest{
|
iter := c.instanceGroupManagersAPI.AggregatedList(ctx, &computepb.AggregatedListInstanceGroupManagersRequest{
|
||||||
Filter: proto.String(fmt.Sprintf("name eq \".+-%s-.+\"", uid)), // filter by constellation UID
|
|
||||||
Project: c.projectID,
|
Project: c.projectID,
|
||||||
})
|
})
|
||||||
for instanceGroupManagerScopedListPair, err := iter.Next(); ; instanceGroupManagerScopedListPair, err = iter.Next() {
|
for instanceGroupManagerScopedListPair, err := iter.Next(); ; instanceGroupManagerScopedListPair, err = iter.Next() {
|
||||||
|
@ -121,18 +120,38 @@ func (c *Client) ListScalingGroups(ctx context.Context, uid string) (controlPlan
|
||||||
if instanceGroupManagerScopedListPair.Value == nil {
|
if instanceGroupManagerScopedListPair.Value == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for _, instanceGroupManager := range instanceGroupManagerScopedListPair.Value.InstanceGroupManagers {
|
for _, grpManager := range instanceGroupManagerScopedListPair.Value.InstanceGroupManagers {
|
||||||
if instanceGroupManager == nil || instanceGroupManager.Name == nil || instanceGroupManager.SelfLink == nil {
|
if grpManager == nil || grpManager.Name == nil || grpManager.SelfLink == nil || grpManager.InstanceTemplate == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
groupID, err := c.canonicalInstanceGroupID(ctx, *instanceGroupManager.SelfLink)
|
|
||||||
|
templateURI := strings.Split(*grpManager.InstanceTemplate, "/")
|
||||||
|
if len(templateURI) < 1 {
|
||||||
|
continue // invalid template URI
|
||||||
|
}
|
||||||
|
template, err := c.instanceTemplateAPI.Get(ctx, &computepb.GetInstanceTemplateRequest{
|
||||||
|
Project: c.projectID,
|
||||||
|
InstanceTemplate: templateURI[len(templateURI)-1],
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("getting instance template: %w", err)
|
||||||
|
}
|
||||||
|
if template.Properties == nil || template.Properties.Labels == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if template.Properties.Labels["constellation-uid"] != uid {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
groupID, err := c.canonicalInstanceGroupID(ctx, *grpManager.SelfLink)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("normalizing instance group ID: %w", err)
|
return nil, nil, fmt.Errorf("normalizing instance group ID: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if isControlPlaneInstanceGroup(*instanceGroupManager.Name) {
|
switch strings.ToLower(template.Properties.Labels["constellation-role"]) {
|
||||||
|
case "control-plane", "controlplane":
|
||||||
controlPlaneGroupIDs = append(controlPlaneGroupIDs, groupID)
|
controlPlaneGroupIDs = append(controlPlaneGroupIDs, groupID)
|
||||||
} else if isWorkerInstanceGroup(*instanceGroupManager.Name) {
|
case "worker":
|
||||||
workerGroupIDs = append(workerGroupIDs, groupID)
|
workerGroupIDs = append(workerGroupIDs, groupID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -326,7 +326,10 @@ func TestListScalingGroups(t *testing.T) {
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
name *string
|
name *string
|
||||||
groupID *string
|
groupID *string
|
||||||
|
templateRef *string
|
||||||
|
templateLabels map[string]string
|
||||||
listInstanceGroupManagersErr error
|
listInstanceGroupManagersErr error
|
||||||
|
templateGetErr error
|
||||||
wantControlPlanes []string
|
wantControlPlanes []string
|
||||||
wantWorkers []string
|
wantWorkers []string
|
||||||
wantErr bool
|
wantErr bool
|
||||||
|
@ -335,9 +338,21 @@ func TestListScalingGroups(t *testing.T) {
|
||||||
listInstanceGroupManagersErr: errors.New("list instance group managers error"),
|
listInstanceGroupManagersErr: errors.New("list instance group managers error"),
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
|
"get instance template fails": {
|
||||||
|
name: proto.String("test-control-plane-uid"),
|
||||||
|
groupID: proto.String("projects/project/zones/zone/instanceGroupManagers/test-control-plane-uid"),
|
||||||
|
templateRef: proto.String("projects/project/global/instanceTemplates/test-control-plane-uid"),
|
||||||
|
templateGetErr: errors.New("get instance template error"),
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
"list instance group managers for control plane": {
|
"list instance group managers for control plane": {
|
||||||
name: proto.String("test-control-plane-uid"),
|
name: proto.String("test-control-plane-uid"),
|
||||||
groupID: proto.String("projects/project/zones/zone/instanceGroupManagers/test-control-plane-uid"),
|
groupID: proto.String("projects/project/zones/zone/instanceGroupManagers/test-control-plane-uid"),
|
||||||
|
templateRef: proto.String("projects/project/global/instanceTemplates/test-control-plane-uid"),
|
||||||
|
templateLabels: map[string]string{
|
||||||
|
"constellation-uid": "uid",
|
||||||
|
"constellation-role": "control-plane",
|
||||||
|
},
|
||||||
wantControlPlanes: []string{
|
wantControlPlanes: []string{
|
||||||
"projects/project/zones/zone/instanceGroupManagers/test-control-plane-uid",
|
"projects/project/zones/zone/instanceGroupManagers/test-control-plane-uid",
|
||||||
},
|
},
|
||||||
|
@ -345,13 +360,34 @@ func TestListScalingGroups(t *testing.T) {
|
||||||
"list instance group managers for worker": {
|
"list instance group managers for worker": {
|
||||||
name: proto.String("test-worker-uid"),
|
name: proto.String("test-worker-uid"),
|
||||||
groupID: proto.String("projects/project/zones/zone/instanceGroupManagers/test-worker-uid"),
|
groupID: proto.String("projects/project/zones/zone/instanceGroupManagers/test-worker-uid"),
|
||||||
|
templateRef: proto.String("projects/project/global/instanceTemplates/test-control-plane-uid"),
|
||||||
|
templateLabels: map[string]string{
|
||||||
|
"constellation-uid": "uid",
|
||||||
|
"constellation-role": "worker",
|
||||||
|
},
|
||||||
wantWorkers: []string{
|
wantWorkers: []string{
|
||||||
"projects/project/zones/zone/instanceGroupManagers/test-worker-uid",
|
"projects/project/zones/zone/instanceGroupManagers/test-worker-uid",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"listing instance group managers is not dependant on resource name": {
|
||||||
|
name: proto.String("some-instance-group-manager"),
|
||||||
|
groupID: proto.String("projects/project/zones/zone/instanceGroupManagers/some-instance-group-manager"),
|
||||||
|
templateRef: proto.String("projects/project/global/instanceTemplates/some-instance-group-template"),
|
||||||
|
templateLabels: map[string]string{
|
||||||
|
"constellation-uid": "uid",
|
||||||
|
"constellation-role": "control-plane",
|
||||||
|
},
|
||||||
|
wantControlPlanes: []string{
|
||||||
|
"projects/project/zones/zone/instanceGroupManagers/some-instance-group-manager",
|
||||||
|
},
|
||||||
|
},
|
||||||
"unrelated instance group manager": {
|
"unrelated instance group manager": {
|
||||||
name: proto.String("test-unrelated-uid"),
|
name: proto.String("test-control-plane-uid"),
|
||||||
groupID: proto.String("projects/project/zones/zone/instanceGroupManagers/test-unrelated-uid"),
|
groupID: proto.String("projects/project/zones/zone/instanceGroupManagers/test-unrelated-uid"),
|
||||||
|
templateRef: proto.String("projects/project/global/instanceTemplates/test-control-plane-uid"),
|
||||||
|
templateLabels: map[string]string{
|
||||||
|
"label": "value",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"invalid instance group manager": {},
|
"invalid instance group manager": {},
|
||||||
}
|
}
|
||||||
|
@ -367,8 +403,17 @@ func TestListScalingGroups(t *testing.T) {
|
||||||
instanceGroupManager: &computepb.InstanceGroupManager{
|
instanceGroupManager: &computepb.InstanceGroupManager{
|
||||||
Name: tc.name,
|
Name: tc.name,
|
||||||
SelfLink: tc.groupID,
|
SelfLink: tc.groupID,
|
||||||
|
InstanceTemplate: tc.templateRef,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
instanceTemplateAPI: &stubInstanceTemplateAPI{
|
||||||
|
template: &computepb.InstanceTemplate{
|
||||||
|
Properties: &computepb.InstanceProperties{
|
||||||
|
Labels: tc.templateLabels,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
getErr: tc.templateGetErr,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
gotControlPlanes, gotWorkers, err := client.ListScalingGroups(context.Background(), "uid")
|
gotControlPlanes, gotWorkers, err := client.ListScalingGroups(context.Background(), "uid")
|
||||||
if tc.wantErr {
|
if tc.wantErr {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue