cli: add support for multiple coordinators

Signed-off-by: Benedict Schlueter <bs@edgeless.systems>
This commit is contained in:
Benedict Schlueter 2022-04-25 17:21:58 +02:00 committed by Benedict Schlüter
parent ff8830e718
commit 49def1e97f
5 changed files with 58 additions and 21 deletions

View File

@ -122,6 +122,7 @@ func initialize(ctx context.Context, cmd *cobra.Command, protCl protoClient, ser
pubKey: flags.userPubKey,
masterSecret: flags.masterSecret,
nodePrivIPs: nodes.PrivateIPs(),
coordinatorPrivIPs: coordinators.PrivateIPs()[1:],
autoscalingNodeGroups: autoscalingNodeGroups,
cloudServiceAccountURI: serviceAccount,
}
@ -161,7 +162,7 @@ func activate(ctx context.Context, cmd *cobra.Command, client protoClient, input
return activationResult{}, err
}
respCl, err := client.Activate(ctx, input.pubKey, input.masterSecret, input.nodePrivIPs, input.autoscalingNodeGroups, input.cloudServiceAccountURI)
respCl, err := client.Activate(ctx, input.pubKey, input.masterSecret, input.nodePrivIPs, input.coordinatorPrivIPs, input.autoscalingNodeGroups, input.cloudServiceAccountURI)
if err != nil {
return activationResult{}, err
}
@ -208,6 +209,7 @@ type activationInput struct {
pubKey []byte
masterSecret []byte
nodePrivIPs []string
coordinatorPrivIPs []string
autoscalingNodeGroups []string
cloudServiceAccountURI string
}
@ -386,12 +388,20 @@ func getScalingGroupsFromConfig(stat state.ConstellationState, config *config.Co
}
func getAWSInstances(stat state.ConstellationState) (coordinators, nodes ScalingGroup, err error) {
coordinatorID, coordinator, err := stat.EC2Instances.GetOne()
coordinatorID, _, err := stat.EC2Instances.GetOne()
if err != nil {
return
}
coordinatorMap := stat.EC2Instances
var coordinatorInstances Instances
for _, node := range coordinatorMap {
coordinatorInstances = append(coordinatorInstances, Instance(node))
}
// GroupID of coordinators is empty, since they currently do not scale.
coordinators = ScalingGroup{Instances: Instances{Instance(coordinator)}, GroupID: ""}
coordinators = ScalingGroup{
Instances: coordinatorInstances,
GroupID: "",
}
nodeMap := stat.EC2Instances.GetOthers(coordinatorID)
if len(nodeMap) == 0 {
@ -411,12 +421,19 @@ func getAWSInstances(stat state.ConstellationState) (coordinators, nodes Scaling
}
func getGCPInstances(stat state.ConstellationState, config *config.Config) (coordinators, nodes ScalingGroup, err error) {
_, coordinator, err := stat.GCPCoordinators.GetOne()
if err != nil {
return
coordinatorMap := stat.GCPCoordinators
if len(coordinatorMap) == 0 {
return ScalingGroup{}, ScalingGroup{}, errors.New("no coordinators available, can't create Constellation without any instance")
}
var coordinatorInstances Instances
for _, node := range coordinatorMap {
coordinatorInstances = append(coordinatorInstances, Instance(node))
}
// GroupID of coordinators is empty, since they currently do not scale.
coordinators = ScalingGroup{Instances: Instances{Instance(coordinator)}, GroupID: ""}
coordinators = ScalingGroup{
Instances: coordinatorInstances,
GroupID: "",
}
nodeMap := stat.GCPNodes
if len(nodeMap) == 0 {
@ -438,13 +455,19 @@ func getGCPInstances(stat state.ConstellationState, config *config.Config) (coor
}
func getAzureInstances(stat state.ConstellationState, config *config.Config) (coordinators, nodes ScalingGroup, err error) {
_, coordinator, err := stat.AzureCoordinators.GetOne()
if err != nil {
return
coordinatorMap := stat.AzureCoordinators
if len(coordinatorMap) == 0 {
return ScalingGroup{}, ScalingGroup{}, errors.New("no coordinators available, can't create Constellation without any instance")
}
var coordinatorInstances Instances
for _, node := range coordinatorMap {
coordinatorInstances = append(coordinatorInstances, Instance(node))
}
// GroupID of coordinators is empty, since they currently do not scale.
coordinators = ScalingGroup{Instances: Instances{Instance(coordinator)}, GroupID: ""}
coordinators = ScalingGroup{
Instances: coordinatorInstances,
GroupID: "",
}
nodeMap := stat.AzureNodes
if len(nodeMap) == 0 {
return ScalingGroup{}, ScalingGroup{}, errors.New("no nodes available, can't create Constellation with one instance")

View File

@ -10,5 +10,5 @@ import (
type protoClient interface {
Connect(ip, port string, validators []atls.Validator) error
Close() error
Activate(ctx context.Context, userPublicKey, masterSecret []byte, endpoints, autoscalingNodeGroups []string, cloudServiceAccountURI string) (proto.ActivationResponseClient, error)
Activate(ctx context.Context, userPublicKey, masterSecret []byte, nodeIPs, coordinatorIPs, autoscalingNodeGroups []string, cloudServiceAccountURI string) (proto.ActivationResponseClient, error)
}

View File

@ -19,7 +19,8 @@ type stubProtoClient struct {
activateUserPublicKey []byte
activateMasterSecret []byte
activateEndpoints []string
activateNodeIPs []string
activateCoordinatorIPs []string
activateAutoscalingNodeGroups []string
cloudServiceAccountURI string
}
@ -34,16 +35,21 @@ func (c *stubProtoClient) Close() error {
return c.closeErr
}
func (c *stubProtoClient) Activate(ctx context.Context, userPublicKey, masterSecret []byte, endpoints []string, autoscalingNodeGroups []string, cloudServiceAccountURI string) (proto.ActivationResponseClient, error) {
func (c *stubProtoClient) Activate(ctx context.Context, userPublicKey, masterSecret []byte, nodeIPs, coordinatorIPs []string, autoscalingNodeGroups []string, cloudServiceAccountURI string) (proto.ActivationResponseClient, error) {
c.activateUserPublicKey = userPublicKey
c.activateMasterSecret = masterSecret
c.activateEndpoints = endpoints
c.activateNodeIPs = nodeIPs
c.activateCoordinatorIPs = coordinatorIPs
c.activateAutoscalingNodeGroups = autoscalingNodeGroups
c.cloudServiceAccountURI = cloudServiceAccountURI
return c.respClient, c.activateErr
}
func (c *stubProtoClient) ActivateAdditionalCoordinators(ctx context.Context, ips []string) error {
return c.activateErr
}
type stubActivationRespClient struct {
nextLogErr *error
getKubeconfigErr error
@ -106,13 +112,20 @@ func (c *fakeProtoClient) Close() error {
return nil
}
func (c *fakeProtoClient) Activate(ctx context.Context, userPublicKey, masterSecret []byte, endpoints []string, autoscalingNodeGroups []string, cloudServiceAccountURI string) (proto.ActivationResponseClient, error) {
func (c *fakeProtoClient) Activate(ctx context.Context, userPublicKey, masterSecret []byte, nodeIPs, coordinatorIPs []string, autoscalingNodeGroups []string, cloudServiceAccountURI string) (proto.ActivationResponseClient, error) {
if !c.conn {
return nil, errors.New("client is not connected")
}
return c.respClient, nil
}
func (c *fakeProtoClient) ActivateAdditionalCoordinators(ctx context.Context, ips []string) error {
if !c.conn {
return errors.New("client is not connected")
}
return nil
}
type fakeActivationRespClient struct {
responses []fakeActivationRespMessage
kubeconfig string

View File

@ -64,14 +64,14 @@ func (c *Client) Close() error {
// Activate activates the Constellation coordinator via a grpc call.
// The handed IP addresses must be the private IP addresses of running AWS or GCP instances,
// and the userPublicKey is the VPN key of the users WireGuard interface.
func (c *Client) Activate(ctx context.Context, userPublicKey, masterSecret []byte, ips, autoscalingNodeGroups []string, cloudServiceAccountURI string) (ActivationResponseClient, error) {
func (c *Client) Activate(ctx context.Context, userPublicKey, masterSecret []byte, nodeIPs, coordinatorIPs, autoscalingNodeGroups []string, cloudServiceAccountURI string) (ActivationResponseClient, error) {
if c.avpn == nil {
return nil, errors.New("client is not connected")
}
if len(userPublicKey) == 0 {
return nil, errors.New("parameter userPublicKey is empty")
}
if len(ips) == 0 {
if len(nodeIPs) == 0 {
return nil, errors.New("parameter ips is empty")
}
@ -82,7 +82,8 @@ func (c *Client) Activate(ctx context.Context, userPublicKey, masterSecret []byt
avpnRequest := &pubproto.ActivateAsCoordinatorRequest{
AdminVpnPubKey: pubKey[:],
NodePublicIps: ips,
NodePublicIps: nodeIPs,
CoordinatorPublicIps: coordinatorIPs,
AutoscalingNodeGroups: autoscalingNodeGroups,
MasterSecret: masterSecret,
KmsUri: kms.ClusterKMSURI,

View File

@ -120,7 +120,7 @@ func TestActivate(t *testing.T) {
if tc.avpn != nil {
client.avpn = tc.avpn
}
_, err := client.Activate(context.Background(), []byte(tc.userPublicKey), []byte("Constellation"), tc.ips, nil, "serviceaccount://test")
_, err := client.Activate(context.Background(), []byte(tc.userPublicKey), []byte("Constellation"), tc.ips, nil, nil, "serviceaccount://test")
if tc.errExpected {
assert.Error(err)
} else {