mirror of https://github.com/status-im/consul.git
resource: add v2tenancy feature flag to deployer tests (#19774)
This commit is contained in:
parent
8f7f15e430
commit
2d1f308138
|
@ -324,6 +324,17 @@ func (client *Client) WaitForResourceState(t T, id *pbresource.ID, verify func(T
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (client *Client) WaitForResourceExists(t T, id *pbresource.ID) *pbresource.Resource {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
var res *pbresource.Resource
|
||||||
|
client.retry(t, func(r *retry.R) {
|
||||||
|
res = client.RequireResourceExists(r, id)
|
||||||
|
})
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
func (client *Client) WaitForDeletion(t T, id *pbresource.ID) {
|
func (client *Client) WaitForDeletion(t T, id *pbresource.ID) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
SHELL := /bin/bash
|
SHELL := /bin/bash
|
||||||
|
|
||||||
.PHONY: noop
|
.PHONY: noop
|
||||||
noop:
|
noop: help
|
||||||
|
|
||||||
##@ Build
|
##@ Build
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ These should use the [testing/deployer framework](../testing/deployer) to bring
|
||||||
up some local testing infrastructure and fixtures to run test assertions against.
|
up some local testing infrastructure and fixtures to run test assertions against.
|
||||||
|
|
||||||
Where reasonably possible, try to bring up infrastructure interesting enough to
|
Where reasonably possible, try to bring up infrastructure interesting enough to
|
||||||
be able to run many related sorts of test against it, rather than waiting for
|
be able to run many related sorts of tests against it, rather than waiting for
|
||||||
many similar clusters to be provisioned and torn down. This will help ensure
|
many similar clusters to be provisioned and torn down. This will help ensure
|
||||||
that the integration tests do not consume CPU cycles needlessly.
|
that the integration tests do not consume CPU cycles needlessly.
|
||||||
|
|
||||||
|
|
|
@ -6,17 +6,17 @@ package connect
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/api"
|
"github.com/hashicorp/consul/api"
|
||||||
|
"github.com/hashicorp/consul/test-integ/topoutil"
|
||||||
"github.com/hashicorp/consul/test/integration/consul-container/libs/utils"
|
"github.com/hashicorp/consul/test/integration/consul-container/libs/utils"
|
||||||
"github.com/hashicorp/consul/testing/deployer/sprawl/sprawltest"
|
"github.com/hashicorp/consul/testing/deployer/sprawl/sprawltest"
|
||||||
"github.com/hashicorp/consul/testing/deployer/topology"
|
"github.com/hashicorp/consul/testing/deployer/topology"
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
|
|
||||||
"github.com/hashicorp/consul/test-integ/topoutil"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Test_Snapshot_Restore_Agentless verifies consul agent can continue
|
// Test_Snapshot_Restore_Agentless verifies consul agent can continue
|
||||||
// to push envoy confgi after restoring from a snapshot.
|
// to push envoy config after restoring from a snapshot.
|
||||||
//
|
//
|
||||||
// - This test is to detect server agent frozen after restoring from a snapshot
|
// - This test is to detect server agent frozen after restoring from a snapshot
|
||||||
// (https://github.com/hashicorp/consul/pull/18636)
|
// (https://github.com/hashicorp/consul/pull/18636)
|
||||||
|
@ -164,7 +164,7 @@ func Test_Snapshot_Restore_Agentless(t *testing.T) {
|
||||||
asserter.HTTPStatus(t, staticServer, staticServer.Port, 200)
|
asserter.HTTPStatus(t, staticServer, staticServer.Port, 200)
|
||||||
|
|
||||||
t.Log("Take a snapshot of the cluster and restore ...")
|
t.Log("Take a snapshot of the cluster and restore ...")
|
||||||
err := sp.SnapshotSave("dc1")
|
err := sp.SnapshotSaveAndRestore("dc1")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Shutdown existing static-server
|
// Shutdown existing static-server
|
||||||
|
|
|
@ -0,0 +1,166 @@
|
||||||
|
// Copyright (c) HashiCorp, Inc.
|
||||||
|
// SPDX-License-Identifier: BUSL-1.1
|
||||||
|
|
||||||
|
package tenancy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/metadata"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/proto-public/pbresource"
|
||||||
|
"github.com/hashicorp/consul/sdk/testutil"
|
||||||
|
"github.com/hashicorp/consul/sdk/testutil/retry"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This duplicates a subset of internal/resource/resourcetest/client.go so
|
||||||
|
// we're not importing consul internals integration tests.
|
||||||
|
//
|
||||||
|
// TODO: Move to a general package if used more widely.
|
||||||
|
|
||||||
|
// T represents the subset of testing.T methods that will be used
|
||||||
|
// by the various functionality in this package
|
||||||
|
type T interface {
|
||||||
|
Helper()
|
||||||
|
Log(args ...interface{})
|
||||||
|
Logf(format string, args ...interface{})
|
||||||
|
Errorf(format string, args ...interface{})
|
||||||
|
Fatalf(format string, args ...interface{})
|
||||||
|
FailNow()
|
||||||
|
Cleanup(func())
|
||||||
|
}
|
||||||
|
|
||||||
|
type ClientOption func(*Client)
|
||||||
|
|
||||||
|
func WithACLToken(token string) ClientOption {
|
||||||
|
return func(c *Client) {
|
||||||
|
c.token = token
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Client decorates a resource service client with helper functions to assist
|
||||||
|
// with integration testing.
|
||||||
|
type Client struct {
|
||||||
|
pbresource.ResourceServiceClient
|
||||||
|
|
||||||
|
timeout time.Duration
|
||||||
|
wait time.Duration
|
||||||
|
token string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewClient(client pbresource.ResourceServiceClient, opts ...ClientOption) *Client {
|
||||||
|
c := &Client{
|
||||||
|
ResourceServiceClient: client,
|
||||||
|
timeout: 7 * time.Second,
|
||||||
|
wait: 50 * time.Millisecond,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewClientWithACLToken(client pbresource.ResourceServiceClient, token string) *Client {
|
||||||
|
return NewClient(client, WithACLToken(token))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *Client) SetRetryerConfig(timeout time.Duration, wait time.Duration) {
|
||||||
|
client.timeout = timeout
|
||||||
|
client.wait = wait
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *Client) retry(t T, fn func(r *retry.R)) {
|
||||||
|
t.Helper()
|
||||||
|
retryer := &retry.Timer{Timeout: client.timeout, Wait: client.wait}
|
||||||
|
retry.RunWith(retryer, t, fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *Client) Context(t T) context.Context {
|
||||||
|
ctx := testutil.TestContext(t)
|
||||||
|
|
||||||
|
if client.token != "" {
|
||||||
|
md := metadata.New(map[string]string{
|
||||||
|
"x-consul-token": client.token,
|
||||||
|
})
|
||||||
|
ctx = metadata.NewOutgoingContext(ctx, md)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *Client) RequireResourceNotFound(t T, id *pbresource.ID) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
rsp, err := client.Read(client.Context(t), &pbresource.ReadRequest{Id: id})
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Equal(t, codes.NotFound, status.Code(err))
|
||||||
|
require.Nil(t, rsp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *Client) RequireResourceExists(t T, id *pbresource.ID) *pbresource.Resource {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
rsp, err := client.Read(client.Context(t), &pbresource.ReadRequest{Id: id})
|
||||||
|
require.NoError(t, err, "error reading %s with type %s", id.Name, ToGVK(id.Type))
|
||||||
|
require.NotNil(t, rsp)
|
||||||
|
return rsp.Resource
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToGVK(resourceType *pbresource.Type) string {
|
||||||
|
return fmt.Sprintf("%s.%s.%s", resourceType.Group, resourceType.GroupVersion, resourceType.Kind)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *Client) WaitForResourceExists(t T, id *pbresource.ID) *pbresource.Resource {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
var res *pbresource.Resource
|
||||||
|
client.retry(t, func(r *retry.R) {
|
||||||
|
res = client.RequireResourceExists(r, id)
|
||||||
|
})
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *Client) WaitForDeletion(t T, id *pbresource.ID) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
client.retry(t, func(r *retry.R) {
|
||||||
|
client.RequireResourceNotFound(r, id)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustDelete will delete a resource by its id, retrying if necessary and fail the test
|
||||||
|
// if it cannot delete it within the timeout. The clients request delay settings are
|
||||||
|
// taken into account with this operation.
|
||||||
|
func (client *Client) MustDelete(t T, id *pbresource.ID) {
|
||||||
|
t.Helper()
|
||||||
|
client.retryDelete(t, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *Client) retryDelete(t T, id *pbresource.ID) {
|
||||||
|
t.Helper()
|
||||||
|
ctx := client.Context(t)
|
||||||
|
|
||||||
|
client.retry(t, func(r *retry.R) {
|
||||||
|
_, err := client.Delete(ctx, &pbresource.DeleteRequest{Id: id})
|
||||||
|
if status.Code(err) == codes.NotFound {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// codes.Aborted indicates a CAS failure and that the delete request should
|
||||||
|
// be retried. Anything else should be considered an unrecoverable error.
|
||||||
|
if err != nil && status.Code(err) != codes.Aborted {
|
||||||
|
r.Stop(fmt.Errorf("failed to delete the resource: %w", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
require.NoError(r, err)
|
||||||
|
})
|
||||||
|
}
|
|
@ -13,7 +13,7 @@ import (
|
||||||
"github.com/hashicorp/consul/testing/deployer/topology"
|
"github.com/hashicorp/consul/testing/deployer/topology"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (g *Generator) generateAgentHCL(node *topology.Node, enableV2 bool) string {
|
func (g *Generator) generateAgentHCL(node *topology.Node, enableV2, enableV2Tenancy bool) string {
|
||||||
if !node.IsAgent() {
|
if !node.IsAgent() {
|
||||||
panic("generateAgentHCL only applies to agents")
|
panic("generateAgentHCL only applies to agents")
|
||||||
}
|
}
|
||||||
|
@ -35,8 +35,15 @@ func (g *Generator) generateAgentHCL(node *topology.Node, enableV2 bool) string
|
||||||
b.add("enable_debug", true)
|
b.add("enable_debug", true)
|
||||||
b.add("use_streaming_backend", true)
|
b.add("use_streaming_backend", true)
|
||||||
|
|
||||||
|
var experiments []string
|
||||||
if enableV2 {
|
if enableV2 {
|
||||||
b.addSlice("experiments", []string{"resource-apis"})
|
experiments = append(experiments, "resource-apis")
|
||||||
|
}
|
||||||
|
if enableV2Tenancy {
|
||||||
|
experiments = append(experiments, "v2tenancy")
|
||||||
|
}
|
||||||
|
if len(experiments) > 0 {
|
||||||
|
b.addSlice("experiments", experiments)
|
||||||
}
|
}
|
||||||
|
|
||||||
// speed up leaves
|
// speed up leaves
|
||||||
|
|
|
@ -67,7 +67,7 @@ func (g *Generator) generateNodeContainers(
|
||||||
}{
|
}{
|
||||||
terraformPod: pod,
|
terraformPod: pod,
|
||||||
ImageResource: DockerImageResourceName(node.Images.Consul),
|
ImageResource: DockerImageResourceName(node.Images.Consul),
|
||||||
HCL: g.generateAgentHCL(node, cluster.EnableV2 && node.IsServer()),
|
HCL: g.generateAgentHCL(node, cluster.EnableV2 && node.IsServer(), cluster.EnableV2Tenancy && node.IsServer()),
|
||||||
EnterpriseLicense: g.license,
|
EnterpriseLicense: g.license,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,13 +17,14 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
retry "github.com/avast/retry-go"
|
retry "github.com/avast/retry-go"
|
||||||
"github.com/hashicorp/consul/api"
|
|
||||||
"github.com/hashicorp/consul/proto-public/pbresource"
|
|
||||||
"github.com/hashicorp/go-hclog"
|
|
||||||
"github.com/hashicorp/go-multierror"
|
|
||||||
"github.com/mitchellh/copystructure"
|
"github.com/mitchellh/copystructure"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-hclog"
|
||||||
|
"github.com/hashicorp/go-multierror"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/api"
|
||||||
|
"github.com/hashicorp/consul/proto-public/pbresource"
|
||||||
"github.com/hashicorp/consul/testing/deployer/sprawl/internal/runner"
|
"github.com/hashicorp/consul/testing/deployer/sprawl/internal/runner"
|
||||||
"github.com/hashicorp/consul/testing/deployer/sprawl/internal/secrets"
|
"github.com/hashicorp/consul/testing/deployer/sprawl/internal/secrets"
|
||||||
"github.com/hashicorp/consul/testing/deployer/sprawl/internal/tfgen"
|
"github.com/hashicorp/consul/testing/deployer/sprawl/internal/tfgen"
|
||||||
|
@ -405,8 +406,8 @@ func (s *Sprawl) RelaunchWithPhase(
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SnapshotSave saves a snapshot of a cluster and restore with the snapshot
|
// SnapshotSaveAndRestore saves a snapshot of a cluster and then restores the snapshot
|
||||||
func (s *Sprawl) SnapshotSave(clusterName string) error {
|
func (s *Sprawl) SnapshotSaveAndRestore(clusterName string) error {
|
||||||
cluster, ok := s.topology.Clusters[clusterName]
|
cluster, ok := s.topology.Clusters[clusterName]
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("no such cluster: %s", clusterName)
|
return fmt.Errorf("no such cluster: %s", clusterName)
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
package topology
|
package topology
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DefaultConsulImage = "hashicorp/consul:1.17.0"
|
DefaultConsulCEImage = "hashicorp/consul:1.17.0"
|
||||||
DefaultConsulEnterpriseImage = "hashicorp/consul-enterprise:1.17.0-ent"
|
DefaultConsulEnterpriseImage = "hashicorp/consul-enterprise:1.17.0-ent"
|
||||||
DefaultEnvoyImage = "envoyproxy/envoy:v1.27.2"
|
DefaultEnvoyImage = "envoyproxy/envoy:v1.27.2"
|
||||||
DefaultDataplaneImage = "hashicorp/consul-dataplane:1.3.0"
|
DefaultDataplaneImage = "hashicorp/consul-dataplane:1.3.0"
|
||||||
|
|
|
@ -122,7 +122,7 @@ func (i Images) OverrideWith(i2 Images) Images {
|
||||||
func DefaultImages() Images {
|
func DefaultImages() Images {
|
||||||
return Images{
|
return Images{
|
||||||
Consul: "",
|
Consul: "",
|
||||||
ConsulCE: DefaultConsulImage,
|
ConsulCE: DefaultConsulCEImage,
|
||||||
ConsulEnterprise: DefaultConsulEnterpriseImage,
|
ConsulEnterprise: DefaultConsulEnterpriseImage,
|
||||||
Envoy: DefaultEnvoyImage,
|
Envoy: DefaultEnvoyImage,
|
||||||
Dataplane: DefaultDataplaneImage,
|
Dataplane: DefaultDataplaneImage,
|
||||||
|
|
|
@ -286,6 +286,10 @@ type Cluster struct {
|
||||||
// EnableV2 activates V2 on the servers. If any node in the cluster needs
|
// EnableV2 activates V2 on the servers. If any node in the cluster needs
|
||||||
// V2 this will be turned on automatically.
|
// V2 this will be turned on automatically.
|
||||||
EnableV2 bool `json:",omitempty"`
|
EnableV2 bool `json:",omitempty"`
|
||||||
|
|
||||||
|
// EnableV2Tenancy activates V2 tenancy on the servers. If not enabled,
|
||||||
|
// V2 resources are bridged to V1 tenancy counterparts.
|
||||||
|
EnableV2Tenancy bool `json:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cluster) inheritFromExisting(existing *Cluster) {
|
func (c *Cluster) inheritFromExisting(existing *Cluster) {
|
||||||
|
|
|
@ -8,7 +8,7 @@ cd "$(dirname "$0")"
|
||||||
|
|
||||||
###
|
###
|
||||||
# This script will update the default image names to the latest released versions of
|
# This script will update the default image names to the latest released versions of
|
||||||
# Consul, Consul Enterprise, and Consul Dataplane.
|
# Consul CE, Consul Enterprise, and Consul Dataplane.
|
||||||
#
|
#
|
||||||
# For Envoy, it will interrogate the latest version of Consul for it's maximum supported
|
# For Envoy, it will interrogate the latest version of Consul for it's maximum supported
|
||||||
# Envoy version and use that.
|
# Envoy version and use that.
|
||||||
|
@ -50,7 +50,7 @@ cat > topology/default_versions.go <<EOF
|
||||||
package topology
|
package topology
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DefaultConsulImage = "hashicorp/consul:${consul_version}"
|
DefaultConsulCEImage = "hashicorp/consul:${consul_version}"
|
||||||
DefaultConsulEnterpriseImage = "hashicorp/consul-enterprise:${consul_version}-ent"
|
DefaultConsulEnterpriseImage = "hashicorp/consul-enterprise:${consul_version}-ent"
|
||||||
DefaultEnvoyImage = "envoyproxy/envoy:v${envoy_version}"
|
DefaultEnvoyImage = "envoyproxy/envoy:v${envoy_version}"
|
||||||
DefaultDataplaneImage = "hashicorp/consul-dataplane:${dataplane_version}"
|
DefaultDataplaneImage = "hashicorp/consul-dataplane:${dataplane_version}"
|
||||||
|
|
Loading…
Reference in New Issue