Skip to content

Commit

Permalink
CLOUDP-291668: Add list command for ASP PrivateLink endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
tcannon91 committed Feb 14, 2025
1 parent 77466b8 commit 24a2b7a
Show file tree
Hide file tree
Showing 9 changed files with 325 additions and 2 deletions.
88 changes: 88 additions & 0 deletions docs/command/atlas-streams-privateLinks-list.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
.. _atlas-streams-privateLinks-list:

===============================
atlas streams privateLinks list
===============================

.. default-domain:: mongodb

.. contents:: On this page
:local:
:backlinks: none
:depth: 1
:class: singlecol

Lists the PrivateLink endpoints in the project that can be used as Atlas Stream Processor connections.

To use this command, you must authenticate with a user account or an API key with any of the following roles: Project Owner, Project Stream Processing Owner.

Syntax
------

.. code-block::
:caption: Command Syntax

atlas streams privateLinks list [options]

.. Code end marker, please don't delete this comment

Options
-------

.. list-table::
:header-rows: 1
:widths: 20 10 10 60

* - Name
- Type
- Required
- Description
* - -h, --help
-
- false
- help for list
* - -o, --output
- string
- false
- Output format. Valid values are json, json-path, go-template, or go-template-file. To see the full output, use the -o json option.
* - --projectId
- string
- false
- Hexadecimal string that identifies the project to use. This option overrides the settings in the configuration file or environment variable.

Inherited Options
-----------------

.. list-table::
:header-rows: 1
:widths: 20 10 10 60

* - Name
- Type
- Required
- Description
* - -P, --profile
- string
- false
- Name of the profile to use from your configuration file. To learn about profiles for the Atlas CLI, see https://dochub.mongodb.org/core/atlas-cli-save-connection-settings.

Output
------

If the command succeeds, the CLI returns output similar to the following sample. Values in brackets represent your values.

.. code-block::

ID PROVIDER REGION VENDOR STATE INTERFACE_ENDPOINT_ID SERVICE_ENDPOINT_ID DNS_DOMAIN DNS_SUBDOMAIN
<Id> <Provider> <Region> <Vendor> <State> <InterfaceEndpointId> <ServiceEndpointId> <DnsDomain> <DnsSubDomain>


Examples
--------

.. code-block::
:copyable: false

# list PrivateLink endpoints for Atlas Stream Processing:
atlas streams privateLink list

2 changes: 2 additions & 0 deletions docs/command/atlas-streams-privateLinks.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,12 @@ Related Commands
----------------

* :ref:`atlas-streams-privateLinks-create` - Creates a PrivateLink endpoint that can be used as an Atlas Stream Processor connection.
* :ref:`atlas-streams-privateLinks-list` - Lists the PrivateLink endpoints in the project that can be used as Atlas Stream Processor connections.


.. toctree::
:titlesonly:

create </command/atlas-streams-privateLinks-create>
list </command/atlas-streams-privateLinks-list>

87 changes: 87 additions & 0 deletions internal/cli/streams/privatelink/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright 2025 MongoDB Inc
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package privatelink

import (
"context"
"fmt"

"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli"
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli/require"
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/config"
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/store"
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/usage"
"github.com/spf13/cobra"
)

var listTemplate = `ID PROVIDER REGION VENDOR STATE INTERFACE_ENDPOINT_ID SERVICE_ENDPOINT_ID DNS_DOMAIN DNS_SUBDOMAIN{{range valueOrEmptySlice .Results}}
{{.Id}} {{.Provider}} {{.Region}} {{.Vendor}} {{.State}} {{.InterfaceEndpointId}} {{.ServiceEndpointId}} {{.DnsDomain}} {{.DnsSubDomain}}{{end}}
`

type ListOpts struct {
cli.ProjectOpts
cli.OutputOpts
store store.PrivateLinkLister
}

func (opts *ListOpts) Run() error {
result, err := opts.store.ListPrivateLinkEndpoints(opts.ConfigProjectID())
if err != nil {
return err
}

return opts.Print(result)
}

func (opts *ListOpts) initStore(ctx context.Context) func() error {
return func() error {
var err error
opts.store, err = store.New(store.AuthenticatedPreset(config.Default()), store.WithContext(ctx))
return err
}
}

// atlas streams privateLink list
// List the PrivateLink endpoints in the project that can be used as Atlas Stream Processor connections.
func ListBuilder() *cobra.Command {
opts := &ListOpts{}
cmd := &cobra.Command{
Use: "list",
Short: "Lists the PrivateLink endpoints in the project that can be used as Atlas Stream Processor connections.",
Long: fmt.Sprintf(usage.RequiredOneOfRoles, commandRoles),
Args: require.NoArgs,
Annotations: map[string]string{
"output": listTemplate,
},
Example: `# list PrivateLink endpoints for Atlas Stream Processing:
atlas streams privateLink list
`,
PreRunE: func(cmd *cobra.Command, _ []string) error {
return opts.PreRunE(
opts.ValidateProjectID,
opts.initStore(cmd.Context()),
opts.InitOutput(cmd.OutOrStdout(), createTemplate),
)
},
RunE: func(_ *cobra.Command, _ []string) error {
return opts.Run()
},
}

opts.AddProjectOptsFlags(cmd)
opts.AddOutputOptFlags(cmd)

return cmd
}
72 changes: 72 additions & 0 deletions internal/cli/streams/privatelink/list_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright 2025 MongoDB Inc
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package privatelink

import (
"bytes"
"fmt"
"testing"

"github.com/golang/mock/gomock"
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/cli"
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/mocks"
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/test"
"github.com/stretchr/testify/require"
atlasv2 "go.mongodb.org/atlas-sdk/v20241113004/admin"
)

func getPrivateLinkConnections() []atlasv2.StreamsPrivateLinkConnection {
var connections []atlasv2.StreamsPrivateLinkConnection

for i := 0; i < 5; i++ {
conn := atlasv2.NewStreamsPrivateLinkConnection()
conn.SetId(fmt.Sprintf("testId%d", i))
conn.SetProvider("Azure")
conn.SetRegion("US_EAST_2")
conn.SetServiceEndpointId("/subscriptions/fd01adff-b37e-4693-8497-83ecf183a145/resourceGroups/test-rg/providers/Microsoft.EventHub/namespaces/test-namespace")
conn.SetDnsDomain("test-namespace.servicebus.windows.net")

connections = append(connections, *conn)
}

return connections
}

func TestListOpts_Run(t *testing.T) {
ctrl := gomock.NewController(t)
mockStore := mocks.NewMockPrivateLinkLister(ctrl)

buf := new(bytes.Buffer)
listOpts := &ListOpts{
store: mockStore,
OutputOpts: cli.OutputOpts{
Template: listTemplate,
OutWriter: buf,
},
}

connections := getPrivateLinkConnections()
expected := atlasv2.NewPaginatedApiStreamsPrivateLink()
expected.SetResults(connections)

mockStore.
EXPECT().
ListPrivateLinkEndpoints(gomock.Eq(listOpts.ConfigProjectID())).
Return(expected, nil).
Times(1)

require.NoError(t, listOpts.Run())
test.VerifyOutputTemplate(t, listTemplate, expected)
}
1 change: 1 addition & 0 deletions internal/cli/streams/privatelink/privatelink.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ func Builder() *cobra.Command {

cmd.AddCommand(
CreateBuilder(),
ListBuilder(),
)

return cmd
Expand Down
40 changes: 39 additions & 1 deletion internal/mocks/mock_streams.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 10 additions & 1 deletion internal/store/streams.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
atlasv2 "go.mongodb.org/atlas-sdk/v20241113004/admin"
)

//go:generate mockgen -destination=../mocks/mock_streams.go -package=mocks github.com/mongodb/mongodb-atlas-cli/atlascli/internal/store StreamsLister,StreamsDescriber,StreamsCreator,StreamsDeleter,StreamsUpdater,StreamsDownloader,ConnectionCreator,ConnectionDeleter,ConnectionUpdater,StreamsConnectionDescriber,StreamsConnectionLister,PrivateLinkCreator
//go:generate mockgen -destination=../mocks/mock_streams.go -package=mocks github.com/mongodb/mongodb-atlas-cli/atlascli/internal/store StreamsLister,StreamsDescriber,StreamsCreator,StreamsDeleter,StreamsUpdater,StreamsDownloader,ConnectionCreator,ConnectionDeleter,ConnectionUpdater,StreamsConnectionDescriber,StreamsConnectionLister,PrivateLinkCreator,PrivateLinkLister

type StreamsLister interface {
ProjectStreams(*atlasv2.ListStreamInstancesApiParams) (*atlasv2.PaginatedApiStreamsTenant, error)
Expand Down Expand Up @@ -71,6 +71,10 @@ type PrivateLinkCreator interface {
CreatePrivateLinkEndpoint(projectID string, connection *atlasv2.StreamsPrivateLinkConnection) (*atlasv2.StreamsPrivateLinkConnection, error)
}

type PrivateLinkLister interface {
ListPrivateLinkEndpoints(projectID string) (*atlasv2.PaginatedApiStreamsPrivateLink, error)
}

func (s *Store) ProjectStreams(opts *atlasv2.ListStreamInstancesApiParams) (*atlasv2.PaginatedApiStreamsTenant, error) {
result, _, err := s.clientv2.StreamsApi.ListStreamInstancesWithParams(s.ctx, opts).Execute()
return result, err
Expand Down Expand Up @@ -141,3 +145,8 @@ func (s *Store) CreatePrivateLinkEndpoint(projectID string, connection *atlasv2.
result, _, err := s.clientv2.StreamsApi.CreatePrivateLinkConnection(s.ctx, projectID, connection).Execute()
return result, err
}

func (s *Store) ListPrivateLinkEndpoints(projectID string) (*atlasv2.PaginatedApiStreamsPrivateLink, error) {
result, _, err := s.clientv2.StreamsApi.ListPrivateLinkConnections(s.ctx, projectID).Execute()
return result, err
}
1 change: 1 addition & 0 deletions test/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@
| `streams instance log` | Y | Y |
| `streams privateLink` | | |
| `streams privateLink create` | Y | Y |
| `streams privateLink list` | Y | Y |
| `config` | | |
| `completion` | Y | Y |
| `config delete` | Y | Y |
Expand Down
25 changes: 25 additions & 0 deletions test/e2e/atlas/streams_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,31 @@ func TestStreams(t *testing.T) {
a.Equal("test-namespace.servicebus.windows.net", *privateLinkEndpoint.DnsDomain)
})

t.Run("List all streams privateLink endpoints", func(t *testing.T) {
streamsCmd := exec.Command(cliPath,
"streams",
"privateLinks",
"list",
"-o=json",
"--projectId",
g.projectID,
)

streamsCmd.Env = os.Environ()
streamsResp, err := e2e.RunAndGetStdOut(streamsCmd)
req.NoError(err, string(streamsResp))

var privateLinkEndpoints []atlasv2.StreamsPrivateLinkConnection
req.NoError(json.Unmarshal(streamsResp, &privateLinkEndpoints))

a := assert.New(t)
a.Len(privateLinkEndpoints, 1)
a.Equal("Azure", privateLinkEndpoints[0].GetProvider())
a.Equal("US_EAST_2", privateLinkEndpoints[0].GetRegion())
a.Equal("/subscriptions/fd01adff-b37e-4693-8497-83ecf183a145/resourceGroups/test-rg/providers/Microsoft.EventHub/namespaces/test-namespace", privateLinkEndpoints[0].GetServiceEndpointId())
a.Equal("test-namespace.servicebus.windows.net", privateLinkEndpoints[0].GetDnsDomain())
})

// Connections
t.Run("Creating a streams connection", func(t *testing.T) {
cmd := exec.Command(cliPath,
Expand Down

0 comments on commit 24a2b7a

Please sign in to comment.