Skip to content

Commit

Permalink
[no ci] wip
Browse files Browse the repository at this point in the history
  • Loading branch information
3u13r committed Feb 20, 2024
1 parent 270497e commit f68d46d
Show file tree
Hide file tree
Showing 15 changed files with 237 additions and 130 deletions.
1 change: 1 addition & 0 deletions cli/internal/cloudcmd/tfvars.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ func openStackTerraformVars(conf *config.Config, imageRef string) (*terraform.Op
Name: conf.Name,
Cloud: toPtr(conf.Provider.OpenStack.Cloud),
FloatingIPPoolID: conf.Provider.OpenStack.FloatingIPPoolID,
StackITProjectID: conf.Provider.OpenStack.ProjectID,
ImageURL: imageRef,
DirectDownload: *conf.Provider.OpenStack.DirectDownload,
OpenstackUserDomainName: conf.Provider.OpenStack.UserDomainName,
Expand Down
3 changes: 2 additions & 1 deletion cli/internal/terraform/variables.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,8 @@ type OpenStackClusterVariables struct {
// NodeGroups is a map of node groups to create.
NodeGroups map[string]OpenStackNodeGroup `hcl:"node_groups" cty:"node_groups"`
// Cloud is the (optional) name of the OpenStack cloud to use when reading the "clouds.yaml" configuration file. If empty, environment variables are used.
Cloud *string `hcl:"cloud" cty:"cloud"`
Cloud *string `hcl:"cloud" cty:"cloud"`
StackITProjectID string `hcl:"stackit_project_id" cty:"stackit_project_id"`
// FloatingIPPoolID is the ID of the OpenStack floating IP pool to use for public IPs.
FloatingIPPoolID string `hcl:"floating_ip_pool_id" cty:"floating_ip_pool_id"`
// ImageURL is the URL of the OpenStack image to use.
Expand Down
1 change: 1 addition & 0 deletions internal/cloud/openstack/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type imdsAPI interface {
initSecretHash(ctx context.Context) (string, error)
role(ctx context.Context) (role.Role, error)
vpcIP(ctx context.Context) (string, error)
loadBalancerEndpoint(ctx context.Context) (string, error)
}

type serversAPI interface {
Expand Down
34 changes: 20 additions & 14 deletions internal/cloud/openstack/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,22 @@ import (
)

type stubIMDSClient struct {
providerIDResult string
providerIDErr error
nameResult string
nameErr error
projectIDResult string
projectIDErr error
uidResult string
uidErr error
initSecretHashResult string
initSecretHashErr error
roleResult role.Role
roleErr error
vpcIPResult string
vpcIPErr error
providerIDResult string
providerIDErr error
nameResult string
nameErr error
projectIDResult string
projectIDErr error
uidResult string
uidErr error
initSecretHashResult string
initSecretHashErr error
roleResult role.Role
roleErr error
vpcIPResult string
vpcIPErr error
loadBalancerEndpointResult string
loadBalancerEndpointErr error
}

func (c *stubIMDSClient) providerID(_ context.Context) (string, error) {
Expand Down Expand Up @@ -60,6 +62,10 @@ func (c *stubIMDSClient) vpcIP(_ context.Context) (string, error) {
return c.vpcIPResult, c.vpcIPErr
}

func (c *stubIMDSClient) loadBalancerEndpoint(_ context.Context) (string, error) {
return c.loadBalancerEndpointResult, c.loadBalancerEndpointErr
}

type stubServersClient struct {
serversPager stubPager
subnetsPager stubPager
Expand Down
29 changes: 22 additions & 7 deletions internal/cloud/openstack/imds.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,20 @@ func (c *imdsClient) role(ctx context.Context) (role.Role, error) {
return role.FromString(c.cache.Tags.Role), nil
}

func (c *imdsClient) loadBalancerEndpoint(ctx context.Context) (string, error) {
if c.timeForUpdate(c.cacheTime) || c.cache.Tags.LoadBalancerEndpoint == "" {
if err := c.update(ctx); err != nil {
return "", err
}
}

if c.cache.Tags.LoadBalancerEndpoint == "" {
return "", errors.New("unable to get load balancer endpoint")
}

return c.cache.Tags.LoadBalancerEndpoint, nil
}

func (c *imdsClient) authURL(ctx context.Context) (string, error) {
if c.timeForUpdate(c.cacheTime) || c.cache.Tags.AuthURL == "" {
if err := c.update(ctx); err != nil {
Expand Down Expand Up @@ -245,13 +259,14 @@ type metadataResponse struct {
}

type metadataTags struct {
InitSecretHash string `json:"constellation-init-secret-hash,omitempty"`
Role string `json:"constellation-role,omitempty"`
UID string `json:"constellation-uid,omitempty"`
AuthURL string `json:"openstack-auth-url,omitempty"`
UserDomainName string `json:"openstack-user-domain-name,omitempty"`
Username string `json:"openstack-username,omitempty"`
Password string `json:"openstack-password,omitempty"`
InitSecretHash string `json:"constellation-init-secret-hash,omitempty"`
Role string `json:"constellation-role,omitempty"`
UID string `json:"constellation-uid,omitempty"`
AuthURL string `json:"openstack-auth-url,omitempty"`
UserDomainName string `json:"openstack-user-domain-name,omitempty"`
Username string `json:"openstack-username,omitempty"`
Password string `json:"openstack-password,omitempty"`
LoadBalancerEndpoint string `json:"openstack-load-balancer-endpoint,omitempty"`
}

type httpClient interface {
Expand Down
72 changes: 2 additions & 70 deletions internal/cloud/openstack/openstack.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ package openstack

import (
"context"
"errors"
"fmt"
"net/http"
"net/netip"
Expand Down Expand Up @@ -233,80 +232,13 @@ func (c *Cloud) InitSecretHash(ctx context.Context) ([]byte, error) {
// a control plane node.
// TODO(malt3): Rewrite to use real load balancer once it is available.
func (c *Cloud) GetLoadBalancerEndpoint(ctx context.Context) (host, port string, err error) {
host, err = c.getLoadBalancerHost(ctx)
host, err = c.imds.loadBalancerEndpoint(ctx)
if err != nil {
return "", "", fmt.Errorf("getting load balancer host: %w", err)
return "", "", fmt.Errorf("getting load balancer endpoint: %w", err)
}
return host, strconv.FormatInt(constants.KubernetesPort, 10), nil
}

func (c *Cloud) getLoadBalancerHost(ctx context.Context) (string, error) {
uid, err := c.imds.uid(ctx)
if err != nil {
return "", fmt.Errorf("getting uid: %w", err)
}

uidTag := fmt.Sprintf("constellation-uid-%s", uid)

subnet, err := c.getSubnetCIDR(uidTag)
if err != nil {
return "", err
}

srvs, err := c.getServers(uidTag)
if err != nil {
return "", err
}

for _, s := range srvs {
if s.Name == "" {
continue
}
if s.ID == "" {
continue
}
if s.Tags == nil {
continue
}

subnetAddrs, err := parseSeverAddresses(s.Addresses)
if err != nil {
return "", fmt.Errorf("parsing server %q addresses: %w", s.Name, err)
}

// In a best effort approach, we take the first fixed IPv4 address that is outside the subnet
// belonging to our cluster and assume it is the "load balancer" floating ip.
for _, serverSubnet := range subnetAddrs {
for _, addr := range serverSubnet.Addresses {
if addr.Type != floatingIP {
continue
}

if addr.IPVersion != ipV4 {
continue
}

if addr.IP == "" {
continue
}

parsedAddr, err := netip.ParseAddr(addr.IP)
if err != nil {
continue
}

if subnet.Contains(parsedAddr) {
continue
}

return addr.IP, nil
}
}
}

return "", errors.New("no load balancer endpoint found")
}

func (c *Cloud) getSubnetCIDR(uidTag string) (netip.Prefix, error) {
listSubnetsOpts := subnets.ListOpts{Tags: uidTag}
subnetsPage, err := c.api.ListSubnets(listSubnetsOpts).AllPages()
Expand Down
4 changes: 3 additions & 1 deletion terraform/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ go_library(
"infrastructure/iam/gcp/main.tf",
"infrastructure/iam/gcp/outputs.tf",
"infrastructure/iam/gcp/variables.tf",
"infrastructure/openstack/.terraform.lock.hcl",
"infrastructure/openstack/main.tf",
"infrastructure/openstack/modules/instance_group/main.tf",
"infrastructure/openstack/modules/instance_group/outputs.tf",
Expand All @@ -75,6 +74,9 @@ go_library(
"infrastructure/aws/modules/jump_host/output.tf",
"infrastructure/aws/modules/load_balancer_target/output.tf",
"infrastructure/aws/modules/public_private_subnet/output.tf",
"infrastructure/openstack/modules/stackit_loadbalancer/main.tf",
"infrastructure/openstack/modules/stackit_loadbalancer/variables.tf",
"infrastructure/openstack/.terraform.lock.hcl",
],
importpath = "github.com/edgelesssys/constellation/v2/terraform",
visibility = ["//visibility:public"],
Expand Down
36 changes: 27 additions & 9 deletions terraform/infrastructure/openstack/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

71 changes: 51 additions & 20 deletions terraform/infrastructure/openstack/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ terraform {
version = "1.52.1"
}

stackit = {
source = "stackitcloud/stackit"
version = "0.12.0"
}

random = {
source = "hashicorp/random"
version = "3.6.0"
Expand All @@ -16,6 +21,11 @@ provider "openstack" {
cloud = var.cloud
}

provider "stackit" {
region = "eu01"
}


data "openstack_identity_auth_scope_v3" "scope" {
name = "scope"
}
Expand Down Expand Up @@ -159,26 +169,27 @@ resource "openstack_compute_secgroup_v2" "vpc_secgroup" {
}

module "instance_group" {
source = "./modules/instance_group"
for_each = var.node_groups
base_name = local.name
node_group_name = each.key
role = each.value.role
initial_count = each.value.initial_count
disk_size = each.value.state_disk_size
state_disk_type = each.value.state_disk_type
availability_zone = each.value.zone
image_id = openstack_images_image_v2.image_id.image_id
flavor_id = each.value.flavor_id
security_groups = [openstack_compute_secgroup_v2.vpc_secgroup.id]
tags = local.tags
uid = local.uid
network_id = openstack_networking_network_v2.vpc_network.id
init_secret_hash = local.init_secret_hash
identity_internal_url = local.identity_internal_url
openstack_username = var.openstack_username
openstack_password = var.openstack_password
openstack_user_domain_name = var.openstack_user_domain_name
source = "./modules/instance_group"
for_each = var.node_groups
base_name = local.name
node_group_name = each.key
role = each.value.role
initial_count = each.value.initial_count
disk_size = each.value.state_disk_size
state_disk_type = each.value.state_disk_type
availability_zone = each.value.zone
image_id = openstack_images_image_v2.image_id.image_id
flavor_id = each.value.flavor_id
security_groups = [openstack_compute_secgroup_v2.vpc_secgroup.id]
tags = local.tags
uid = local.uid
network_id = openstack_networking_network_v2.vpc_network.id
init_secret_hash = local.init_secret_hash
identity_internal_url = local.identity_internal_url
openstack_username = var.openstack_username
openstack_password = var.openstack_password
openstack_user_domain_name = var.openstack_user_domain_name
openstack_load_balancer_endpoint = openstack_networking_floatingip_v2.public_ip.address
}

resource "openstack_networking_floatingip_v2" "public_ip" {
Expand All @@ -189,6 +200,7 @@ resource "openstack_networking_floatingip_v2" "public_ip" {


resource "openstack_compute_floatingip_associate_v2" "public_ip_associate" {
count = var.cloud == "stackit" ? 0 : 1
floating_ip = openstack_networking_floatingip_v2.public_ip.address
instance_id = module.instance_group["control_plane_default"].instance_ids.0
depends_on = [
Expand All @@ -197,6 +209,25 @@ resource "openstack_compute_floatingip_associate_v2" "public_ip_associate" {
]
}

module "stackit_loadbalancer" {
count = var.cloud == "stackit" ? 1 : 0
source = "./modules/stackit_loadbalancer"
name = local.name
project_id = var.stackit_project_id
member_ips = module.instance_group["control_plane_default"].ips
network_id = openstack_networking_network_v2.vpc_network.id
external_address = openstack_networking_floatingip_v2.public_ip.address
ports = {
kubernetes = local.ports_kubernetes,
bootstrapper = local.ports_bootstrapper,
konnectivity = local.ports_konnectivity,
verify = local.ports_verify,
recovery = local.ports_recovery,
debugd = local.ports_debugd,
}
}


moved {
from = module.instance_group_control_plane
to = module.instance_group["control_plane_default"]
Expand Down
Loading

0 comments on commit f68d46d

Please sign in to comment.