mirror of https://github.com/hashicorp/consul
Backport of APIGW Normalize Status Conditions into release/1.15.x (#17844)
* 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 * Resolve sneaky merge conflicts --------- Co-authored-by: John Maguire <john.maguire@hashicorp.com> Co-authored-by: Nathan Coleman <nathan.coleman@hashicorp.com>pull/17857/head
parent
1291786d76
commit
65cc60e87f
|
@ -8,11 +8,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"
|
||||
|
@ -23,6 +18,11 @@ import (
|
|||
"github.com/hashicorp/consul/api"
|
||||
"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) {
|
||||
|
@ -1361,9 +1361,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{
|
||||
|
@ -1392,7 +1393,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{
|
||||
|
@ -1416,7 +1417,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
|
||||
|
@ -1445,7 +1446,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,77 +0,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
|
||||
}
|
|
@ -5,7 +5,6 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-hclog"
|
||||
"github.com/hashicorp/go-memdb"
|
||||
|
@ -17,6 +16,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 (
|
||||
|
@ -208,8 +208,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")
|
||||
|
@ -249,18 +247,18 @@ func (r *apiGatewayReconciler) reconcileGateway(_ context.Context, req controlle
|
|||
SectionName: bound.Name,
|
||||
EnterpriseMeta: meta.BoundGateway.EnterpriseMeta,
|
||||
}
|
||||
updater.SetCondition(conditions.validCertificate(listenerRef))
|
||||
updater.SetCondition(validCertificate(listenerRef))
|
||||
return nil
|
||||
})
|
||||
|
||||
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
|
||||
|
@ -272,19 +270,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
|
||||
|
@ -364,8 +362,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")
|
||||
|
@ -445,23 +441,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
|
||||
|
@ -470,12 +466,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
|
||||
|
@ -489,7 +485,7 @@ PARENT_LOOP:
|
|||
if _, ok := bindErrors[ref]; ok {
|
||||
continue PARENT_LOOP
|
||||
}
|
||||
updater.SetCondition(conditions.gatewayNotFound(ref))
|
||||
updater.SetCondition(gatewayNotFound(ref))
|
||||
}
|
||||
|
||||
return finalize(modifiedGateways)
|
||||
|
@ -559,8 +555,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
|
||||
|
@ -688,13 +682,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)
|
||||
}
|
||||
|
||||
|
@ -771,7 +765,6 @@ func (g *gatewayMeta) checkCertificates(store *state.Store) (map[structs.Resourc
|
|||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -789,8 +782,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,
|
||||
|
@ -801,19 +792,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 {
|
||||
|
@ -856,162 +845,145 @@ 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
|
||||
// gatewayAccepted marks the APIGateway as valid.
|
||||
func gatewayAccepted() structs.Condition {
|
||||
return structs.NewGatewayCondition(
|
||||
api.GatewayConditionAccepted,
|
||||
api.ConditionStatusTrue,
|
||||
api.GatewayReasonAccepted,
|
||||
"gateway is valid",
|
||||
structs.ResourceReference{},
|
||||
)
|
||||
}
|
||||
|
||||
// newGatewayConditionGenerator initializes a status conditions generator
|
||||
func newGatewayConditionGenerator() *gatewayConditionGenerator {
|
||||
return &gatewayConditionGenerator{
|
||||
now: pointerTo(time.Now().UTC()),
|
||||
}
|
||||
// validCertificate returns a condition used when a gateway references a
|
||||
// certificate that does exist. It takes a ref used to scope the condition
|
||||
// to a given APIGateway listener.
|
||||
func validCertificate(ref structs.ResourceReference) structs.Condition {
|
||||
return structs.NewGatewayCondition(
|
||||
api.GatewayConditionResolvedRefs,
|
||||
api.ConditionStatusTrue,
|
||||
api.GatewayReasonResolvedRefs,
|
||||
"resolved refs",
|
||||
ref,
|
||||
)
|
||||
}
|
||||
|
||||
// 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: "ResolvedRefs",
|
||||
Status: "False",
|
||||
Reason: "InvalidCertificate",
|
||||
Message: err.Error(),
|
||||
Resource: pointerTo(ref),
|
||||
LastTransitionTime: g.now,
|
||||
}
|
||||
}
|
||||
|
||||
func (g *gatewayConditionGenerator) validCertificate(ref structs.ResourceReference) structs.Condition {
|
||||
return structs.Condition{
|
||||
Type: "ResolvedRefs",
|
||||
Status: "True",
|
||||
Reason: "ResolvedRefs",
|
||||
Message: "resolved refs",
|
||||
Resource: pointerTo(ref),
|
||||
LastTransitionTime: g.now,
|
||||
}
|
||||
func invalidCertificate(ref structs.ResourceReference, err error) structs.Condition {
|
||||
return structs.NewGatewayCondition(
|
||||
api.GatewayConditionResolvedRefs,
|
||||
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.
|
||||
|
@ -1051,7 +1023,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 {
|
||||
|
@ -1059,7 +1030,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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,14 +8,15 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-hclog"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/hashicorp/consul/acl"
|
||||
"github.com/hashicorp/consul/agent/consul/controller"
|
||||
"github.com/hashicorp/consul/agent/consul/fsm"
|
||||
"github.com/hashicorp/consul/agent/consul/state"
|
||||
"github.com/hashicorp/consul/agent/consul/stream"
|
||||
"github.com/hashicorp/consul/agent/structs"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestBoundAPIGatewayBindRoute(t *testing.T) {
|
||||
|
@ -51,7 +52,7 @@ func TestBoundAPIGatewayBindRoute(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -68,7 +69,7 @@ func TestBoundAPIGatewayBindRoute(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -128,7 +129,7 @@ func TestBoundAPIGatewayBindRoute(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -144,7 +145,7 @@ func TestBoundAPIGatewayBindRoute(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -439,7 +440,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -458,7 +459,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -553,7 +554,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -578,7 +579,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -602,7 +603,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -671,7 +672,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -690,7 +691,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -748,7 +749,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -767,7 +768,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -837,7 +838,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -856,7 +857,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -920,7 +921,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -953,7 +954,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -977,7 +978,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1060,7 +1061,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1079,7 +1080,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1129,7 +1130,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1154,7 +1155,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1173,7 +1174,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1189,7 +1190,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1250,7 +1251,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1269,7 +1270,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1313,7 +1314,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1332,14 +1333,13 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedBoundAPIGateways: []*structs.BoundAPIGatewayConfigEntry{
|
||||
{
|
||||
|
||||
Name: "Gateway",
|
||||
Listeners: []structs.BoundAPIGatewayListener{
|
||||
{
|
||||
|
@ -1431,7 +1431,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1449,7 +1449,7 @@ func TestBindRoutesToGateways(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1489,7 +1489,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
|
||||
|
@ -1517,7 +1516,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1548,7 +1547,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeNoUpstreams(),
|
||||
routeNoUpstreams(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1574,7 +1573,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeNoUpstreams(),
|
||||
routeNoUpstreams(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1624,8 +1623,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")),
|
||||
|
@ -1642,7 +1641,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",
|
||||
|
@ -1690,7 +1689,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeInvalidDiscoveryChain(errInvalidProtocol),
|
||||
routeInvalidDiscoveryChain(errInvalidProtocol),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1729,8 +1728,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,
|
||||
|
@ -1783,8 +1782,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,
|
||||
|
@ -1847,8 +1846,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,
|
||||
|
@ -1916,8 +1915,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,
|
||||
|
@ -1952,7 +1951,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1972,7 +1971,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2002,14 +2001,14 @@ 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,
|
||||
SectionName: "listener",
|
||||
}),
|
||||
conditions.validCertificate(structs.ResourceReference{
|
||||
validCertificate(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *defaultMeta,
|
||||
|
@ -2024,8 +2023,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,
|
||||
|
@ -2060,7 +2059,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2100,14 +2099,14 @@ 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,
|
||||
SectionName: "listener",
|
||||
}),
|
||||
conditions.validCertificate(structs.ResourceReference{
|
||||
validCertificate(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *defaultMeta,
|
||||
|
@ -2122,8 +2121,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,
|
||||
|
@ -2162,7 +2161,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2180,7 +2179,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2229,14 +2228,14 @@ 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,
|
||||
SectionName: "listener",
|
||||
}),
|
||||
conditions.validCertificate(structs.ResourceReference{
|
||||
validCertificate(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *defaultMeta,
|
||||
|
@ -2251,8 +2250,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,
|
||||
|
@ -2266,8 +2265,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,
|
||||
|
@ -2308,7 +2307,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2328,7 +2327,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2378,14 +2377,14 @@ 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,
|
||||
SectionName: "listener",
|
||||
}),
|
||||
conditions.validCertificate(structs.ResourceReference{
|
||||
validCertificate(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *defaultMeta,
|
||||
|
@ -2400,8 +2399,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,
|
||||
|
@ -2415,8 +2414,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,
|
||||
|
@ -2525,14 +2524,14 @@ 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,
|
||||
SectionName: "listener",
|
||||
}),
|
||||
conditions.validCertificate(structs.ResourceReference{
|
||||
validCertificate(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
EnterpriseMeta: *defaultMeta,
|
||||
|
@ -2547,8 +2546,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,
|
||||
|
@ -2562,8 +2561,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,
|
||||
|
@ -2604,7 +2603,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2622,7 +2621,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
newGatewayConditionGenerator().routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2685,23 +2684,23 @@ 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",
|
||||
}),
|
||||
conditions.validCertificate(structs.ResourceReference{
|
||||
validCertificate(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "http-listener",
|
||||
}),
|
||||
conditions.validCertificate(structs.ResourceReference{
|
||||
validCertificate(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "tcp-listener",
|
||||
|
@ -2715,8 +2714,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,
|
||||
|
@ -2730,8 +2729,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,
|
||||
|
@ -2757,8 +2756,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,
|
||||
|
@ -2812,7 +2811,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",
|
||||
|
@ -2827,7 +2826,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeAccepted(),
|
||||
routeAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2846,8 +2845,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,
|
||||
|
@ -2901,7 +2900,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",
|
||||
|
@ -2916,7 +2915,7 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
EnterpriseMeta: *defaultMeta,
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.routeNoUpstreams(),
|
||||
routeNoUpstreams(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2944,8 +2943,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,
|
||||
|
@ -2970,8 +2969,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")),
|
||||
|
@ -3001,8 +3000,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",
|
||||
|
@ -3044,13 +3043,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.validCertificate(structs.ResourceReference{
|
||||
validCertificate(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "http-listener",
|
||||
|
@ -3064,8 +3063,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 ''")),
|
||||
|
@ -3078,8 +3077,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",
|
||||
}),
|
||||
|
@ -3114,8 +3113,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,
|
||||
|
@ -3150,8 +3149,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",
|
||||
}),
|
||||
|
@ -3191,8 +3190,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",
|
||||
|
@ -3217,8 +3216,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",
|
||||
|
@ -3262,8 +3261,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",
|
||||
}),
|
||||
|
@ -3278,8 +3277,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",
|
||||
}),
|
||||
|
@ -3328,13 +3327,13 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
}},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.invalidCertificate(structs.ResourceReference{
|
||||
invalidCertificate(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "http-listener",
|
||||
}, errors.New("certificate \"certificate\" not found")),
|
||||
conditions.invalidCertificates(),
|
||||
conditions.gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
invalidCertificates(),
|
||||
gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "http-listener",
|
||||
|
@ -3397,13 +3396,13 @@ 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",
|
||||
}),
|
||||
conditions.validCertificate(structs.ResourceReference{
|
||||
validCertificate(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "http-listener",
|
||||
|
@ -3500,27 +3499,27 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.validCertificate(structs.ResourceReference{
|
||||
validCertificate(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "listener-1",
|
||||
}),
|
||||
conditions.validCertificate(structs.ResourceReference{
|
||||
validCertificate(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "listener-2",
|
||||
}),
|
||||
conditions.gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "listener-1",
|
||||
}),
|
||||
conditions.gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "listener-2",
|
||||
}),
|
||||
conditions.gatewayAccepted(),
|
||||
gatewayAccepted(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -3615,23 +3614,23 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.invalidCertificate(structs.ResourceReference{
|
||||
invalidCertificate(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "listener-1",
|
||||
}, errors.New("certificate \"missing certificate\" not found")),
|
||||
conditions.invalidCertificate(structs.ResourceReference{
|
||||
invalidCertificate(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "listener-2",
|
||||
}, errors.New("certificate \"another missing certificate\" not found")),
|
||||
conditions.invalidCertificates(),
|
||||
conditions.gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
invalidCertificates(),
|
||||
gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "listener-1",
|
||||
}),
|
||||
conditions.gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "listener-2",
|
||||
|
@ -3719,24 +3718,24 @@ func TestAPIGatewayController(t *testing.T) {
|
|||
},
|
||||
Status: structs.Status{
|
||||
Conditions: []structs.Condition{
|
||||
conditions.invalidCertificate(structs.ResourceReference{
|
||||
invalidCertificate(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "invalid-listener",
|
||||
}, errors.New("certificate \"missing certificate\" not found")),
|
||||
conditions.validCertificate(structs.ResourceReference{
|
||||
validCertificate(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "valid-listener",
|
||||
}),
|
||||
|
||||
conditions.invalidCertificates(),
|
||||
conditions.gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
invalidCertificates(),
|
||||
gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "valid-listener",
|
||||
}),
|
||||
conditions.gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
gatewayListenerNoConflicts(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "invalid-listener",
|
||||
|
@ -3788,12 +3787,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",
|
||||
|
@ -3824,13 +3823,13 @@ 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",
|
||||
}),
|
||||
conditions.validCertificate(structs.ResourceReference{
|
||||
validCertificate(structs.ResourceReference{
|
||||
Kind: structs.APIGateway,
|
||||
Name: "gateway",
|
||||
SectionName: "http-listener",
|
||||
|
@ -4094,12 +4093,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...)
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/hashicorp/consul/acl"
|
||||
"github.com/hashicorp/consul/api"
|
||||
)
|
||||
|
||||
// ResourceReference is a reference to a ConfigEntry
|
||||
|
@ -64,30 +65,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 {
|
||||
|
@ -111,6 +88,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
|
||||
|
@ -192,3 +194,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
|
||||
}
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
// ResourceReference is a reference to a ConfigEntry
|
||||
|
@ -43,7 +46,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
|
||||
|
@ -55,3 +58,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
|
||||
)
|
||||
|
|
14
api/go.sum
14
api/go.sum
|
@ -13,10 +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/hashicorp/consul/sdk v0.13.1 h1:EygWVWWMczTzXGpO93awkHFzfUka6hLYJ0qhETd+6lY=
|
||||
github.com/hashicorp/consul/sdk v0.13.1/go.mod h1:SW/mM4LbKfqmMvcFu8v+eiQQ7oitXEFeiBe9StxERb0=
|
||||
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=
|
||||
|
@ -98,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=
|
||||
|
@ -120,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=
|
||||
|
@ -130,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/api v1.21.0 h1:WMR2JiyuaQWRAMFaOGiYfY4Q4HRpyYRe/oYQofjyduM=
|
||||
|
@ -145,6 +145,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=
|
||||
|
@ -187,8 +189,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=
|
||||
|
@ -202,7 +205,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=
|
||||
|
|
2
go.mod
2
go.mod
|
@ -230,7 +230,7 @@ require (
|
|||
go.opencensus.io v0.23.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.16.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.6.0 // indirect
|
||||
golang.org/x/text v0.8.0 // indirect
|
||||
|
|
4
go.sum
4
go.sum
|
@ -1124,8 +1124,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=
|
||||
|
|
|
@ -71,6 +71,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-20230321023759-10a507213a29 // indirect
|
||||
golang.org/x/net v0.8.0 // indirect
|
||||
golang.org/x/sys v0.6.0 // indirect
|
||||
golang.org/x/tools v0.6.0 // indirect
|
||||
|
|
|
@ -862,6 +862,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-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=
|
||||
|
|
|
@ -134,7 +134,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=
|
||||
|
@ -215,6 +214,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