Skip to content

Commit

Permalink
feat: v2 mesh-init command
Browse files Browse the repository at this point in the history
  • Loading branch information
DanStough committed Sep 11, 2023
1 parent 6e8831f commit 4b19620
Show file tree
Hide file tree
Showing 8 changed files with 1,098 additions and 32 deletions.
8 changes: 7 additions & 1 deletion control-plane/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ package main
import (
"os"

"github.com/mitchellh/cli"

cmdACLInit "github.com/hashicorp/consul-k8s/control-plane/subcommand/acl-init"
cmdConnectInit "github.com/hashicorp/consul-k8s/control-plane/subcommand/connect-init"
cmdConsulLogout "github.com/hashicorp/consul-k8s/control-plane/subcommand/consul-logout"
Expand All @@ -18,14 +20,14 @@ import (
cmdGossipEncryptionAutogenerate "github.com/hashicorp/consul-k8s/control-plane/subcommand/gossip-encryption-autogenerate"
cmdInjectConnect "github.com/hashicorp/consul-k8s/control-plane/subcommand/inject-connect"
cmdInstallCNI "github.com/hashicorp/consul-k8s/control-plane/subcommand/install-cni"
cmdMeshInit "github.com/hashicorp/consul-k8s/control-plane/subcommand/mesh-init"
cmdPartitionInit "github.com/hashicorp/consul-k8s/control-plane/subcommand/partition-init"
cmdServerACLInit "github.com/hashicorp/consul-k8s/control-plane/subcommand/server-acl-init"
cmdSyncCatalog "github.com/hashicorp/consul-k8s/control-plane/subcommand/sync-catalog"
cmdTLSInit "github.com/hashicorp/consul-k8s/control-plane/subcommand/tls-init"
cmdVersion "github.com/hashicorp/consul-k8s/control-plane/subcommand/version"
webhookCertManager "github.com/hashicorp/consul-k8s/control-plane/subcommand/webhook-cert-manager"
"github.com/hashicorp/consul-k8s/control-plane/version"
"github.com/mitchellh/cli"
)

// Commands is the mapping of all available consul-k8s commands.
Expand All @@ -43,6 +45,10 @@ func init() {
return &cmdConnectInit.Command{UI: ui}, nil
},

"mesh-init": func() (cli.Command, error) {
return &cmdMeshInit.Command{UI: ui}, nil
},

"inject-connect": func() (cli.Command, error) {
return &cmdInjectConnect.Command{UI: ui}, nil
},
Expand Down
28 changes: 28 additions & 0 deletions control-plane/consul/dataplane_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package consul

import (
"fmt"

"github.com/hashicorp/consul/proto-public/pbdataplane"
)

// NewDataplaneServiceClient creates a pbdataplane.DataplaneServiceClient for gathering proxy bootstrap config.
// It is initialized with a consul-server-connection-manager Watcher to continuously find Consul
// server addresses.
func NewDataplaneServiceClient(watcher ServerConnectionManager) (pbdataplane.DataplaneServiceClient, error) {

// We recycle the GRPC connection from the discovery client because it
// should have all the necessary dial options, including the resolver that
// continuously updates Consul server addresses. Otherwise, a lot of code from consul-server-connection-manager
// would need to be duplicated
state, err := watcher.State()
if err != nil {
return nil, fmt.Errorf("unable to get connection manager state: %w", err)
}
dpClient := pbdataplane.NewDataplaneServiceClient(state.GRPCConn)

return dpClient, nil
}
206 changes: 206 additions & 0 deletions control-plane/consul/dataplane_client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
package consul

import (
"context"
"testing"
"time"

"github.com/google/go-cmp/cmp"
"github.com/hashicorp/consul-server-connection-manager/discovery"
pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1"
"github.com/hashicorp/consul/proto-public/pbdataplane"
pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v1alpha1"
"github.com/hashicorp/consul/proto-public/pbresource"
"github.com/hashicorp/consul/sdk/testutil"
"github.com/hashicorp/go-hclog"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/testing/protocmp"
"google.golang.org/protobuf/types/known/anypb"
)

func Test_NewDataplaneServiceClient(t *testing.T) {

var serverConfig *testutil.TestServerConfig
server, err := testutil.NewTestServerConfigT(t, func(c *testutil.TestServerConfig) {
c.Experiments = []string{"resource-apis"}
serverConfig = c
})
require.NoError(t, err)
defer server.Stop()

server.WaitForLeader(t)
server.WaitForActiveCARoot(t)

t.Logf("server grpc address on %d", serverConfig.Ports.GRPC)

// Create discovery configuration
discoverConfig := discovery.Config{
Addresses: "127.0.0.1",
GRPCPort: serverConfig.Ports.GRPC,
}

opts := hclog.LoggerOptions{Name: "dataplane-service-client"}
logger := hclog.New(&opts)

watcher, err := discovery.NewWatcher(context.Background(), discoverConfig, logger)
require.NoError(t, err)
require.NotNil(t, watcher)

defer watcher.Stop()
go watcher.Run()

// Create a workload and create a proxyConfiguration
createWorkload(t, watcher, "foo")
pc := createProxyConfiguration(t, watcher, "foo")

client, err := NewDataplaneServiceClient(watcher)
require.NoError(t, err)
require.NotNil(t, client)
require.NotNil(t, watcher)

req := &pbdataplane.GetEnvoyBootstrapParamsRequest{
ProxyId: "foo",
Namespace: "default",
Partition: "default",
}

res, err := client.GetEnvoyBootstrapParams(context.Background(), req)
require.NoError(t, err)
require.NotNil(t, res)
require.Equal(t, "foo", res.GetIdentity())
require.Equal(t, "default", res.GetNamespace())
require.Equal(t, "default", res.GetPartition())

if diff := cmp.Diff(pc.BootstrapConfig, res.GetBootstrapConfig(), protocmp.Transform()); diff != "" {
t.Errorf("unexpected difference:\n%v", diff)
}

// NOTE: currently it isn't possible to test that the grpc connection responds to changes in the
// discovery server. The discovery response only includes the IP address of the host, so all servers
// for a local test are de-duplicated as a single entry.
}

func createWorkload(t *testing.T, watcher ServerConnectionManager, name string) {

client, err := NewResourceServiceClient(watcher)
require.NoError(t, err)

workload := &pbcatalog.Workload{
Addresses: []*pbcatalog.WorkloadAddress{
{Host: "10.0.0.1", Ports: []string{"public", "admin", "mesh"}},
},
Ports: map[string]*pbcatalog.WorkloadPort{
"public": {
Port: 80,
Protocol: pbcatalog.Protocol_PROTOCOL_TCP,
},
"admin": {
Port: 8080,
Protocol: pbcatalog.Protocol_PROTOCOL_TCP,
},
"mesh": {
Port: 20000,
Protocol: pbcatalog.Protocol_PROTOCOL_MESH,
},
},
NodeName: "k8s-node-0-virtual",
Identity: name,
}

id := &pbresource.ID{
Name: name,
Type: &pbresource.Type{
Group: "catalog",
GroupVersion: "v1alpha1",
Kind: "Workload",
},
Tenancy: &pbresource.Tenancy{
Partition: "default",
Namespace: "default",
PeerName: "local",
},
}

proto, err := anypb.New(workload)
require.NoError(t, err)

req := &pbresource.WriteRequest{
Resource: &pbresource.Resource{
Id: id,
Data: proto,
},
}

_, err = client.Write(context.Background(), req)
require.NoError(t, err)

resourceHasPersisted(t, client, id)
}

func createProxyConfiguration(t *testing.T, watcher ServerConnectionManager, name string) *pbmesh.ProxyConfiguration {

client, err := NewResourceServiceClient(watcher)
require.NoError(t, err)

pc := &pbmesh.ProxyConfiguration{
Workloads: &pbcatalog.WorkloadSelector{
Names: []string{"foo"},
},
BootstrapConfig: &pbmesh.BootstrapConfig{
StatsBindAddr: "127.0.0.2:1234",
ReadyBindAddr: "127.0.0.3:5678",
},
}

id := &pbresource.ID{
Name: name,
Type: &pbresource.Type{
Group: "mesh",
GroupVersion: "v1alpha1",
Kind: "ProxyConfiguration",
},
Tenancy: &pbresource.Tenancy{
Partition: "default",
Namespace: "default",
PeerName: "local",
},
}

proto, err := anypb.New(pc)
require.NoError(t, err)

req := &pbresource.WriteRequest{
Resource: &pbresource.Resource{
Id: id,
Data: proto,
},
}

_, err = client.Write(context.Background(), req)
require.NoError(t, err)

resourceHasPersisted(t, client, id)
return pc
}

// resourceHasPersisted checks that a recently written resource exists in the Consul
// state store with a valid version. This must be true before a resource is overwritten
// or deleted.
// TODO: refactor so that there isn't an import cycle when using test.ResourceHasPersisted
func resourceHasPersisted(t *testing.T, client pbresource.ResourceServiceClient, id *pbresource.ID) {
req := &pbresource.ReadRequest{Id: id}

require.Eventually(t, func() bool {
res, err := client.Read(context.Background(), req)
if err != nil {
return false
}

if res.GetResource().GetVersion() == "" {
return false
}

return true
}, 5*time.Second,
time.Second)
}
22 changes: 11 additions & 11 deletions control-plane/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@ require (
github.com/hashicorp/consul-k8s/control-plane/cni v0.0.0-20230825213844-4ea04860c5ed
github.com/hashicorp/consul-server-connection-manager v0.1.4
github.com/hashicorp/consul/api v1.10.1-0.20230906155245-56917eb4c968
github.com/hashicorp/consul/proto-public v0.1.2-0.20230906155245-56917eb4c968
github.com/hashicorp/consul/proto-public v0.1.2-0.20230907203049-2e7d95108602
github.com/hashicorp/consul/sdk v0.14.1
github.com/hashicorp/go-bexpr v0.1.11
github.com/hashicorp/go-discover v0.0.0-20230519164032-214571b6a530
github.com/hashicorp/go-hclog v1.5.0
github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/go-netaddrs v0.1.0
github.com/hashicorp/go-rootcerts v1.0.2
github.com/hashicorp/go-uuid v1.0.3
github.com/hashicorp/go-version v1.6.0
github.com/hashicorp/serf v0.10.1
github.com/hashicorp/vault/api v1.8.3
Expand All @@ -33,8 +34,8 @@ require (
github.com/mitchellh/mapstructure v1.5.0
github.com/stretchr/testify v1.8.3
go.uber.org/zap v1.24.0
golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53
golang.org/x/text v0.11.0
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63
golang.org/x/text v0.12.0
golang.org/x/time v0.3.0
gomodules.xyz/jsonpatch/v2 v2.3.0
google.golang.org/grpc v1.55.0
Expand Down Expand Up @@ -104,7 +105,6 @@ require (
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 // indirect
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect
github.com/hashicorp/go-sockaddr v1.0.2 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hashicorp/mdns v1.0.4 // indirect
Expand Down Expand Up @@ -151,14 +151,14 @@ require (
go.opencensus.io v0.24.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
golang.org/x/crypto v0.11.0 // indirect
golang.org/x/mod v0.9.0 // indirect
golang.org/x/net v0.13.0 // indirect
golang.org/x/crypto v0.12.0 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/oauth2 v0.6.0 // indirect
golang.org/x/sync v0.2.0 // indirect
golang.org/x/sys v0.10.0 // indirect
golang.org/x/term v0.10.0 // indirect
golang.org/x/tools v0.7.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/term v0.11.0 // indirect
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect
google.golang.org/api v0.114.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
Expand Down
Loading

0 comments on commit 4b19620

Please sign in to comment.