Skip to content

Commit

Permalink
Target node health controller instead of demo resources
Browse files Browse the repository at this point in the history
  • Loading branch information
boxofrad committed May 22, 2023
1 parent 157dbee commit e48194e
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 56 deletions.
2 changes: 0 additions & 2 deletions test/integration/consul-container/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ require (
github.com/avast/retry-go v3.0.0+incompatible
github.com/docker/docker v23.0.6+incompatible
github.com/docker/go-connections v0.4.0
github.com/hashicorp/consul v0.0.0-00010101000000-000000000000
github.com/hashicorp/consul/api v1.20.0
github.com/hashicorp/consul/envoyextensions v0.1.2
github.com/hashicorp/consul/proto-public v0.2.1
Expand Down Expand Up @@ -90,7 +89,6 @@ require (
)

replace (
github.com/hashicorp/consul => ../../..
github.com/hashicorp/consul/api => ../../../api
github.com/hashicorp/consul/envoyextensions => ../../../envoyextensions
github.com/hashicorp/consul/proto-public => ../../../proto-public
Expand Down
2 changes: 1 addition & 1 deletion test/integration/consul-container/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
Expand Down
132 changes: 79 additions & 53 deletions test/integration/consul-container/test/resources/resources_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,96 +4,122 @@ import (
"testing"

"github.com/stretchr/testify/require"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/types/known/anypb"

"github.com/hashicorp/consul/sdk/testutil"
"github.com/hashicorp/consul/sdk/testutil/retry"
libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster"
libtopology "github.com/hashicorp/consul/test/integration/consul-container/libs/topology"

pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1"
pbresource "github.com/hashicorp/consul/proto-public/pbresource"
pbdemov2 "github.com/hashicorp/consul/proto/private/pbdemo/v2"
)

// TestResources exercises the full Resource Service and Controller stack.
func TestResources(t *testing.T) {
t.Parallel()

ctx := testutil.TestContext(t)

cluster, _, _ := libtopology.NewCluster(t, &libtopology.ClusterConfig{
NumServers: 2,
Cmd: `-hcl=enable_dev_resources = true`,
BuildOpts: &libcluster.BuildOptions{Datacenter: "dc1"},
})

// Write an artist resource to a follower to exercise leader forwarding.
// This test specifically targets a follower because:
//
// 1. It ensures leader-forwarding works (as only leaders can process writes).
// 2. It exercises the full Raft replication and FSM flow (as writes will only
// be readable once they are replicated to the follower).
followers, err := cluster.Followers()
require.NoError(t, err)
client := pbresource.NewResourceServiceClient(followers[0].GetGRPCConn())

conn := followers[0].GetGRPCConn()
client := pbresource.NewResourceServiceClient(conn)
ctx := testutil.TestContext(t)

artist, err := anypb.New(&pbdemov2.Artist{
Name: "Five Iron Frenzy",
Genre: pbdemov2.Genre_GENRE_SKA,
// Write a Node and HealthStatus resource. We want to observe the node health
// controller running (to exercise the full controller runtime machinery) and
// later, observe the deletion of the Node cascading to the HealthStatus.
nodeRsp, err := client.Write(ctx, &pbresource.WriteRequest{
Resource: &pbresource.Resource{
Id: &pbresource.ID{
Type: typeNode,
Tenancy: tenancyDefault,
Name: "node1",
},
Data: any(t, &pbcatalog.Node{
Addresses: []*pbcatalog.NodeAddress{
{Host: "127.0.0.1"},
},
}),
},
})
require.NoError(t, err)

writeRsp, err := client.Write(ctx, &pbresource.WriteRequest{
statusRsp, err := client.Write(ctx, &pbresource.WriteRequest{
Resource: &pbresource.Resource{
Id: &pbresource.ID{
Type: &pbresource.Type{
Group: "demo",
GroupVersion: "v2",
Kind: "artist",
},
Tenancy: &pbresource.Tenancy{
Partition: "default",
PeerName: "local",
Namespace: "default",
},
Name: "five-iron-frenzy",
Type: typeHealthStatus,
Tenancy: tenancyDefault,
Name: "node1-http",
},
Data: artist,
Owner: nodeRsp.Resource.Id,
Data: any(t, &pbcatalog.HealthStatus{
Type: "http",
Status: pbcatalog.Health_HEALTH_MAINTENANCE,
}),
},
})
require.NoError(t, err)

// Wait for controller to run and update the artist's status. Also checks
// leader to follower replication is working.
// Check that the node health controller ran and updated the node's status.
//
// We don't actually care _what_ it wrote to the status in this test, as we're
// just trying to exercise the controller runtime.
retry.Run(t, func(r *retry.R) {
readRsp, err := client.Read(ctx, &pbresource.ReadRequest{Id: writeRsp.Resource.Id})
readRsp, err := client.Read(ctx, &pbresource.ReadRequest{
Id: nodeRsp.Resource.Id,
})
require.NoError(r, err)
require.NotNil(r, readRsp.Resource.Status)
require.Contains(r, readRsp.Resource.Status, "consul.io/artist-controller")
})

// Controller will create albums for the artist.
listRsp, err := client.List(ctx, &pbresource.ListRequest{
Type: &pbresource.Type{
Group: "demo",
GroupVersion: "v2",
Kind: "album",
},
Tenancy: writeRsp.Resource.Id.Tenancy,
require.Contains(r, readRsp.Resource.Status, "consul.io/node-health")
})
require.NoError(t, err)
require.Len(t, listRsp.Resources, 3)

// Delete the artist and check the albums are also cleaned up.
_, err = client.Delete(ctx, &pbresource.DeleteRequest{Id: writeRsp.Resource.Id})
// Delete the node and check it cascades to also delete the HealthStatus.
_, err = client.Delete(ctx, &pbresource.DeleteRequest{Id: nodeRsp.Resource.Id})
require.NoError(t, err)

retry.Run(t, func(r *retry.R) {
listRsp, err := client.List(ctx, &pbresource.ListRequest{
Type: &pbresource.Type{
Group: "demo",
GroupVersion: "v2",
Kind: "album",
},
Tenancy: writeRsp.Resource.Id.Tenancy,
})
require.NoError(r, err)
require.Empty(r, listRsp.Resources)
_, err = client.Read(ctx, &pbresource.ReadRequest{Id: statusRsp.Resource.Id})
require.Error(r, err)
require.Equal(r, codes.NotFound.String(), status.Code(err).String())
})
}

func any(t *testing.T, m protoreflect.ProtoMessage) *anypb.Any {
t.Helper()

any, err := anypb.New(m)
require.NoError(t, err)

return any
}

var (
tenancyDefault = &pbresource.Tenancy{
Partition: "default",
PeerName: "local",
Namespace: "default",
}

typeNode = &pbresource.Type{
Group: "catalog",
GroupVersion: "v1alpha1",
Kind: "Node",
}

typeHealthStatus = &pbresource.Type{
Group: "catalog",
GroupVersion: "v1alpha1",
Kind: "HealthStatus",
}
)

0 comments on commit e48194e

Please sign in to comment.