APIGW Normalize Status Conditions (#16994)
* normalize status conditions for gateways and routes * Added tests for checking condition status and panic conditions for validating combinations, added dummy code for fsm store * get rid of unneeded gateway condition generator struct * Remove unused file * run go mod tidy * Update tests, add conflicted gateway status * put back removed status for test * Fix linting violation, remove custom conflicted status * Update fsm commands oss * Fix incorrect combination of type/condition/status * cleaning up from PR review * Change "invalidCertificate" to be of accepted status * Move status condition enums into api package * Update gateways controller and generated code * Update conditions in fsm oss tests * run go mod tidy on consul-container module to fix linting * Fix type for gateway endpoint test * go mod tidy from changes to api * go mod tidy on troubleshoot * Fix route conflicted reason * fix route conflict reason rename * Fix text for gateway conflicted status * Add valid certificate ref condition setting * Revert change to resolved refs to be handled in future PR
This commit is contained in:
parent
40dd8ce65b
commit
c5b7164b16
|
@ -13,11 +13,6 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-raftchunking"
|
||||
raftchunkingtypes "github.com/hashicorp/go-raftchunking/types"
|
||||
"github.com/hashicorp/go-uuid"
|
||||
"github.com/hashicorp/raft"
|
||||
"github.com/hashicorp/serf/coordinate"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -34,6 +29,11 @@ import (
|
|||
"github.com/hashicorp/consul/proto/private/prototest"
|
||||
"github.com/hashicorp/consul/sdk/testutil"
|
||||
"github.com/hashicorp/consul/types"
|
||||
"github.com/hashicorp/go-raftchunking"
|
||||
raftchunkingtypes "github.com/hashicorp/go-raftchunking/types"
|
||||
"github.com/hashicorp/go-uuid"
|
||||
"github.com/hashicorp/raft"
|
||||
"github.com/hashicorp/serf/coordinate"
|
||||
)
|
||||
|
||||
func generateUUID() (ret string) {
|
||||
|
@ -1372,9 +1372,10 @@ func TestFSM_ConfigEntry_StatusCAS(t *testing.T) {
|
|||
EnterpriseMeta: *structs.DefaultEnterpriseMetaInDefaultPartition(),
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{{
|
||||
Status: "Foo",
|
||||
Status: string(api.ConditionStatusTrue),
|
||||
}},
|
||||
}}
|
||||
},
|
||||
}
|
||||
|
||||
// Create a new request.
|
||||
req := &structs.ConfigEntryRequest{
|
||||
|
@ -1403,7 +1404,7 @@ func TestFSM_ConfigEntry_StatusCAS(t *testing.T) {
|
|||
// do a status update
|
||||
entry.Status = structs.Status{
|
||||
Conditions: []structs.Condition{{
|
||||
Status: "Foo",
|
||||
Status: string(api.ConditionStatusTrue),
|
||||
}},
|
||||
}
|
||||
req = &structs.ConfigEntryRequest{
|
||||
|
@ -1427,7 +1428,7 @@ func TestFSM_ConfigEntry_StatusCAS(t *testing.T) {
|
|||
entry.RaftIndex.ModifyIndex = 2
|
||||
conditions := config.(*structs.APIGatewayConfigEntry).Status.Conditions
|
||||
require.Len(t, conditions, 1)
|
||||
require.Equal(t, "Foo", conditions[0].Status)
|
||||
require.Equal(t, string(api.ConditionStatusTrue), conditions[0].Status)
|
||||
}
|
||||
|
||||
// attempt to change the status with a regular update and make sure it's ignored
|
||||
|
@ -1456,7 +1457,7 @@ func TestFSM_ConfigEntry_StatusCAS(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
conditions := config.(*structs.APIGatewayConfigEntry).Status.Conditions
|
||||
require.Len(t, conditions, 1)
|
||||
require.Equal(t, "Foo", conditions[0].Status)
|
||||
require.Equal(t, string(api.ConditionStatusTrue), conditions[0].Status)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,80 +0,0 @@
|
|||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package consul
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/consul/acl"
|
||||
"github.com/hashicorp/consul/agent/consul/fsm"
|
||||
"github.com/hashicorp/consul/agent/structs"
|
||||
)
|
||||
|
||||
// FSMDataStore implements the DataStore interface using the Consul server and finite state manager.
|
||||
type FSMDataStore struct {
|
||||
server *Server
|
||||
fsm *fsm.FSM
|
||||
}
|
||||
|
||||
func NewFSMDataStore(server *Server, fsm *fsm.FSM) *FSMDataStore {
|
||||
return &FSMDataStore{
|
||||
server: server,
|
||||
fsm: fsm,
|
||||
}
|
||||
}
|
||||
|
||||
// GetConfigEntry takes in a kind, name, and meta and returns a configentry and an error from the FSM state
|
||||
func (f *FSMDataStore) GetConfigEntry(kind string, name string, meta *acl.EnterpriseMeta) (structs.ConfigEntry, error) {
|
||||
store := f.fsm.State()
|
||||
|
||||
_, entry, err := store.ConfigEntry(nil, kind, name, meta)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return entry, nil
|
||||
}
|
||||
|
||||
// GetConfigEntriesByKind takes in a kind and returns all instances of that kind of config entry from the FSM state
|
||||
func (f *FSMDataStore) GetConfigEntriesByKind(kind string) ([]structs.ConfigEntry, error) {
|
||||
store := f.fsm.State()
|
||||
|
||||
_, entries, err := store.ConfigEntriesByKind(nil, kind, acl.WildcardEnterpriseMeta())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return entries, nil
|
||||
}
|
||||
|
||||
// Update takes a config entry and upserts it in the FSM state
|
||||
func (f *FSMDataStore) Update(entry structs.ConfigEntry) error {
|
||||
_, err := f.server.leaderRaftApply("ConfigEntry.Apply", structs.ConfigEntryRequestType, &structs.ConfigEntryRequest{
|
||||
Op: structs.ConfigEntryUpsertCAS,
|
||||
Entry: entry,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateStatus takes a config entry, an error, and updates the status field as needed in the FSM state
|
||||
func (f *FSMDataStore) UpdateStatus(entry structs.ControlledConfigEntry, err error) error {
|
||||
if err == nil {
|
||||
//TODO additional status messages for success?
|
||||
return nil
|
||||
}
|
||||
status := structs.Status{
|
||||
Conditions: []structs.Condition{{
|
||||
|
||||
Status: err.Error() + ": Accepted == false",
|
||||
},
|
||||
},
|
||||
}
|
||||
entry.SetStatus(status)
|
||||
return f.Update(entry)
|
||||
}
|
||||
|
||||
// Delete takes a config entry and deletes it from the FSM state
|
||||
func (f *FSMDataStore) Delete(entry structs.ConfigEntry) error {
|
||||
_, err := f.server.leaderRaftApply("ConfigEntry.Delete", structs.ConfigEntryRequestType, &structs.ConfigEntryRequest{
|
||||
Op: structs.ConfigEntryDelete,
|
||||
Entry: entry,
|
||||
})
|
||||
return err
|
||||
}
|
|
@ -8,7 +8,6 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-hclog"
|
||||
"github.com/hashicorp/go-memdb"
|
||||
|
@ -20,6 +19,7 @@ import (
|
|||
"github.com/hashicorp/consul/agent/consul/state"
|
||||
"github.com/hashicorp/consul/agent/consul/stream"
|
||||
"github.com/hashicorp/consul/agent/structs"
|
||||
"github.com/hashicorp/consul/api"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -211,8 +211,6 @@ func (r *apiGatewayReconciler) cleanupGateway(_ context.Context, req controller.
|
|||
// referenced this gateway. It then persists any status updates for the gateway,
|
||||
// the modified routes, and updates the bound gateway.
|
||||
func (r *apiGatewayReconciler) reconcileGateway(_ context.Context, req controller.Request, store *state.Store, gateway *structs.APIGatewayConfigEntry) error {
|
||||
conditions := newGatewayConditionGenerator()
|
||||
|
||||
logger := gatewayRequestLogger(r.logger, req)
|
||||
|
||||
logger.Trace("started reconciling gateway")
|
||||
|
@ -244,13 +242,13 @@ func (r *apiGatewayReconciler) reconcileGateway(_ context.Context, req controlle
|
|||
}
|
||||
|
||||
for ref, err := range certificateErrors {
|
||||
updater.SetCondition(conditions.invalidCertificate(ref, err))
|
||||
updater.SetCondition(invalidCertificate(ref, err))
|
||||
}
|
||||
|
||||
if len(certificateErrors) > 0 {
|
||||
updater.SetCondition(conditions.invalidCertificates())
|
||||
updater.SetCondition(invalidCertificates())
|
||||
} else {
|
||||
updater.SetCondition(conditions.gatewayAccepted())
|
||||
updater.SetCondition(gatewayAccepted())
|
||||
}
|
||||
|
||||
// now we bind all of the routes we can
|
||||
|
@ -262,19 +260,19 @@ func (r *apiGatewayReconciler) reconcileGateway(_ context.Context, req controlle
|
|||
// unset the old gateway binding in case it's stale
|
||||
for _, parent := range route.GetParents() {
|
||||
if parent.Kind == gateway.Kind && parent.Name == gateway.Name && parent.EnterpriseMeta.IsSame(&gateway.EnterpriseMeta) {
|
||||
routeUpdater.RemoveCondition(conditions.routeBound(parent))
|
||||
routeUpdater.RemoveCondition(routeBound(parent))
|
||||
}
|
||||
}
|
||||
|
||||
// set the status for parents that have bound successfully
|
||||
for _, ref := range boundRefs {
|
||||
routeUpdater.SetCondition(conditions.routeBound(ref))
|
||||
routeUpdater.SetCondition(routeBound(ref))
|
||||
}
|
||||
|
||||
// set the status for any parents that have errored trying to
|
||||
// bind
|
||||
for ref, err := range bindErrors {
|
||||
routeUpdater.SetCondition(conditions.routeUnbound(ref, err))
|
||||
routeUpdater.SetCondition(routeUnbound(ref, err))
|
||||
}
|
||||
|
||||
// if we've updated any statuses, then store them as needing
|
||||
|
@ -354,8 +352,6 @@ func (r *apiGatewayReconciler) cleanupRoute(_ context.Context, req controller.Re
|
|||
// gateways that now have route conflicts, and updates all statuses and states
|
||||
// as necessary.
|
||||
func (r *apiGatewayReconciler) reconcileRoute(_ context.Context, req controller.Request, store *state.Store, route structs.BoundRoute) error {
|
||||
conditions := newGatewayConditionGenerator()
|
||||
|
||||
logger := routeRequestLogger(r.logger, req)
|
||||
|
||||
logger.Trace("reconciling route")
|
||||
|
@ -435,23 +431,23 @@ func (r *apiGatewayReconciler) reconcileRoute(_ context.Context, req controller.
|
|||
Entries: chainSet,
|
||||
})
|
||||
if err != nil {
|
||||
updater.SetCondition(conditions.routeInvalidDiscoveryChain(err))
|
||||
updater.SetCondition(routeInvalidDiscoveryChain(err))
|
||||
continue
|
||||
}
|
||||
|
||||
if chain.Protocol != string(route.GetProtocol()) {
|
||||
updater.SetCondition(conditions.routeInvalidDiscoveryChain(errInvalidProtocol))
|
||||
updater.SetCondition(routeInvalidDiscoveryChain(errInvalidProtocol))
|
||||
continue
|
||||
}
|
||||
|
||||
updater.SetCondition(conditions.routeAccepted())
|
||||
updater.SetCondition(routeAccepted())
|
||||
}
|
||||
|
||||
// if we have no upstream targets, then set the route as invalid
|
||||
// this should already happen in the validation check on write, but
|
||||
// we'll do it here too just in case
|
||||
if len(route.GetServiceNames()) == 0 {
|
||||
updater.SetCondition(conditions.routeNoUpstreams())
|
||||
updater.SetCondition(routeNoUpstreams())
|
||||
}
|
||||
|
||||
// the route is valid, attempt to bind it to all gateways
|
||||
|
@ -460,12 +456,12 @@ func (r *apiGatewayReconciler) reconcileRoute(_ context.Context, req controller.
|
|||
|
||||
// set the status of the references that are bound
|
||||
for _, ref := range boundRefs {
|
||||
updater.SetCondition(conditions.routeBound(ref))
|
||||
updater.SetCondition(routeBound(ref))
|
||||
}
|
||||
|
||||
// set any binding errors
|
||||
for ref, err := range bindErrors {
|
||||
updater.SetCondition(conditions.routeUnbound(ref, err))
|
||||
updater.SetCondition(routeUnbound(ref, err))
|
||||
}
|
||||
|
||||
// set any refs that haven't been bound or explicitly errored
|
||||
|
@ -479,7 +475,7 @@ PARENT_LOOP:
|
|||
if _, ok := bindErrors[ref]; ok {
|
||||
continue PARENT_LOOP
|
||||
}
|
||||
updater.SetCondition(conditions.gatewayNotFound(ref))
|
||||
updater.SetCondition(gatewayNotFound(ref))
|
||||
}
|
||||
|
||||
return finalize(modifiedGateways)
|
||||
|
@ -549,8 +545,6 @@ type gatewayMeta struct {
|
|||
// the map values are pointers so that we can update them directly
|
||||
// and have the changes propagate back to the container gateways.
|
||||
boundListeners map[string]*structs.BoundAPIGatewayListener
|
||||
|
||||
generator *gatewayConditionGenerator
|
||||
}
|
||||
|
||||
// getAllGatewayMeta returns a pre-constructed list of all valid gateway and state
|
||||
|
@ -678,13 +672,13 @@ func (g *gatewayMeta) bindRoute(listener *structs.APIGatewayListener, bound *str
|
|||
}
|
||||
|
||||
// check to make sure we're not binding to an invalid gateway
|
||||
if !g.Gateway.Status.MatchesConditionStatus(g.generator.gatewayAccepted()) {
|
||||
if !g.Gateway.Status.MatchesConditionStatus(gatewayAccepted()) {
|
||||
return false, fmt.Errorf("failed to bind route to gateway %s: gateway has not been accepted", g.Gateway.Name)
|
||||
}
|
||||
|
||||
// check to make sure we're not binding to an invalid route
|
||||
status := route.GetStatus()
|
||||
if !status.MatchesConditionStatus(g.generator.routeAccepted()) {
|
||||
if !status.MatchesConditionStatus(routeAccepted()) {
|
||||
return false, fmt.Errorf("failed to bind route to gateway %s: route has not been accepted", g.Gateway.Name)
|
||||
}
|
||||
|
||||
|
@ -755,7 +749,6 @@ func (g *gatewayMeta) checkCertificates(store *state.Store) (map[structs.Resourc
|
|||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -773,8 +766,6 @@ func (g *gatewayMeta) checkConflicts() (structs.ControlledConfigEntry, bool) {
|
|||
// setConflicts ensures that no TCP listener has more than the one allowed route and
|
||||
// assigns an appropriate status
|
||||
func (g *gatewayMeta) setConflicts(updater *structs.StatusUpdater) {
|
||||
conditions := newGatewayConditionGenerator()
|
||||
|
||||
g.eachListener(func(listener *structs.APIGatewayListener, bound *structs.BoundAPIGatewayListener) error {
|
||||
ref := structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
|
@ -785,19 +776,17 @@ func (g *gatewayMeta) setConflicts(updater *structs.StatusUpdater) {
|
|||
switch listener.Protocol {
|
||||
case structs.ListenerProtocolTCP:
|
||||
if len(bound.Routes) > 1 {
|
||||
updater.SetCondition(conditions.gatewayListenerConflicts(ref))
|
||||
updater.SetCondition(gatewayListenerConflicts(ref))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
updater.SetCondition(conditions.gatewayListenerNoConflicts(ref))
|
||||
updater.SetCondition(gatewayListenerNoConflicts(ref))
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// initialize sets up the listener maps that we use for quickly indexing the listeners in our binding logic
|
||||
func (g *gatewayMeta) initialize() *gatewayMeta {
|
||||
g.generator = newGatewayConditionGenerator()
|
||||
|
||||
// set up the maps for fast access
|
||||
g.boundListeners = make(map[string]*structs.BoundAPIGatewayListener, len(g.BoundGateway.Listeners))
|
||||
for i, listener := range g.BoundGateway.Listeners {
|
||||
|
@ -840,151 +829,132 @@ func newGatewayMeta(gateway *structs.APIGatewayConfigEntry, bound structs.Config
|
|||
}).initialize()
|
||||
}
|
||||
|
||||
// gatewayConditionGenerator is a simple struct used for isolating
|
||||
// the status conditions that we generate for our components
|
||||
type gatewayConditionGenerator struct {
|
||||
now *time.Time
|
||||
}
|
||||
|
||||
// newGatewayConditionGenerator initializes a status conditions generator
|
||||
func newGatewayConditionGenerator() *gatewayConditionGenerator {
|
||||
return &gatewayConditionGenerator{
|
||||
now: pointerTo(time.Now().UTC()),
|
||||
}
|
||||
// gatewayAccepted marks the APIGateway as valid.
|
||||
func gatewayAccepted() structs.Condition {
|
||||
return structs.NewGatewayCondition(
|
||||
api.GatewayConditionAccepted,
|
||||
api.ConditionStatusTrue,
|
||||
api.GatewayReasonAccepted,
|
||||
"gateway is valid",
|
||||
structs.ResourceReference{},
|
||||
)
|
||||
}
|
||||
|
||||
// invalidCertificate returns a condition used when a gateway references a
|
||||
// certificate that does not exist. It takes a ref used to scope the condition
|
||||
// to a given APIGateway listener.
|
||||
func (g *gatewayConditionGenerator) invalidCertificate(ref structs.ResourceReference, err error) structs.Condition {
|
||||
return structs.Condition{
|
||||
Type: "Accepted",
|
||||
Status: "False",
|
||||
Reason: "InvalidCertificate",
|
||||
Message: err.Error(),
|
||||
Resource: pointerTo(ref),
|
||||
LastTransitionTime: g.now,
|
||||
}
|
||||
func invalidCertificate(ref structs.ResourceReference, err error) structs.Condition {
|
||||
return structs.NewGatewayCondition(
|
||||
api.GatewayConditionAccepted,
|
||||
api.ConditionStatusFalse,
|
||||
api.GatewayListenerReasonInvalidCertificateRef,
|
||||
err.Error(),
|
||||
ref,
|
||||
)
|
||||
}
|
||||
|
||||
// invalidCertificates is used to set the overall condition of the APIGateway
|
||||
// to invalid due to missing certificates that it references.
|
||||
func (g *gatewayConditionGenerator) invalidCertificates() structs.Condition {
|
||||
return structs.Condition{
|
||||
Type: "Accepted",
|
||||
Status: "False",
|
||||
Reason: "InvalidCertificates",
|
||||
Message: "gateway references invalid certificates",
|
||||
LastTransitionTime: g.now,
|
||||
}
|
||||
}
|
||||
|
||||
// gatewayAccepted marks the APIGateway as valid.
|
||||
func (g *gatewayConditionGenerator) gatewayAccepted() structs.Condition {
|
||||
return structs.Condition{
|
||||
Type: "Accepted",
|
||||
Status: "True",
|
||||
Reason: "Accepted",
|
||||
Message: "gateway is valid",
|
||||
LastTransitionTime: g.now,
|
||||
}
|
||||
}
|
||||
|
||||
// routeBound marks a Route as bound to the referenced APIGateway
|
||||
func (g *gatewayConditionGenerator) routeBound(ref structs.ResourceReference) structs.Condition {
|
||||
return structs.Condition{
|
||||
Type: "Bound",
|
||||
Status: "True",
|
||||
Reason: "Bound",
|
||||
Resource: pointerTo(ref),
|
||||
Message: "successfully bound route",
|
||||
LastTransitionTime: g.now,
|
||||
}
|
||||
}
|
||||
|
||||
// routeAccepted marks the Route as valid
|
||||
func (g *gatewayConditionGenerator) routeAccepted() structs.Condition {
|
||||
return structs.Condition{
|
||||
Type: "Accepted",
|
||||
Status: "True",
|
||||
Reason: "Accepted",
|
||||
Message: "route is valid",
|
||||
LastTransitionTime: g.now,
|
||||
}
|
||||
}
|
||||
|
||||
// routeUnbound marks the route as having failed to bind to the referenced APIGateway
|
||||
func (g *gatewayConditionGenerator) routeUnbound(ref structs.ResourceReference, err error) structs.Condition {
|
||||
return structs.Condition{
|
||||
Type: "Bound",
|
||||
Status: "False",
|
||||
Reason: "FailedToBind",
|
||||
Resource: pointerTo(ref),
|
||||
Message: err.Error(),
|
||||
LastTransitionTime: g.now,
|
||||
}
|
||||
}
|
||||
|
||||
// routeInvalidDiscoveryChain marks the route as invalid due to an error while validating its referenced
|
||||
// discovery chian
|
||||
func (g *gatewayConditionGenerator) routeInvalidDiscoveryChain(err error) structs.Condition {
|
||||
return structs.Condition{
|
||||
Type: "Accepted",
|
||||
Status: "False",
|
||||
Reason: "InvalidDiscoveryChain",
|
||||
Message: err.Error(),
|
||||
LastTransitionTime: g.now,
|
||||
}
|
||||
}
|
||||
|
||||
// routeNoUpstreams marks the route as invalid because it has no upstreams that it targets
|
||||
func (g *gatewayConditionGenerator) routeNoUpstreams() structs.Condition {
|
||||
return structs.Condition{
|
||||
Type: "Accepted",
|
||||
Status: "False",
|
||||
Reason: "NoUpstreamServicesTargeted",
|
||||
Message: "route must target at least one upstream service",
|
||||
LastTransitionTime: g.now,
|
||||
}
|
||||
}
|
||||
|
||||
// gatewayListenerConflicts marks an APIGateway listener as having bound routes that conflict with each other
|
||||
// and make the listener, therefore invalid
|
||||
func (g *gatewayConditionGenerator) gatewayListenerConflicts(ref structs.ResourceReference) structs.Condition {
|
||||
return structs.Condition{
|
||||
Type: "Conflicted",
|
||||
Status: "True",
|
||||
Reason: "RouteConflict",
|
||||
Resource: pointerTo(ref),
|
||||
Message: "TCP-based listeners currently only support binding a single route",
|
||||
LastTransitionTime: g.now,
|
||||
}
|
||||
func invalidCertificates() structs.Condition {
|
||||
return structs.NewGatewayCondition(
|
||||
api.GatewayConditionAccepted,
|
||||
api.ConditionStatusFalse,
|
||||
api.GatewayReasonInvalidCertificates,
|
||||
"gateway references invalid certificates",
|
||||
structs.ResourceReference{},
|
||||
)
|
||||
}
|
||||
|
||||
// gatewayListenerNoConflicts marks an APIGateway listener as having no conflicts within its
|
||||
// bound routes
|
||||
func (g *gatewayConditionGenerator) gatewayListenerNoConflicts(ref structs.ResourceReference) structs.Condition {
|
||||
return structs.Condition{
|
||||
Type: "Conflicted",
|
||||
Status: "False",
|
||||
Reason: "NoConflict",
|
||||
Resource: pointerTo(ref),
|
||||
Message: "listener has no route conflicts",
|
||||
LastTransitionTime: g.now,
|
||||
}
|
||||
func gatewayListenerNoConflicts(ref structs.ResourceReference) structs.Condition {
|
||||
return structs.NewGatewayCondition(
|
||||
api.GatewayConditionConflicted,
|
||||
api.ConditionStatusFalse,
|
||||
api.GatewayReasonNoConflict,
|
||||
"listener has no route conflicts",
|
||||
ref,
|
||||
)
|
||||
}
|
||||
|
||||
// gatewayListenerConflicts marks an APIGateway listener as having bound routes that conflict with each other
|
||||
// and make the listener, therefore invalid
|
||||
func gatewayListenerConflicts(ref structs.ResourceReference) structs.Condition {
|
||||
return structs.NewGatewayCondition(
|
||||
api.GatewayConditionConflicted,
|
||||
api.ConditionStatusTrue,
|
||||
api.GatewayReasonRouteConflict,
|
||||
"TCP-based listeners currently only support binding a single route",
|
||||
ref,
|
||||
)
|
||||
}
|
||||
|
||||
// routeBound marks a Route as bound to the referenced APIGateway
|
||||
func routeBound(ref structs.ResourceReference) structs.Condition {
|
||||
return structs.NewRouteCondition(
|
||||
api.RouteConditionBound,
|
||||
api.ConditionStatusTrue,
|
||||
api.RouteReasonBound,
|
||||
"successfully bound route",
|
||||
ref,
|
||||
)
|
||||
}
|
||||
|
||||
// gatewayNotFound marks a Route as having failed to bind to a referenced APIGateway due to
|
||||
// the Gateway not existing (or having not been reconciled yet)
|
||||
func (g *gatewayConditionGenerator) gatewayNotFound(ref structs.ResourceReference) structs.Condition {
|
||||
return structs.Condition{
|
||||
Type: "Bound",
|
||||
Status: "False",
|
||||
Reason: "GatewayNotFound",
|
||||
Resource: pointerTo(ref),
|
||||
Message: "gateway was not found",
|
||||
LastTransitionTime: g.now,
|
||||
}
|
||||
func gatewayNotFound(ref structs.ResourceReference) structs.Condition {
|
||||
return structs.NewRouteCondition(
|
||||
api.RouteConditionBound,
|
||||
api.ConditionStatusFalse,
|
||||
api.RouteReasonGatewayNotFound,
|
||||
"gateway was not found",
|
||||
ref,
|
||||
)
|
||||
}
|
||||
|
||||
// routeUnbound marks the route as having failed to bind to the referenced APIGateway
|
||||
func routeUnbound(ref structs.ResourceReference, err error) structs.Condition {
|
||||
return structs.NewRouteCondition(
|
||||
api.RouteConditionBound,
|
||||
api.ConditionStatusFalse,
|
||||
api.RouteReasonFailedToBind,
|
||||
err.Error(),
|
||||
ref,
|
||||
)
|
||||
}
|
||||
|
||||
// routeAccepted marks the Route as valid
|
||||
func routeAccepted() structs.Condition {
|
||||
return structs.NewRouteCondition(
|
||||
api.RouteConditionAccepted,
|
||||
api.ConditionStatusTrue,
|
||||
api.RouteReasonAccepted,
|
||||
"route is valid",
|
||||
structs.ResourceReference{},
|
||||
)
|
||||
}
|
||||
|
||||
// routeInvalidDiscoveryChain marks the route as invalid due to an error while validating its referenced
|
||||
// discovery chian
|
||||
func routeInvalidDiscoveryChain(err error) structs.Condition {
|
||||
return structs.NewRouteCondition(
|
||||
api.RouteConditionAccepted,
|
||||
api.ConditionStatusFalse,
|
||||
api.RouteReasonInvalidDiscoveryChain,
|
||||
err.Error(),
|
||||
structs.ResourceReference{},
|
||||
)
|
||||
}
|
||||
|
||||
// routeNoUpstreams marks the route as invalid because it has no upstreams that it targets
|
||||
func routeNoUpstreams() structs.Condition {
|
||||
return structs.NewRouteCondition(
|
||||
api.RouteConditionAccepted,
|
||||
api.ConditionStatusFalse,
|
||||
api.RouteReasonNoUpstreamServicesTargeted,
|
||||
"route must target at least one upstream service",
|
||||
structs.ResourceReference{},
|
||||
)
|
||||
}
|
||||
|
||||
// bindRoutesToGateways takes a route variadic number of gateways.
|
||||
|
@ -1024,7 +994,6 @@ func bindRoutesToGateways(route structs.BoundRoute, gateways ...*gatewayMeta) ([
|
|||
// removeGateway sets the route's status appropriately when the gateway that it's
|
||||
// attempting to bind to does not exist
|
||||
func removeGateway(gateway structs.ResourceReference, entries ...structs.BoundRoute) []structs.ControlledConfigEntry {
|
||||
conditions := newGatewayConditionGenerator()
|
||||
modified := []structs.ControlledConfigEntry{}
|
||||
|
||||
for _, route := range entries {
|
||||
|
@ -1032,7 +1001,7 @@ func removeGateway(gateway structs.ResourceReference, entries ...structs.BoundRo
|
|||
|
||||
for _, parent := range route.GetParents() {
|
||||
if parent.Kind == gateway.Kind && parent.Name == gateway.Name && parent.EnterpriseMeta.IsSame(&gateway.EnterpriseMeta) {
|
||||
updater.SetCondition(conditions.gatewayNotFound(parent))
|
||||
updater.SetCondition(gatewayNotFound(parent))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,9 +11,10 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-hclog"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/hashicorp/go-hclog"
|
||||
|
||||
"github.com/hashicorp/consul/acl"
|
||||
"github.com/hashicorp/consul/agent/consul/controller"
|
||||
"github.com/hashicorp/consul/agent/consul/fsm"
|
||||
|
@ -55,7 +56,7 @@ func TestBoundAPIGatewayBindRoute(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -72,7 +73,7 @@ func TestBoundAPIGatewayBindRoute(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -132,7 +133,7 @@ func TestBoundAPIGatewayBindRoute(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -148,7 +149,7 @@ func TestBoundAPIGatewayBindRoute(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -443,7 +444,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -462,7 +463,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -557,7 +558,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -582,7 +583,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -606,7 +607,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -675,7 +676,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -694,7 +695,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -752,7 +753,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -771,7 +772,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -841,7 +842,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -860,7 +861,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -924,7 +925,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -957,7 +958,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -981,7 +982,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1064,7 +1065,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1083,7 +1084,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1133,7 +1134,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1158,7 +1159,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1177,7 +1178,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1193,7 +1194,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1254,7 +1255,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1273,7 +1274,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1317,7 +1318,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1336,14 +1337,13 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedBoundAPIGateways: []*structs.BoundAPIGatewayConfigEntry{
|
||||
{
|
||||
|
||||
Name: "Gateway",
|
||||
Listeners: []structs.BoundAPIGatewayListener{
|
||||
{
|
||||
|
@ -1435,7 +1435,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1453,7 +1453,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1493,7 +1493,6 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestAPIGatewayController(t *testing.T) {
|
||||
conditions := newGatewayConditionGenerator()
|
||||
defaultMeta := acl.DefaultEnterpriseMeta()
|
||||
for name, tc := range map[string]struct {
|
||||
requests []controller.Request
|
||||
|
@ -1521,7 +1520,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1552,7 +1551,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeNoUpstreams(),
|
||||
routeNoUpstreams(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1578,7 +1577,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeNoUpstreams(),
|
||||
routeNoUpstreams(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1628,8 +1627,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeAccepted(),
|
||||
conditions.routeUnbound(structs.ResourceReference{
|
||||
routeAccepted(),
|
||||
routeUnbound(structs.ResourceReference{
|
||||
Name: "api-gateway",
|
||||
EnterpriseMeta: *defaultMeta,
|
||||
}, errors.New("failed to bind route to gateway api-gateway: gateway has not been accepted")),
|
||||
|
@ -1646,7 +1645,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "api-gateway",
|
||||
SectionName: "listener",
|
||||
|
@ -1694,7 +1693,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeInvalidDiscoveryChain(errInvalidProtocol),
|
||||
routeInvalidDiscoveryChain(errInvalidProtocol),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1733,8 +1732,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeAccepted(),
|
||||
conditions.gatewayNotFound(structs.ResourceReference{
|
||||
routeAccepted(),
|
||||
gatewayNotFound(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *defaultMeta,
|
||||
|
@ -1787,8 +1786,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeAccepted(),
|
||||
conditions.gatewayNotFound(structs.ResourceReference{
|
||||
routeAccepted(),
|
||||
gatewayNotFound(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *defaultMeta,
|
||||
|
@ -1851,8 +1850,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeAccepted(),
|
||||
conditions.routeUnbound(structs.ResourceReference{
|
||||
routeAccepted(),
|
||||
routeUnbound(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *defaultMeta,
|
||||
|
@ -1920,8 +1919,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeAccepted(),
|
||||
conditions.gatewayNotFound(structs.ResourceReference{
|
||||
routeAccepted(),
|
||||
gatewayNotFound(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *defaultMeta,
|
||||
|
@ -1956,7 +1955,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1976,7 +1975,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2006,8 +2005,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.gatewayAccepted(),
|
||||
conditions.gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
gatewayAccepted(),
|
||||
gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *defaultMeta,
|
||||
|
@ -2022,8 +2021,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeAccepted(),
|
||||
conditions.routeBound(structs.ResourceReference{
|
||||
routeAccepted(),
|
||||
routeBound(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *defaultMeta,
|
||||
|
@ -2058,7 +2057,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2098,8 +2097,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.gatewayAccepted(),
|
||||
conditions.gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
gatewayAccepted(),
|
||||
gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *defaultMeta,
|
||||
|
@ -2114,8 +2113,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeAccepted(),
|
||||
conditions.routeUnbound(structs.ResourceReference{
|
||||
routeAccepted(),
|
||||
routeUnbound(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *defaultMeta,
|
||||
|
@ -2154,7 +2153,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2172,7 +2171,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2221,8 +2220,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.gatewayAccepted(),
|
||||
conditions.gatewayListenerConflicts(structs.ResourceReference{
|
||||
gatewayAccepted(),
|
||||
gatewayListenerConflicts(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *defaultMeta,
|
||||
|
@ -2237,8 +2236,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeAccepted(),
|
||||
conditions.routeBound(structs.ResourceReference{
|
||||
routeAccepted(),
|
||||
routeBound(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *defaultMeta,
|
||||
|
@ -2252,8 +2251,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeAccepted(),
|
||||
conditions.routeBound(structs.ResourceReference{
|
||||
routeAccepted(),
|
||||
routeBound(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *defaultMeta,
|
||||
|
@ -2294,7 +2293,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2314,7 +2313,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2364,8 +2363,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.gatewayAccepted(),
|
||||
conditions.gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
gatewayAccepted(),
|
||||
gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *defaultMeta,
|
||||
|
@ -2380,8 +2379,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeAccepted(),
|
||||
conditions.routeBound(structs.ResourceReference{
|
||||
routeAccepted(),
|
||||
routeBound(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *defaultMeta,
|
||||
|
@ -2395,8 +2394,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeAccepted(),
|
||||
conditions.routeBound(structs.ResourceReference{
|
||||
routeAccepted(),
|
||||
routeBound(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *defaultMeta,
|
||||
|
@ -2505,8 +2504,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.gatewayAccepted(),
|
||||
conditions.gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
gatewayAccepted(),
|
||||
gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *defaultMeta,
|
||||
|
@ -2521,8 +2520,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeAccepted(),
|
||||
conditions.routeBound(structs.ResourceReference{
|
||||
routeAccepted(),
|
||||
routeBound(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *defaultMeta,
|
||||
|
@ -2536,8 +2535,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeAccepted(),
|
||||
conditions.routeUnbound(structs.ResourceReference{
|
||||
routeAccepted(),
|
||||
routeUnbound(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *defaultMeta,
|
||||
|
@ -2578,7 +2577,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2596,7 +2595,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2659,13 +2658,13 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.gatewayAccepted(),
|
||||
conditions.gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
gatewayAccepted(),
|
||||
gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "http-listener",
|
||||
}),
|
||||
conditions.gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "tcp-listener",
|
||||
|
@ -2679,8 +2678,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeAccepted(),
|
||||
conditions.routeBound(structs.ResourceReference{
|
||||
routeAccepted(),
|
||||
routeBound(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *defaultMeta,
|
||||
|
@ -2694,8 +2693,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeAccepted(),
|
||||
conditions.routeBound(structs.ResourceReference{
|
||||
routeAccepted(),
|
||||
routeBound(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *defaultMeta,
|
||||
|
@ -2721,8 +2720,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeAccepted(),
|
||||
conditions.routeBound(structs.ResourceReference{
|
||||
routeAccepted(),
|
||||
routeBound(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *defaultMeta,
|
||||
|
@ -2776,7 +2775,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "tcp-listener",
|
||||
|
@ -2791,7 +2790,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2810,8 +2809,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeAccepted(),
|
||||
conditions.routeBound(structs.ResourceReference{
|
||||
routeAccepted(),
|
||||
routeBound(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *defaultMeta,
|
||||
|
@ -2865,7 +2864,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "tcp-listener",
|
||||
|
@ -2880,7 +2879,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeNoUpstreams(),
|
||||
routeNoUpstreams(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2908,8 +2907,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeAccepted(),
|
||||
conditions.routeBound(structs.ResourceReference{
|
||||
routeAccepted(),
|
||||
routeBound(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *defaultMeta,
|
||||
|
@ -2934,8 +2933,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeAccepted(),
|
||||
conditions.routeUnbound(structs.ResourceReference{
|
||||
routeAccepted(),
|
||||
routeUnbound(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
}, errors.New("foo")),
|
||||
|
@ -2965,8 +2964,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.gatewayAccepted(),
|
||||
conditions.gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
gatewayAccepted(),
|
||||
gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "tcp-listener",
|
||||
|
@ -3008,8 +3007,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.gatewayAccepted(),
|
||||
conditions.gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
gatewayAccepted(),
|
||||
gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "http-listener",
|
||||
|
@ -3023,8 +3022,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeAccepted(),
|
||||
conditions.routeUnbound(structs.ResourceReference{
|
||||
routeAccepted(),
|
||||
routeUnbound(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
}, errors.New("failed to bind route tcp-route to gateway gateway with listener ''")),
|
||||
|
@ -3037,8 +3036,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeAccepted(),
|
||||
conditions.routeBound(structs.ResourceReference{
|
||||
routeAccepted(),
|
||||
routeBound(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
}),
|
||||
|
@ -3073,8 +3072,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeAccepted(),
|
||||
conditions.routeBound(structs.ResourceReference{
|
||||
routeAccepted(),
|
||||
routeBound(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *defaultMeta,
|
||||
|
@ -3109,8 +3108,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeAccepted(),
|
||||
conditions.gatewayNotFound(structs.ResourceReference{
|
||||
routeAccepted(),
|
||||
gatewayNotFound(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
}),
|
||||
|
@ -3150,8 +3149,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.gatewayAccepted(),
|
||||
conditions.gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
gatewayAccepted(),
|
||||
gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "tcp-listener",
|
||||
|
@ -3176,8 +3175,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.gatewayAccepted(),
|
||||
conditions.gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
gatewayAccepted(),
|
||||
gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "tcp-listener",
|
||||
|
@ -3221,8 +3220,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeAccepted(),
|
||||
conditions.routeBound(structs.ResourceReference{
|
||||
routeAccepted(),
|
||||
routeBound(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
}),
|
||||
|
@ -3237,8 +3236,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeAccepted(),
|
||||
conditions.gatewayNotFound(structs.ResourceReference{
|
||||
routeAccepted(),
|
||||
gatewayNotFound(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
}),
|
||||
|
@ -3287,12 +3286,12 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.invalidCertificate(structs.ResourceReference{
|
||||
invalidCertificate(structs.ResourceReference{
|
||||
Kind: structs.InlineCertificate,
|
||||
Name: "certificate",
|
||||
}, errors.New("certificate not found")),
|
||||
conditions.invalidCertificates(),
|
||||
conditions.gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
invalidCertificates(),
|
||||
gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "http-listener",
|
||||
|
@ -3355,8 +3354,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.gatewayAccepted(),
|
||||
conditions.gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
gatewayAccepted(),
|
||||
gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "http-listener",
|
||||
|
@ -3402,12 +3401,12 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.invalidCertificate(structs.ResourceReference{
|
||||
invalidCertificate(structs.ResourceReference{
|
||||
Kind: structs.InlineCertificate,
|
||||
Name: "certificate",
|
||||
}, errors.New("certificate not found")),
|
||||
conditions.invalidCertificates(),
|
||||
conditions.gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
invalidCertificates(),
|
||||
gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "http-listener",
|
||||
|
@ -3438,8 +3437,8 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.gatewayAccepted(),
|
||||
conditions.gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
gatewayAccepted(),
|
||||
gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "http-listener",
|
||||
|
@ -3705,12 +3704,15 @@ func (n *noopController) WithWorkers(i int) controller.Controller
|
|||
func (n *noopController) WithQueueFactory(fn func(ctx context.Context, baseBackoff time.Duration, maxBackoff time.Duration) controller.WorkQueue) controller.Controller {
|
||||
return n
|
||||
}
|
||||
|
||||
func (n *noopController) AddTrigger(request controller.Request, trigger func(ctx context.Context) error) {
|
||||
n.triggers[request] = struct{}{}
|
||||
}
|
||||
|
||||
func (n *noopController) RemoveTrigger(request controller.Request) {
|
||||
delete(n.triggers, request)
|
||||
}
|
||||
|
||||
func (n *noopController) Enqueue(requests ...controller.Request) {
|
||||
n.enqueued = append(n.enqueued, requests...)
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/hashicorp/consul/acl"
|
||||
"github.com/hashicorp/consul/api"
|
||||
)
|
||||
|
||||
// ResourceReference is a reference to a ConfigEntry
|
||||
|
@ -67,30 +68,6 @@ func (s Status) SameConditions(other Status) bool {
|
|||
if len(s.Conditions) != len(other.Conditions) {
|
||||
return false
|
||||
}
|
||||
lessResource := func(one, two *ResourceReference) bool {
|
||||
if one == nil && two == nil {
|
||||
return false
|
||||
}
|
||||
if one == nil {
|
||||
return true
|
||||
}
|
||||
if two == nil {
|
||||
return false
|
||||
}
|
||||
if one.Kind < two.Kind {
|
||||
return true
|
||||
}
|
||||
if one.Kind > two.Kind {
|
||||
return false
|
||||
}
|
||||
if one.Name < two.Name {
|
||||
return true
|
||||
}
|
||||
if one.Name > two.Name {
|
||||
return false
|
||||
}
|
||||
return one.SectionName < two.SectionName
|
||||
}
|
||||
sortConditions := func(conditions []Condition) []Condition {
|
||||
sort.SliceStable(conditions, func(i, j int) bool {
|
||||
if conditions[i].Type < conditions[j].Type {
|
||||
|
@ -114,6 +91,31 @@ func (s Status) SameConditions(other Status) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func lessResource(one, two *ResourceReference) bool {
|
||||
if one == nil && two == nil {
|
||||
return false
|
||||
}
|
||||
if one == nil {
|
||||
return true
|
||||
}
|
||||
if two == nil {
|
||||
return false
|
||||
}
|
||||
if one.Kind < two.Kind {
|
||||
return true
|
||||
}
|
||||
if one.Kind > two.Kind {
|
||||
return false
|
||||
}
|
||||
if one.Name < two.Name {
|
||||
return true
|
||||
}
|
||||
if one.Name > two.Name {
|
||||
return false
|
||||
}
|
||||
return one.SectionName < two.SectionName
|
||||
}
|
||||
|
||||
// Condition is used for a single message and state associated
|
||||
// with an object. For example, a ConfigEntry that references
|
||||
// multiple other resources may have different statuses with
|
||||
|
@ -195,3 +197,42 @@ func (u *StatusUpdater) UpdateEntry() (ControlledConfigEntry, bool) {
|
|||
u.entry.SetStatus(u.status)
|
||||
return u.entry, true
|
||||
}
|
||||
|
||||
func NewGatewayCondition(name api.GatewayConditionType, status api.ConditionStatus, reason api.GatewayConditionReason, message string, resource ResourceReference) Condition {
|
||||
if err := api.ValidateGatewayConditionReason(name, status, reason); err != nil {
|
||||
// note we panic here because an invalid combination is a programmer error
|
||||
// this should never actually be hit
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return Condition{
|
||||
Type: string(name),
|
||||
Status: string(status),
|
||||
Reason: string(reason),
|
||||
Message: message,
|
||||
Resource: ptrTo(resource),
|
||||
LastTransitionTime: ptrTo(time.Now().UTC()),
|
||||
}
|
||||
}
|
||||
|
||||
// NewRouteCondition is a helper to build allowable Conditions for a Route config entry
|
||||
func NewRouteCondition(name api.RouteConditionType, status api.ConditionStatus, reason api.RouteConditionReason, message string, ref ResourceReference) Condition {
|
||||
if err := api.ValidateRouteConditionReason(name, status, reason); err != nil {
|
||||
// note we panic here because an invalid combination is a programmer error
|
||||
// this should never actually be hit
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return Condition{
|
||||
Type: string(name),
|
||||
Status: string(status),
|
||||
Reason: string(reason),
|
||||
Message: message,
|
||||
Resource: ptrTo(ref),
|
||||
LastTransitionTime: ptrTo(time.Now().UTC()),
|
||||
}
|
||||
}
|
||||
|
||||
func ptrTo[T any](val T) *T {
|
||||
return &val
|
||||
}
|
||||
|
|
|
@ -4,7 +4,10 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
// ResourceReference is a reference to a ConfigEntry
|
||||
|
@ -46,7 +49,7 @@ type Condition struct {
|
|||
// Type is a value from a bounded set of types that an object might have
|
||||
Type string
|
||||
// Status is a value from a bounded set of statuses that an object might have
|
||||
Status string
|
||||
Status ConditionStatus
|
||||
// Reason is a value from a bounded set of reasons for a given status
|
||||
Reason string
|
||||
// Message is a message that gives more detailed information about
|
||||
|
@ -58,3 +61,280 @@ type Condition struct {
|
|||
// LastTransitionTime is the time at which this Condition was created
|
||||
LastTransitionTime *time.Time
|
||||
}
|
||||
|
||||
type (
|
||||
ConditionStatus string
|
||||
)
|
||||
|
||||
const (
|
||||
ConditionStatusTrue ConditionStatus = "True"
|
||||
ConditionStatusFalse ConditionStatus = "False"
|
||||
ConditionStatusUnknown ConditionStatus = "Unknown"
|
||||
)
|
||||
|
||||
// GatewayConditionType is a type of condition associated with a
|
||||
// Gateway. This type should be used with the GatewayStatus.Conditions
|
||||
// field.
|
||||
type GatewayConditionType string
|
||||
|
||||
// GatewayConditionReason defines the set of reasons that explain why a
|
||||
// particular Gateway condition type has been raised.
|
||||
type GatewayConditionReason string
|
||||
|
||||
// the following are directly from the k8s spec
|
||||
const (
|
||||
// This condition is true when the controller managing the Gateway is
|
||||
// syntactically and semantically valid enough to produce some configuration
|
||||
// in the underlying data plane. This does not indicate whether or not the
|
||||
// configuration has been propagated to the data plane.
|
||||
//
|
||||
// Possible reasons for this condition to be True are:
|
||||
//
|
||||
// * "Accepted"
|
||||
//
|
||||
// Possible reasons for this condition to be False are:
|
||||
//
|
||||
// * InvalidCertificates
|
||||
//
|
||||
GatewayConditionAccepted GatewayConditionType = "Accepted"
|
||||
|
||||
// This reason is used with the "Accepted" condition when the condition is
|
||||
// True.
|
||||
GatewayReasonAccepted GatewayConditionReason = "Accepted"
|
||||
|
||||
// This reason is used with the "Accepted" condition when the gateway has multiple invalid
|
||||
// certificates and cannot bind to any routes
|
||||
GatewayReasonInvalidCertificates GatewayConditionReason = "InvalidCertificates"
|
||||
|
||||
// This condition indicates that the gateway was unable to resolve
|
||||
// conflicting specification requirements for this Listener. If a
|
||||
// Listener is conflicted, its network port should not be configured
|
||||
// on any network elements.
|
||||
//
|
||||
// Possible reasons for this condition to be true are:
|
||||
//
|
||||
// * "RouteConflict"
|
||||
//
|
||||
// Possible reasons for this condition to be False are:
|
||||
//
|
||||
// * "NoConflict"
|
||||
//
|
||||
// Controllers may raise this condition with other reasons,
|
||||
// but should prefer to use the reasons listed above to improve
|
||||
// interoperability.
|
||||
GatewayConditionConflicted GatewayConditionType = "Conflicted"
|
||||
// This reason is used with the "Conflicted" condition when the condition
|
||||
// is False.
|
||||
GatewayReasonNoConflict GatewayConditionReason = "NoConflict"
|
||||
// This reason is used with the "Conflicted" condition when the route is
|
||||
// in a conflicted state, such as when a TCPListener attempts to bind to two routes
|
||||
GatewayReasonRouteConflict GatewayConditionReason = "RouteConflict"
|
||||
|
||||
// This condition indicates whether the controller was able to
|
||||
// resolve all the object references for the Gateway. When setting this
|
||||
// condition to False, a ResourceReference to the misconfigured Listener should
|
||||
// be provided.
|
||||
//
|
||||
// Possible reasons for this condition to be true are:
|
||||
//
|
||||
// * "ResolvedRefs"
|
||||
//
|
||||
// Possible reasons for this condition to be False are:
|
||||
//
|
||||
// * "InvalidCertificateRef"
|
||||
// * "InvalidRouteKinds"
|
||||
// * "RefNotPermitted"
|
||||
//
|
||||
GatewayConditionResolvedRefs GatewayConditionType = "ResolvedRefs"
|
||||
|
||||
// This reason is used with the "ResolvedRefs" condition when the condition
|
||||
// is true.
|
||||
GatewayReasonResolvedRefs GatewayConditionReason = "ResolvedRefs"
|
||||
|
||||
// This reason is used with the "ResolvedRefs" condition when a
|
||||
// Listener has a TLS configuration with at least one TLS CertificateRef
|
||||
// that is invalid or does not exist.
|
||||
// A CertificateRef is considered invalid when it refers to a nonexistent
|
||||
// or unsupported resource or kind, or when the data within that resource
|
||||
// is malformed.
|
||||
// This reason must be used only when the reference is allowed, either by
|
||||
// referencing an object in the same namespace as the Gateway, or when
|
||||
// a cross-namespace reference has been explicitly allowed by a ReferenceGrant.
|
||||
// If the reference is not allowed, the reason RefNotPermitted must be used
|
||||
// instead.
|
||||
GatewayListenerReasonInvalidCertificateRef GatewayConditionReason = "InvalidCertificateRef"
|
||||
)
|
||||
|
||||
var validGatewayConditionReasonsMapping = map[GatewayConditionType]map[ConditionStatus][]GatewayConditionReason{
|
||||
GatewayConditionAccepted: {
|
||||
ConditionStatusTrue: {
|
||||
GatewayReasonAccepted,
|
||||
},
|
||||
ConditionStatusFalse: {
|
||||
GatewayListenerReasonInvalidCertificateRef, // TODO: remove this in follow up PR
|
||||
GatewayReasonInvalidCertificates,
|
||||
},
|
||||
ConditionStatusUnknown: {},
|
||||
},
|
||||
GatewayConditionConflicted: {
|
||||
ConditionStatusTrue: {
|
||||
GatewayReasonRouteConflict,
|
||||
},
|
||||
ConditionStatusFalse: {
|
||||
GatewayReasonNoConflict,
|
||||
},
|
||||
ConditionStatusUnknown: {},
|
||||
},
|
||||
GatewayConditionResolvedRefs: {
|
||||
ConditionStatusTrue: {
|
||||
GatewayReasonResolvedRefs,
|
||||
},
|
||||
ConditionStatusFalse: {
|
||||
GatewayListenerReasonInvalidCertificateRef,
|
||||
},
|
||||
ConditionStatusUnknown: {},
|
||||
},
|
||||
}
|
||||
|
||||
func ValidateGatewayConditionReason(name GatewayConditionType, status ConditionStatus, reason GatewayConditionReason) error {
|
||||
if err := checkConditionStatus(status); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
reasons, ok := validGatewayConditionReasonsMapping[name]
|
||||
if !ok {
|
||||
return fmt.Errorf("unrecognized GatewayConditionType %q", name)
|
||||
}
|
||||
|
||||
reasonsForStatus, ok := reasons[status]
|
||||
if !ok {
|
||||
return fmt.Errorf("unrecognized ConditionStatus %q", status)
|
||||
}
|
||||
|
||||
if !slices.Contains(reasonsForStatus, reason) {
|
||||
return fmt.Errorf("gateway condition reason %q not allowed for gateway condition type %q with status %q", reason, name, status)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RouteConditionType is a type of condition for a route.
|
||||
type RouteConditionType string
|
||||
|
||||
// RouteConditionReason is a reason for a route condition.
|
||||
type RouteConditionReason string
|
||||
|
||||
// The following statuses are taken from the K8's Spec
|
||||
// With the exception of: "RouteReasonInvalidDiscoveryChain" and "NoUpstreamServicesTargeted"
|
||||
const (
|
||||
// This condition indicates whether the route has been accepted or rejected
|
||||
// by a Gateway, and why.
|
||||
//
|
||||
// Possible reasons for this condition to be true are:
|
||||
//
|
||||
// * "Accepted"
|
||||
//
|
||||
// Possible reasons for this condition to be False are:
|
||||
//
|
||||
// * "InvalidDiscoveryChain"
|
||||
// * "NoUpstreamServicesTargeted"
|
||||
//
|
||||
//
|
||||
// Controllers may raise this condition with other reasons,
|
||||
// but should prefer to use the reasons listed above to improve
|
||||
// interoperability.
|
||||
RouteConditionAccepted RouteConditionType = "Accepted"
|
||||
|
||||
// This reason is used with the "Accepted" condition when the Route has been
|
||||
// accepted by the Gateway.
|
||||
RouteReasonAccepted RouteConditionReason = "Accepted"
|
||||
|
||||
// This reason is used with the "Accepted" condition when the route has an
|
||||
// invalid discovery chain, this includes conditions like the protocol being invalid
|
||||
// or the discovery chain failing to compile
|
||||
RouteReasonInvalidDiscoveryChain RouteConditionReason = "InvalidDiscoveryChain"
|
||||
|
||||
// This reason is used with the "Accepted" condition when the route
|
||||
RouteReasonNoUpstreamServicesTargeted RouteConditionReason = "NoUpstreamServicesTargeted"
|
||||
)
|
||||
|
||||
// the following statuses are custom to Consul
|
||||
const (
|
||||
// This condition indicates whether the route was able to successfully bind the
|
||||
// Listener on the gateway
|
||||
// Possible reasons for this condition to be true are:
|
||||
//
|
||||
// * "Bound"
|
||||
//
|
||||
// Possible reasons for this condition to be false are:
|
||||
//
|
||||
// * "FailedToBind"
|
||||
// * "GatewayNotFound"
|
||||
//
|
||||
RouteConditionBound RouteConditionType = "Bound"
|
||||
|
||||
// This reason is used with the "Bound" condition when the condition
|
||||
// is true
|
||||
RouteReasonBound RouteConditionReason = "Bound"
|
||||
|
||||
// This reason is used with the "Bound" condition when the route failed
|
||||
// to bind to the gateway
|
||||
RouteReasonFailedToBind RouteConditionReason = "FailedToBind"
|
||||
|
||||
// This reason is used with the "Bound" condition when the route fails
|
||||
// to find the gateway
|
||||
RouteReasonGatewayNotFound RouteConditionReason = "GatewayNotFound"
|
||||
)
|
||||
|
||||
var validRouteConditionReasonsMapping = map[RouteConditionType]map[ConditionStatus][]RouteConditionReason{
|
||||
RouteConditionAccepted: {
|
||||
ConditionStatusTrue: {
|
||||
RouteReasonAccepted,
|
||||
},
|
||||
ConditionStatusFalse: {
|
||||
RouteReasonInvalidDiscoveryChain,
|
||||
RouteReasonNoUpstreamServicesTargeted,
|
||||
},
|
||||
ConditionStatusUnknown: {},
|
||||
},
|
||||
RouteConditionBound: {
|
||||
ConditionStatusTrue: {
|
||||
RouteReasonBound,
|
||||
},
|
||||
ConditionStatusFalse: {
|
||||
RouteReasonGatewayNotFound,
|
||||
RouteReasonFailedToBind,
|
||||
},
|
||||
ConditionStatusUnknown: {},
|
||||
},
|
||||
}
|
||||
|
||||
func ValidateRouteConditionReason(name RouteConditionType, status ConditionStatus, reason RouteConditionReason) error {
|
||||
if err := checkConditionStatus(status); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
reasons, ok := validRouteConditionReasonsMapping[name]
|
||||
if !ok {
|
||||
return fmt.Errorf("unrecognized RouteConditionType %s", name)
|
||||
}
|
||||
|
||||
reasonsForStatus, ok := reasons[status]
|
||||
if !ok {
|
||||
return fmt.Errorf("unrecognized ConditionStatus %s", name)
|
||||
}
|
||||
|
||||
if !slices.Contains(reasonsForStatus, reason) {
|
||||
return fmt.Errorf("route condition reason %s not allowed for route condition type %s with status %s", reason, name, status)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkConditionStatus(status ConditionStatus) error {
|
||||
switch status {
|
||||
case ConditionStatusTrue, ConditionStatusFalse, ConditionStatusUnknown:
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("unrecognized condition status: %q", status)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,187 @@
|
|||
package api
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestValidateGatewayConditionReasonWithValidCombinations(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
status ConditionStatus
|
||||
reason GatewayConditionReason
|
||||
condType GatewayConditionType
|
||||
}{
|
||||
"accepted": {
|
||||
status: ConditionStatusTrue,
|
||||
reason: GatewayReasonAccepted,
|
||||
condType: GatewayConditionAccepted,
|
||||
},
|
||||
"accepted invalid certificates": {
|
||||
status: ConditionStatusFalse,
|
||||
reason: GatewayReasonInvalidCertificates,
|
||||
condType: GatewayConditionAccepted,
|
||||
},
|
||||
"conflicted": {
|
||||
status: ConditionStatusTrue,
|
||||
reason: GatewayReasonRouteConflict,
|
||||
condType: GatewayConditionConflicted,
|
||||
},
|
||||
"conflicted no conflicts": {
|
||||
status: ConditionStatusFalse,
|
||||
reason: GatewayReasonNoConflict,
|
||||
condType: GatewayConditionConflicted,
|
||||
},
|
||||
|
||||
"resolved refs": {
|
||||
status: ConditionStatusTrue,
|
||||
reason: GatewayReasonResolvedRefs,
|
||||
condType: GatewayConditionResolvedRefs,
|
||||
},
|
||||
"resolved refs invalid certificate ref": {
|
||||
status: ConditionStatusFalse,
|
||||
reason: GatewayListenerReasonInvalidCertificateRef,
|
||||
condType: GatewayConditionResolvedRefs,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
err := ValidateGatewayConditionReason(tc.condType, tc.status, tc.reason)
|
||||
if err != nil {
|
||||
t.Error("Expected gateway condition reason to be valid but it was not")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateGatewayConditionReasonWithInvalidCombinationsReturnsError(t *testing.T) {
|
||||
// This is not an exhaustive list of all invalid combinations, just a few to confirm
|
||||
testCases := map[string]struct {
|
||||
status ConditionStatus
|
||||
reason GatewayConditionReason
|
||||
condType GatewayConditionType
|
||||
}{
|
||||
"reason and condition type are valid but status is not": {
|
||||
status: ConditionStatusTrue,
|
||||
reason: GatewayReasonNoConflict,
|
||||
condType: GatewayConditionConflicted,
|
||||
},
|
||||
"reason and status are valid but condition type is not": {
|
||||
status: ConditionStatusFalse,
|
||||
reason: GatewayReasonNoConflict,
|
||||
condType: GatewayConditionResolvedRefs,
|
||||
},
|
||||
"condition type and status are valid but status is not": {
|
||||
status: ConditionStatusTrue,
|
||||
reason: GatewayReasonNoConflict,
|
||||
condType: GatewayConditionAccepted,
|
||||
},
|
||||
"all are invalid": {
|
||||
status: ConditionStatusUnknown,
|
||||
reason: GatewayReasonAccepted,
|
||||
condType: GatewayConditionResolvedRefs,
|
||||
},
|
||||
"pass something other than a condition status": {
|
||||
status: ConditionStatus("hello"),
|
||||
reason: GatewayReasonAccepted,
|
||||
condType: GatewayConditionResolvedRefs,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
err := ValidateGatewayConditionReason(tc.condType, tc.status, tc.reason)
|
||||
if err == nil {
|
||||
t.Error("Expected route condition reason to be invalid, but it was valid")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateRouteConfigReasonWithValidCombinations(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
status ConditionStatus
|
||||
reason RouteConditionReason
|
||||
condType RouteConditionType
|
||||
}{
|
||||
"accepted all around": {
|
||||
status: ConditionStatusTrue,
|
||||
reason: RouteReasonAccepted,
|
||||
condType: RouteConditionAccepted,
|
||||
},
|
||||
"accepted invalid discovery chain": {
|
||||
status: ConditionStatusFalse,
|
||||
reason: RouteReasonInvalidDiscoveryChain,
|
||||
condType: RouteConditionAccepted,
|
||||
},
|
||||
"accepted no upstream services targeted": {
|
||||
status: ConditionStatusFalse,
|
||||
reason: RouteReasonNoUpstreamServicesTargeted,
|
||||
condType: RouteConditionAccepted,
|
||||
},
|
||||
"route bound": {
|
||||
status: ConditionStatusTrue,
|
||||
reason: RouteReasonBound,
|
||||
condType: RouteConditionBound,
|
||||
},
|
||||
"route bound gateway not found": {
|
||||
status: ConditionStatusFalse,
|
||||
reason: RouteReasonGatewayNotFound,
|
||||
condType: RouteConditionBound,
|
||||
},
|
||||
"route bound failed to bind": {
|
||||
status: ConditionStatusFalse,
|
||||
reason: RouteReasonFailedToBind,
|
||||
condType: RouteConditionBound,
|
||||
},
|
||||
}
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
err := ValidateRouteConditionReason(tc.condType, tc.status, tc.reason)
|
||||
if err != nil {
|
||||
t.Errorf("Expected route condition reason to be valid, it was not")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateRouteConditionReasonInvalidCombinationsCausePanic(t *testing.T) {
|
||||
// This is not an exhaustive list of all invalid combinations, just a few to confirm
|
||||
testCases := map[string]struct {
|
||||
status ConditionStatus
|
||||
reason RouteConditionReason
|
||||
condType RouteConditionType
|
||||
}{
|
||||
"reason and condition type are valid but status is not": {
|
||||
status: ConditionStatusTrue,
|
||||
reason: RouteReasonNoUpstreamServicesTargeted,
|
||||
condType: RouteConditionAccepted,
|
||||
},
|
||||
"reason and status are valid but condition type is not": {
|
||||
status: ConditionStatusFalse,
|
||||
reason: RouteReasonInvalidDiscoveryChain,
|
||||
condType: RouteConditionBound,
|
||||
},
|
||||
"condition type and status are valid but status is not": {
|
||||
status: ConditionStatusUnknown,
|
||||
reason: RouteReasonBound,
|
||||
condType: RouteConditionBound,
|
||||
},
|
||||
"all are invalid": {
|
||||
status: ConditionStatusUnknown,
|
||||
reason: RouteReasonGatewayNotFound,
|
||||
condType: RouteConditionBound,
|
||||
},
|
||||
"pass something other than a condition status": {
|
||||
status: ConditionStatus("hello"),
|
||||
reason: RouteReasonAccepted,
|
||||
condType: RouteConditionAccepted,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
err := ValidateRouteConditionReason(tc.condType, tc.status, tc.reason)
|
||||
if err == nil {
|
||||
t.Error("Expected route condition reason to be invalid, it was valid")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@ go 1.19
|
|||
replace github.com/hashicorp/consul/sdk => ../sdk
|
||||
|
||||
require (
|
||||
github.com/google/go-cmp v0.5.7
|
||||
github.com/google/go-cmp v0.5.8
|
||||
github.com/hashicorp/consul/sdk v0.13.1
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1
|
||||
github.com/hashicorp/go-hclog v0.12.0
|
||||
|
@ -14,6 +14,7 @@ require (
|
|||
github.com/hashicorp/serf v0.10.1
|
||||
github.com/mitchellh/mapstructure v1.4.1
|
||||
github.com/stretchr/testify v1.7.0
|
||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29
|
||||
)
|
||||
|
||||
require (
|
||||
|
@ -40,7 +41,6 @@ require (
|
|||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect
|
||||
github.com/stretchr/objx v0.1.0 // indirect
|
||||
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f // indirect
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
golang.org/x/sys v0.1.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
||||
)
|
||||
|
|
12
api/go.sum
12
api/go.sum
|
@ -13,8 +13,8 @@ github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
|
|||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
|
||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM=
|
||||
|
@ -96,6 +96,8 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc
|
|||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
|
||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug=
|
||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
|
@ -118,8 +120,9 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg=
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
|
@ -128,9 +131,6 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
|
|
@ -36,6 +36,7 @@ require (
|
|||
github.com/mitchellh/mapstructure v1.4.1 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect
|
||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect
|
||||
golang.org/x/sys v0.1.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
|
|
@ -55,7 +55,7 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
|
||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/hashicorp/consul/sdk v0.13.1 h1:EygWVWWMczTzXGpO93awkHFzfUka6hLYJ0qhETd+6lY=
|
||||
|
@ -143,6 +143,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
|||
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug=
|
||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
|
@ -185,8 +187,9 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg=
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
|
@ -200,7 +203,6 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
|
|||
golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
|
|
4
go.mod
4
go.mod
|
@ -227,11 +227,11 @@ require (
|
|||
go.opencensus.io v0.23.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v0.7.0 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91 // indirect
|
||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect
|
||||
golang.org/x/term v0.5.0 // indirect
|
||||
golang.org/x/text v0.7.0 // indirect
|
||||
golang.org/x/tools v0.1.12 // indirect
|
||||
golang.org/x/tools v0.2.0 // indirect
|
||||
google.golang.org/api v0.57.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
|
|
8
go.sum
8
go.sum
|
@ -1115,8 +1115,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
|||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91 h1:tnebWN09GYg9OLPss1KXj8txwZc6X6uMr6VFdcGNbHw=
|
||||
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
|
||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug=
|
||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
|
@ -1426,8 +1426,8 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
|||
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
|
||||
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
|
|
@ -77,7 +77,7 @@ require (
|
|||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect
|
||||
github.com/sirupsen/logrus v1.8.1 // indirect
|
||||
go.opencensus.io v0.23.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230303215020-44a13b063f3e // indirect
|
||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect
|
||||
golang.org/x/net v0.8.0 // indirect
|
||||
golang.org/x/sys v0.6.0 // indirect
|
||||
golang.org/x/text v0.8.0 // indirect
|
||||
|
|
|
@ -874,8 +874,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
|||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20230303215020-44a13b063f3e h1:S8xf0d0OEmWrClvbMiUSp+7cGD00txONylwExlf9wR0=
|
||||
golang.org/x/exp v0.0.0-20230303215020-44a13b063f3e/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug=
|
||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
|
|
|
@ -137,7 +137,7 @@ func isBound(conditions []api.Condition) bool {
|
|||
|
||||
func conditionStatusIsValue(typeName string, statusValue string, conditions []api.Condition) bool {
|
||||
for _, c := range conditions {
|
||||
if c.Type == typeName && c.Status == statusValue {
|
||||
if c.Type == typeName && string(c.Status) == statusValue {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ require (
|
|||
github.com/fatih/color v1.13.0 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/google/btree v1.0.0 // indirect
|
||||
github.com/google/go-cmp v0.5.8 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-hclog v1.2.1 // indirect
|
||||
|
@ -47,6 +46,7 @@ require (
|
|||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v0.7.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect
|
||||
golang.org/x/net v0.4.0 // indirect
|
||||
golang.org/x/sys v0.3.0 // indirect
|
||||
golang.org/x/text v0.5.0 // indirect
|
||||
|
|
|
@ -79,7 +79,6 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
|
@ -211,6 +210,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
|||
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug=
|
||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
|
|
Loading…
Reference in New Issue