Merge pull request #14364 from hashicorp/peering/term-delete
This commit is contained in:
commit
69d99aa8c0
|
@ -0,0 +1,3 @@
|
|||
```release-note:bugfix
|
||||
peering: Fix issue preventing deletion and recreation of peerings in TERMINATED state.
|
||||
```
|
|
@ -40,6 +40,7 @@ func TestLeader_PeeringSync_Lifecycle_ClientDeletion(t *testing.T) {
|
|||
testLeader_PeeringSync_Lifecycle_ClientDeletion(t, true)
|
||||
})
|
||||
}
|
||||
|
||||
func testLeader_PeeringSync_Lifecycle_ClientDeletion(t *testing.T, enableTLS bool) {
|
||||
if testing.Short() {
|
||||
t.Skip("too slow for testing.Short")
|
||||
|
@ -137,9 +138,11 @@ func testLeader_PeeringSync_Lifecycle_ClientDeletion(t *testing.T, enableTLS boo
|
|||
|
||||
// Delete the peering to trigger the termination sequence.
|
||||
deleted := &pbpeering.Peering{
|
||||
ID: p.Peering.ID,
|
||||
Name: "my-peer-acceptor",
|
||||
DeletedAt: structs.TimeToProto(time.Now()),
|
||||
ID: p.Peering.ID,
|
||||
Name: "my-peer-acceptor",
|
||||
State: pbpeering.PeeringState_DELETING,
|
||||
PeerServerAddresses: p.Peering.PeerServerAddresses,
|
||||
DeletedAt: structs.TimeToProto(time.Now()),
|
||||
}
|
||||
require.NoError(t, dialer.fsm.State().PeeringWrite(2000, &pbpeering.PeeringWriteRequest{Peering: deleted}))
|
||||
dialer.logger.Trace("deleted peering for my-peer-acceptor")
|
||||
|
@ -262,6 +265,7 @@ func testLeader_PeeringSync_Lifecycle_AcceptorDeletion(t *testing.T, enableTLS b
|
|||
deleted := &pbpeering.Peering{
|
||||
ID: p.Peering.PeerID,
|
||||
Name: "my-peer-dialer",
|
||||
State: pbpeering.PeeringState_DELETING,
|
||||
DeletedAt: structs.TimeToProto(time.Now()),
|
||||
}
|
||||
|
||||
|
@ -431,6 +435,7 @@ func TestLeader_Peering_DeferredDeletion(t *testing.T) {
|
|||
Peering: &pbpeering.Peering{
|
||||
ID: peerID,
|
||||
Name: peerName,
|
||||
State: pbpeering.PeeringState_DELETING,
|
||||
DeletedAt: structs.TimeToProto(time.Now()),
|
||||
},
|
||||
}))
|
||||
|
@ -1165,6 +1170,7 @@ func TestLeader_Peering_NoDeletionWhenPeeringDisabled(t *testing.T) {
|
|||
Peering: &pbpeering.Peering{
|
||||
ID: peerID,
|
||||
Name: peerName,
|
||||
State: pbpeering.PeeringState_DELETING,
|
||||
DeletedAt: structs.TimeToProto(time.Now()),
|
||||
},
|
||||
}))
|
||||
|
|
|
@ -535,6 +535,12 @@ func (s *Store) PeeringWrite(idx uint64, req *pbpeering.PeeringWriteRequest) err
|
|||
if req.Peering.Name == "" {
|
||||
return errors.New("Missing Peering Name")
|
||||
}
|
||||
if req.Peering.State == pbpeering.PeeringState_DELETING && (req.Peering.DeletedAt == nil || structs.IsZeroProtoTime(req.Peering.DeletedAt)) {
|
||||
return errors.New("Missing deletion time for peering in deleting state")
|
||||
}
|
||||
if req.Peering.DeletedAt != nil && !structs.IsZeroProtoTime(req.Peering.DeletedAt) && req.Peering.State != pbpeering.PeeringState_DELETING {
|
||||
return fmt.Errorf("Unexpected state for peering with deletion time: %s", pbpeering.PeeringStateToAPI(req.Peering.State))
|
||||
}
|
||||
|
||||
// Ensure the name is unique (cannot conflict with another peering with a different ID).
|
||||
_, existing, err := peeringReadTxn(tx, nil, Query{
|
||||
|
@ -546,11 +552,32 @@ func (s *Store) PeeringWrite(idx uint64, req *pbpeering.PeeringWriteRequest) err
|
|||
}
|
||||
|
||||
if existing != nil {
|
||||
if req.Peering.ShouldDial() != existing.ShouldDial() {
|
||||
return fmt.Errorf("Cannot switch peering dialing mode from %t to %t", existing.ShouldDial(), req.Peering.ShouldDial())
|
||||
}
|
||||
|
||||
if req.Peering.ID != existing.ID {
|
||||
return fmt.Errorf("A peering already exists with the name %q and a different ID %q", req.Peering.Name, existing.ID)
|
||||
}
|
||||
|
||||
// Nothing to do if our peer wants to terminate the peering but the peering is already marked for deletion.
|
||||
if existing.State == pbpeering.PeeringState_DELETING && req.Peering.State == pbpeering.PeeringState_TERMINATED {
|
||||
return nil
|
||||
}
|
||||
|
||||
// No-op deletion
|
||||
if existing.State == pbpeering.PeeringState_DELETING && req.Peering.State == pbpeering.PeeringState_DELETING {
|
||||
return nil
|
||||
}
|
||||
|
||||
// No-op termination
|
||||
if existing.State == pbpeering.PeeringState_TERMINATED && req.Peering.State == pbpeering.PeeringState_TERMINATED {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Prevent modifications to Peering marked for deletion.
|
||||
if !existing.IsActive() {
|
||||
// This blocks generating new peering tokens or re-establishing the peering until the peering is done deleting.
|
||||
if existing.State == pbpeering.PeeringState_DELETING {
|
||||
return fmt.Errorf("cannot write to peering that is marked for deletion")
|
||||
}
|
||||
|
||||
|
@ -582,8 +609,8 @@ func (s *Store) PeeringWrite(idx uint64, req *pbpeering.PeeringWriteRequest) err
|
|||
req.Peering.ModifyIndex = idx
|
||||
}
|
||||
|
||||
// Ensure associated secrets are cleaned up when a peering is marked for deletion.
|
||||
if req.Peering.State == pbpeering.PeeringState_DELETING {
|
||||
// Ensure associated secrets are cleaned up when a peering is marked for deletion or terminated.
|
||||
if !req.Peering.IsActive() {
|
||||
if err := peeringSecretsDeleteTxn(tx, req.Peering.ID, req.Peering.ShouldDial()); err != nil {
|
||||
return fmt.Errorf("failed to delete peering secrets: %w", err)
|
||||
}
|
||||
|
|
|
@ -950,6 +950,7 @@ func TestStore_Peering_Watch(t *testing.T) {
|
|||
Peering: &pbpeering.Peering{
|
||||
ID: testFooPeerID,
|
||||
Name: "foo",
|
||||
State: pbpeering.PeeringState_DELETING,
|
||||
DeletedAt: structs.TimeToProto(time.Now()),
|
||||
},
|
||||
})
|
||||
|
@ -976,6 +977,7 @@ func TestStore_Peering_Watch(t *testing.T) {
|
|||
err := s.PeeringWrite(lastIdx, &pbpeering.PeeringWriteRequest{Peering: &pbpeering.Peering{
|
||||
ID: testBarPeerID,
|
||||
Name: "bar",
|
||||
State: pbpeering.PeeringState_DELETING,
|
||||
DeletedAt: structs.TimeToProto(time.Now()),
|
||||
},
|
||||
})
|
||||
|
@ -1077,6 +1079,7 @@ func TestStore_PeeringList_Watch(t *testing.T) {
|
|||
Peering: &pbpeering.Peering{
|
||||
ID: testFooPeerID,
|
||||
Name: "foo",
|
||||
State: pbpeering.PeeringState_DELETING,
|
||||
DeletedAt: structs.TimeToProto(time.Now()),
|
||||
Partition: structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty(),
|
||||
},
|
||||
|
@ -1112,16 +1115,22 @@ func TestStore_PeeringWrite(t *testing.T) {
|
|||
// Each case depends on the previous.
|
||||
s := NewStateStore(nil)
|
||||
|
||||
testTime := time.Now()
|
||||
|
||||
type expectations struct {
|
||||
peering *pbpeering.Peering
|
||||
secrets *pbpeering.PeeringSecrets
|
||||
err string
|
||||
}
|
||||
type testcase struct {
|
||||
name string
|
||||
input *pbpeering.PeeringWriteRequest
|
||||
expectSecrets *pbpeering.PeeringSecrets
|
||||
expectErr string
|
||||
name string
|
||||
input *pbpeering.PeeringWriteRequest
|
||||
expect expectations
|
||||
}
|
||||
run := func(t *testing.T, tc testcase) {
|
||||
err := s.PeeringWrite(10, tc.input)
|
||||
if tc.expectErr != "" {
|
||||
testutil.RequireErrorContains(t, err, tc.expectErr)
|
||||
if tc.expect.err != "" {
|
||||
testutil.RequireErrorContains(t, err, tc.expect.err)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
@ -1133,52 +1142,176 @@ func TestStore_PeeringWrite(t *testing.T) {
|
|||
_, p, err := s.PeeringRead(nil, q)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, p)
|
||||
require.Equal(t, tc.input.Peering.State, p.State)
|
||||
require.Equal(t, tc.input.Peering.Name, p.Name)
|
||||
require.Equal(t, tc.expect.peering.State, p.State)
|
||||
require.Equal(t, tc.expect.peering.Name, p.Name)
|
||||
require.Equal(t, tc.expect.peering.Meta, p.Meta)
|
||||
if tc.expect.peering.DeletedAt != nil {
|
||||
require.Equal(t, tc.expect.peering.DeletedAt, p.DeletedAt)
|
||||
}
|
||||
|
||||
secrets, err := s.PeeringSecretsRead(nil, tc.input.Peering.ID)
|
||||
require.NoError(t, err)
|
||||
prototest.AssertDeepEqual(t, tc.expectSecrets, secrets)
|
||||
prototest.AssertDeepEqual(t, tc.expect.secrets, secrets)
|
||||
}
|
||||
tcs := []testcase{
|
||||
{
|
||||
name: "create baz",
|
||||
input: &pbpeering.PeeringWriteRequest{
|
||||
Peering: &pbpeering.Peering{
|
||||
ID: testBazPeerID,
|
||||
Name: "baz",
|
||||
Partition: structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty(),
|
||||
ID: testBazPeerID,
|
||||
Name: "baz",
|
||||
State: pbpeering.PeeringState_ESTABLISHING,
|
||||
PeerServerAddresses: []string{"localhost:8502"},
|
||||
Partition: structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty(),
|
||||
},
|
||||
SecretsRequest: &pbpeering.SecretsWriteRequest{
|
||||
PeerID: testBazPeerID,
|
||||
Request: &pbpeering.SecretsWriteRequest_GenerateToken{
|
||||
GenerateToken: &pbpeering.SecretsWriteRequest_GenerateTokenRequest{
|
||||
EstablishmentSecret: testBazSecretID,
|
||||
Request: &pbpeering.SecretsWriteRequest_Establish{
|
||||
Establish: &pbpeering.SecretsWriteRequest_EstablishRequest{
|
||||
ActiveStreamSecret: testBazSecretID,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectSecrets: &pbpeering.PeeringSecrets{
|
||||
PeerID: testBazPeerID,
|
||||
Establishment: &pbpeering.PeeringSecrets_Establishment{
|
||||
SecretID: testBazSecretID,
|
||||
expect: expectations{
|
||||
peering: &pbpeering.Peering{
|
||||
ID: testBazPeerID,
|
||||
Name: "baz",
|
||||
State: pbpeering.PeeringState_ESTABLISHING,
|
||||
},
|
||||
secrets: &pbpeering.PeeringSecrets{
|
||||
PeerID: testBazPeerID,
|
||||
Stream: &pbpeering.PeeringSecrets_Stream{
|
||||
ActiveSecretID: testBazSecretID,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "cannot change ID for baz",
|
||||
input: &pbpeering.PeeringWriteRequest{
|
||||
Peering: &pbpeering.Peering{
|
||||
ID: "123",
|
||||
Name: "baz",
|
||||
State: pbpeering.PeeringState_FAILING,
|
||||
PeerServerAddresses: []string{"localhost:8502"},
|
||||
Partition: structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty(),
|
||||
},
|
||||
},
|
||||
expect: expectations{
|
||||
err: `A peering already exists with the name "baz" and a different ID`,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "cannot change dialer status for baz",
|
||||
input: &pbpeering.PeeringWriteRequest{
|
||||
Peering: &pbpeering.Peering{
|
||||
ID: "123",
|
||||
Name: "baz",
|
||||
State: pbpeering.PeeringState_FAILING,
|
||||
// Excluding the peer server addresses leads to baz not being considered a dialer.
|
||||
// PeerServerAddresses: []string{"localhost:8502"},
|
||||
Partition: structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty(),
|
||||
},
|
||||
},
|
||||
expect: expectations{
|
||||
err: "Cannot switch peering dialing mode from true to false",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "update baz",
|
||||
input: &pbpeering.PeeringWriteRequest{
|
||||
Peering: &pbpeering.Peering{
|
||||
ID: testBazPeerID,
|
||||
Name: "baz",
|
||||
State: pbpeering.PeeringState_FAILING,
|
||||
Partition: structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty(),
|
||||
ID: testBazPeerID,
|
||||
Name: "baz",
|
||||
State: pbpeering.PeeringState_FAILING,
|
||||
PeerServerAddresses: []string{"localhost:8502"},
|
||||
Partition: structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty(),
|
||||
},
|
||||
},
|
||||
expectSecrets: &pbpeering.PeeringSecrets{
|
||||
PeerID: testBazPeerID,
|
||||
Establishment: &pbpeering.PeeringSecrets_Establishment{
|
||||
SecretID: testBazSecretID,
|
||||
expect: expectations{
|
||||
peering: &pbpeering.Peering{
|
||||
ID: testBazPeerID,
|
||||
Name: "baz",
|
||||
State: pbpeering.PeeringState_FAILING,
|
||||
},
|
||||
secrets: &pbpeering.PeeringSecrets{
|
||||
PeerID: testBazPeerID,
|
||||
Stream: &pbpeering.PeeringSecrets_Stream{
|
||||
ActiveSecretID: testBazSecretID,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "if no state was included in request it is inherited from existing",
|
||||
input: &pbpeering.PeeringWriteRequest{
|
||||
Peering: &pbpeering.Peering{
|
||||
ID: testBazPeerID,
|
||||
Name: "baz",
|
||||
// Send undefined state.
|
||||
// State: pbpeering.PeeringState_FAILING,
|
||||
PeerServerAddresses: []string{"localhost:8502"},
|
||||
Partition: structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty(),
|
||||
},
|
||||
},
|
||||
expect: expectations{
|
||||
peering: &pbpeering.Peering{
|
||||
ID: testBazPeerID,
|
||||
Name: "baz",
|
||||
// Previous failing state is picked up.
|
||||
State: pbpeering.PeeringState_FAILING,
|
||||
},
|
||||
secrets: &pbpeering.PeeringSecrets{
|
||||
PeerID: testBazPeerID,
|
||||
Stream: &pbpeering.PeeringSecrets_Stream{
|
||||
ActiveSecretID: testBazSecretID,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "mark baz as terminated",
|
||||
input: &pbpeering.PeeringWriteRequest{
|
||||
Peering: &pbpeering.Peering{
|
||||
ID: testBazPeerID,
|
||||
Name: "baz",
|
||||
State: pbpeering.PeeringState_TERMINATED,
|
||||
PeerServerAddresses: []string{"localhost:8502"},
|
||||
Partition: structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty(),
|
||||
},
|
||||
},
|
||||
expect: expectations{
|
||||
peering: &pbpeering.Peering{
|
||||
ID: testBazPeerID,
|
||||
Name: "baz",
|
||||
State: pbpeering.PeeringState_TERMINATED,
|
||||
},
|
||||
// Secrets for baz should have been deleted
|
||||
secrets: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "cannot modify peering during no-op termination",
|
||||
input: &pbpeering.PeeringWriteRequest{
|
||||
Peering: &pbpeering.Peering{
|
||||
ID: testBazPeerID,
|
||||
Name: "baz",
|
||||
State: pbpeering.PeeringState_TERMINATED,
|
||||
Partition: structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty(),
|
||||
PeerServerAddresses: []string{"localhost:8502"},
|
||||
|
||||
// Attempt to add metadata
|
||||
Meta: map[string]string{"foo": "bar"},
|
||||
},
|
||||
},
|
||||
expect: expectations{
|
||||
peering: &pbpeering.Peering{
|
||||
ID: testBazPeerID,
|
||||
Name: "baz",
|
||||
State: pbpeering.PeeringState_TERMINATED,
|
||||
// Meta should be unchanged.
|
||||
Meta: nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1186,42 +1319,104 @@ func TestStore_PeeringWrite(t *testing.T) {
|
|||
name: "mark baz for deletion",
|
||||
input: &pbpeering.PeeringWriteRequest{
|
||||
Peering: &pbpeering.Peering{
|
||||
ID: testBazPeerID,
|
||||
Name: "baz",
|
||||
State: pbpeering.PeeringState_DELETING,
|
||||
PeerServerAddresses: []string{"localhost:8502"},
|
||||
DeletedAt: structs.TimeToProto(testTime),
|
||||
Partition: structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty(),
|
||||
},
|
||||
},
|
||||
expect: expectations{
|
||||
peering: &pbpeering.Peering{
|
||||
ID: testBazPeerID,
|
||||
Name: "baz",
|
||||
State: pbpeering.PeeringState_DELETING,
|
||||
DeletedAt: structs.TimeToProto(time.Now()),
|
||||
Partition: structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty(),
|
||||
DeletedAt: structs.TimeToProto(testTime),
|
||||
},
|
||||
secrets: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "deleting a deleted peering is a no-op",
|
||||
input: &pbpeering.PeeringWriteRequest{
|
||||
Peering: &pbpeering.Peering{
|
||||
ID: testBazPeerID,
|
||||
Name: "baz",
|
||||
State: pbpeering.PeeringState_DELETING,
|
||||
PeerServerAddresses: []string{"localhost:8502"},
|
||||
DeletedAt: structs.TimeToProto(time.Now()),
|
||||
Partition: structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty(),
|
||||
},
|
||||
},
|
||||
// Secrets for baz should have been deleted
|
||||
expectSecrets: nil,
|
||||
expect: expectations{
|
||||
peering: &pbpeering.Peering{
|
||||
ID: testBazPeerID,
|
||||
Name: "baz",
|
||||
// Still marked as deleting at the original testTime
|
||||
State: pbpeering.PeeringState_DELETING,
|
||||
DeletedAt: structs.TimeToProto(testTime),
|
||||
},
|
||||
// Secrets for baz should have been deleted
|
||||
secrets: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "terminating a peering marked for deletion is a no-op",
|
||||
input: &pbpeering.PeeringWriteRequest{
|
||||
Peering: &pbpeering.Peering{
|
||||
ID: testBazPeerID,
|
||||
Name: "baz",
|
||||
State: pbpeering.PeeringState_TERMINATED,
|
||||
PeerServerAddresses: []string{"localhost:8502"},
|
||||
Partition: structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty(),
|
||||
},
|
||||
},
|
||||
expect: expectations{
|
||||
peering: &pbpeering.Peering{
|
||||
ID: testBazPeerID,
|
||||
Name: "baz",
|
||||
// Still marked as deleting
|
||||
State: pbpeering.PeeringState_DELETING,
|
||||
},
|
||||
// Secrets for baz should have been deleted
|
||||
secrets: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "cannot update peering marked for deletion",
|
||||
input: &pbpeering.PeeringWriteRequest{
|
||||
Peering: &pbpeering.Peering{
|
||||
ID: testBazPeerID,
|
||||
Name: "baz",
|
||||
ID: testBazPeerID,
|
||||
Name: "baz",
|
||||
PeerServerAddresses: []string{"localhost:8502"},
|
||||
Partition: structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty(),
|
||||
|
||||
// Attempt to add metadata
|
||||
Meta: map[string]string{
|
||||
"source": "kubernetes",
|
||||
},
|
||||
Partition: structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty(),
|
||||
},
|
||||
},
|
||||
expectErr: "cannot write to peering that is marked for deletion",
|
||||
expect: expectations{
|
||||
err: "cannot write to peering that is marked for deletion",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "cannot create peering marked for deletion",
|
||||
input: &pbpeering.PeeringWriteRequest{
|
||||
Peering: &pbpeering.Peering{
|
||||
ID: testFooPeerID,
|
||||
Name: "foo",
|
||||
DeletedAt: structs.TimeToProto(time.Now()),
|
||||
Partition: structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty(),
|
||||
ID: testFooPeerID,
|
||||
Name: "foo",
|
||||
PeerServerAddresses: []string{"localhost:8502"},
|
||||
State: pbpeering.PeeringState_DELETING,
|
||||
DeletedAt: structs.TimeToProto(time.Now()),
|
||||
Partition: structs.NodeEnterpriseMetaInDefaultPartition().PartitionOrEmpty(),
|
||||
},
|
||||
},
|
||||
expectErr: "cannot create a new peering marked for deletion",
|
||||
expect: expectations{
|
||||
err: "cannot create a new peering marked for deletion",
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range tcs {
|
||||
|
@ -1246,6 +1441,7 @@ func TestStore_PeeringDelete(t *testing.T) {
|
|||
Peering: &pbpeering.Peering{
|
||||
ID: testFooPeerID,
|
||||
Name: "foo",
|
||||
State: pbpeering.PeeringState_DELETING,
|
||||
DeletedAt: structs.TimeToProto(time.Now()),
|
||||
},
|
||||
}))
|
||||
|
@ -1759,6 +1955,7 @@ func TestStateStore_PeeringsForService(t *testing.T) {
|
|||
copied := pbpeering.Peering{
|
||||
ID: tp.peering.ID,
|
||||
Name: tp.peering.Name,
|
||||
State: pbpeering.PeeringState_DELETING,
|
||||
DeletedAt: structs.TimeToProto(time.Now()),
|
||||
}
|
||||
require.NoError(t, s.PeeringWrite(lastIdx, &pbpeering.PeeringWriteRequest{Peering: &copied}))
|
||||
|
@ -2201,6 +2398,7 @@ func TestStore_TrustBundleListByService(t *testing.T) {
|
|||
Peering: &pbpeering.Peering{
|
||||
ID: peerID1,
|
||||
Name: "peer1",
|
||||
State: pbpeering.PeeringState_DELETING,
|
||||
DeletedAt: structs.TimeToProto(time.Now()),
|
||||
},
|
||||
}))
|
||||
|
|
|
@ -726,11 +726,12 @@ func (s *Server) PeeringDelete(ctx context.Context, req *pbpeering.PeeringDelete
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if !existing.IsActive() {
|
||||
if existing == nil || existing.State == pbpeering.PeeringState_DELETING {
|
||||
// Return early when the Peering doesn't exist or is already marked for deletion.
|
||||
// We don't return nil because the pb will fail to marshal.
|
||||
return &pbpeering.PeeringDeleteResponse{}, nil
|
||||
}
|
||||
|
||||
// We are using a write request due to needing to perform a deferred deletion.
|
||||
// The peering gets marked for deletion by setting the DeletedAt field,
|
||||
// and a leader routine will handle deleting the peering.
|
||||
|
|
|
@ -621,38 +621,50 @@ func TestPeeringService_Read_ACLEnforcement(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestPeeringService_Delete(t *testing.T) {
|
||||
// TODO(peering): see note on newTestServer, refactor to not use this
|
||||
s := newTestServer(t, nil)
|
||||
|
||||
p := &pbpeering.Peering{
|
||||
ID: testUUID(t),
|
||||
Name: "foo",
|
||||
State: pbpeering.PeeringState_ESTABLISHING,
|
||||
PeerCAPems: nil,
|
||||
PeerServerName: "test",
|
||||
PeerServerAddresses: []string{"addr1"},
|
||||
tt := map[string]pbpeering.PeeringState{
|
||||
"active peering": pbpeering.PeeringState_ACTIVE,
|
||||
"terminated peering": pbpeering.PeeringState_TERMINATED,
|
||||
}
|
||||
err := s.Server.FSM().State().PeeringWrite(10, &pbpeering.PeeringWriteRequest{Peering: p})
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, p.DeletedAt)
|
||||
require.True(t, p.IsActive())
|
||||
|
||||
client := pbpeering.NewPeeringServiceClient(s.ClientConn(t))
|
||||
for name, overrideState := range tt {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
// TODO(peering): see note on newTestServer, refactor to not use this
|
||||
s := newTestServer(t, nil)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
t.Cleanup(cancel)
|
||||
// A pointer is kept for the following peering so that we can modify the object without another PeeringWrite.
|
||||
p := &pbpeering.Peering{
|
||||
ID: testUUID(t),
|
||||
Name: "foo",
|
||||
PeerCAPems: nil,
|
||||
PeerServerName: "test",
|
||||
PeerServerAddresses: []string{"addr1"},
|
||||
}
|
||||
err := s.Server.FSM().State().PeeringWrite(10, &pbpeering.PeeringWriteRequest{Peering: p})
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, p.DeletedAt)
|
||||
require.True(t, p.IsActive())
|
||||
|
||||
_, err = client.PeeringDelete(ctx, &pbpeering.PeeringDeleteRequest{Name: "foo"})
|
||||
require.NoError(t, err)
|
||||
// Overwrite the peering state to simulate deleting from a non-initial state.
|
||||
p.State = overrideState
|
||||
|
||||
retry.Run(t, func(r *retry.R) {
|
||||
_, resp, err := s.Server.FSM().State().PeeringRead(nil, state.Query{Value: "foo"})
|
||||
require.NoError(r, err)
|
||||
client := pbpeering.NewPeeringServiceClient(s.ClientConn(t))
|
||||
|
||||
// Initially the peering will be marked for deletion but eventually the leader
|
||||
// routine will clean it up.
|
||||
require.Nil(r, resp)
|
||||
})
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
t.Cleanup(cancel)
|
||||
|
||||
_, err = client.PeeringDelete(ctx, &pbpeering.PeeringDeleteRequest{Name: "foo"})
|
||||
require.NoError(t, err)
|
||||
|
||||
retry.Run(t, func(r *retry.R) {
|
||||
_, resp, err := s.Server.FSM().State().PeeringRead(nil, state.Query{Value: "foo"})
|
||||
require.NoError(r, err)
|
||||
|
||||
// Initially the peering will be marked for deletion but eventually the leader
|
||||
// routine will clean it up.
|
||||
require.Nil(r, resp)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPeeringService_Delete_ACLEnforcement(t *testing.T) {
|
||||
|
|
Loading…
Reference in New Issue