diff --git a/internal/provider/cisco/nxos/crypto/trustpoint.go b/internal/provider/cisco/nxos/crypto/trustpoint.go index 2e83b8e2..8d813a80 100644 --- a/internal/provider/cisco/nxos/crypto/trustpoint.go +++ b/internal/provider/cisco/nxos/crypto/trustpoint.go @@ -4,6 +4,10 @@ package crypto import ( + "context" + "errors" + "fmt" + "github.com/openconfig/ygot/ygot" nxos "github.com/ironcore-dev/network-operator/internal/provider/cisco/nxos/genyang" @@ -16,7 +20,18 @@ type Trustpoint struct { ID string } -func (t *Trustpoint) ToYGOT(_ gnmiext.Client) ([]gnmiext.Update, error) { +var ErrAlreadyExists = errors.New("crypto: trustpoint already exists") + +func (t *Trustpoint) ToYGOT(client gnmiext.Client) ([]gnmiext.Update, error) { + ctx := context.Background() + exists, err := client.Exists(ctx, "System/userext-items/pkiext-items/tp-items/TP-list[name="+t.ID+"]") + if err != nil { + return nil, fmt.Errorf("trustpoint: failed to get trustpoint %q: %w", t.ID, err) + } + if exists { + // Trying to replace an existing trustpoint configuration will fail with "disassociating rsa key-pair not allowed when identity certificate exists" + return nil, ErrAlreadyExists + } v := &nxos.Cisco_NX_OSDevice_System_UserextItems_PkiextItems_TpItems_TPList{} v.PopulateDefaults() v.Name = ygot.String(t.ID) @@ -33,5 +48,8 @@ func (t *Trustpoint) Reset(_ gnmiext.Client) ([]gnmiext.Update, error) { gnmiext.DeletingUpdate{ XPath: "System/userext-items/pkiext-items/tp-items/TP-list[name=" + t.ID + "]", }, + gnmiext.DeletingUpdate{ + XPath: "System/userext-items/pkiext-items/keyring-items/KeyRing-list[name=" + t.ID + "]", + }, }, nil } diff --git a/internal/provider/cisco/nxos/crypto/trustpoint_test.go b/internal/provider/cisco/nxos/crypto/trustpoint_test.go index 6a08d034..9e9bbefb 100644 --- a/internal/provider/cisco/nxos/crypto/trustpoint_test.go +++ b/internal/provider/cisco/nxos/crypto/trustpoint_test.go @@ -4,6 +4,7 @@ package crypto import ( + "context" "reflect" "testing" @@ -16,7 +17,18 @@ import ( func Test_Trustpoint(t *testing.T) { tp := &Trustpoint{ID: "mytrustpoint"} - got, err := tp.ToYGOT(&gnmiext.ClientMock{}) + // Mock the client to return false for Exists (trustpoint doesn't exist) + mockClient := &gnmiext.ClientMock{ + ExistsFunc: func(ctx context.Context, xpath string) (bool, error) { + expectedXPath := "System/userext-items/pkiext-items/tp-items/TP-list[name=mytrustpoint]" + if xpath != expectedXPath { + t.Errorf("Exists called with unexpected xpath: got=%s, want=%s", xpath, expectedXPath) + } + return false, nil + }, + } + + got, err := tp.ToYGOT(mockClient) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -36,16 +48,47 @@ func Test_Trustpoint(t *testing.T) { ti, ok := update.Value.(*nxos.Cisco_NX_OSDevice_System_UserextItems_PkiextItems_TpItems_TPList) if !ok { - t.Errorf("expected value to be of type *nxos.Cisco_NX_OSDevice_System_UserextItems_PkiextItems_TpItems") + t.Errorf("expected value to be of type *nxos.Cisco_NX_OSDevice_System_UserextItems_PkiextItems_TpItems_TPList") } - want := &nxos.Cisco_NX_OSDevice_System_UserextItems_PkiextItems_TpItems_TPList{ - Name: ygot.String("mytrustpoint"), - KeyType: nxos.Cisco_NX_OSDevice_Pki_KeyType_Type_RSA, - RevokeCheckConf: nxos.Cisco_NX_OSDevice_Pki_CertRevokeCheck_crl, - EnrollmentType: nxos.Cisco_NX_OSDevice_Pki_CertEnrollType_none, - } + // Create expected struct with PopulateDefaults to match the implementation + want := &nxos.Cisco_NX_OSDevice_System_UserextItems_PkiextItems_TpItems_TPList{} + want.PopulateDefaults() + want.Name = ygot.String("mytrustpoint") + if !reflect.DeepEqual(ti, want) { t.Errorf("unexpected value for 'System/userext-items/pkiext-items/tp-items/TP-list[name=mytrustpoint]': got=%+v, want=%+v", ti, want) } + + // Verify that Exists was called exactly once + existsCalls := mockClient.ExistsCalls() + if len(existsCalls) != 1 { + t.Errorf("expected Exists to be called once, got %d calls", len(existsCalls)) + } +} + +func Test_Trustpoint_AlreadyExists(t *testing.T) { + tp := &Trustpoint{ID: "mytrustpoint"} + + // Mock the client to return true for Exists (trustpoint already exists) + mockClient := &gnmiext.ClientMock{ + ExistsFunc: func(ctx context.Context, xpath string) (bool, error) { + expectedXPath := "System/userext-items/pkiext-items/tp-items/TP-list[name=mytrustpoint]" + if xpath != expectedXPath { + t.Errorf("Exists called with unexpected xpath: got=%s, want=%s", xpath, expectedXPath) + } + return true, nil + }, + } + + _, err := tp.ToYGOT(mockClient) + if err != ErrAlreadyExists { + t.Errorf("expected ErrAlreadyExists, got %v", err) + } + + // Verify that Exists was called exactly once + existsCalls := mockClient.ExistsCalls() + if len(existsCalls) != 1 { + t.Errorf("expected Exists to be called once, got %d calls", len(existsCalls)) + } }