Skip to content

Commit

Permalink
CLOUDP-216631 download streams logs (#2770)
Browse files Browse the repository at this point in the history
  • Loading branch information
jarjee committed Mar 22, 2024
1 parent 568c075 commit 6a8e6e0
Show file tree
Hide file tree
Showing 10 changed files with 407 additions and 4 deletions.
113 changes: 113 additions & 0 deletions docs/command/atlas-streams-instances-download.txt
@@ -0,0 +1,113 @@
.. _atlas-streams-instances-download:

================================
atlas streams instances download
================================

.. default-domain:: mongodb

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

Download a compressed file that contains the logs for the specified Atlas Stream Processing instance.

This command downloads a file with a .gz extension. To use this command, you must authenticate with a user account or an API key with the Project Data Access Read/Write role.

Syntax
------

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

atlas streams instances download <tenantName> [options]

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

Arguments
---------

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

* - Name
- Type
- Required
- Description
* - tenantName
- string
- true
- Label that identifies the tenant that stores the log files that you want to download.

Options
-------

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

* - Name
- Type
- Required
- Description
* - --end
- int
- false
- UNIX Epoch-formatted ending date and time for the range of log messages to retrieve. This value defaults to the current timestamp.
* - --force
-
- false
- Flag that indicates whether to overwrite the destination file.
* - -h, --help
-
- false
- help for download
* - --out
- string
- true
- Output file name. This value defaults to the log name.
* - --projectId
- string
- false
- Hexadecimal string that identifies the project to use. This option overrides the settings in the configuration file or environment variable.
* - --start
- int
- false
- UNIX Epoch-formatted starting date and time for the range of log messages to retrieve. This value defaults to 24 hours prior to the current timestamp.

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::

Download of <Name> completed.


Examples
--------

.. code-block::

# Download the audit log file from the instance myProcessor for the project with the ID 5e2211c17a3e5a48f5497de3:
atlas streams instance download myProcessor --projectId 5e2211c17a3e5a48f5497de3
2 changes: 2 additions & 0 deletions docs/command/atlas-streams-instances.txt
Expand Up @@ -54,6 +54,7 @@ Related Commands
* :ref:`atlas-streams-instances-create` - Create an Atlas Stream Processing instance for your project
* :ref:`atlas-streams-instances-delete` - Delete an Atlas Stream Processing instance.
* :ref:`atlas-streams-instances-describe` - Describe an Atlas Stream Processing instance for your project.
* :ref:`atlas-streams-instances-download` - Download a compressed file that contains the logs for the specified Atlas Stream Processing instance.
* :ref:`atlas-streams-instances-list` - List all the Atlas Stream Processing instances for your project.
* :ref:`atlas-streams-instances-update` - Updates an Atlas Stream Processing instance for your project.

Expand All @@ -64,6 +65,7 @@ Related Commands
create </command/atlas-streams-instances-create>
delete </command/atlas-streams-instances-delete>
describe </command/atlas-streams-instances-describe>
download </command/atlas-streams-instances-download>
list </command/atlas-streams-instances-list>
update </command/atlas-streams-instances-update>

122 changes: 122 additions & 0 deletions internal/cli/atlas/streams/instance/download.go
@@ -0,0 +1,122 @@
// Copyright 2024 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 instance

import (
"context"
"fmt"
"io"

"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/flag"
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/store"
"github.com/mongodb/mongodb-atlas-cli/atlascli/internal/usage"
"github.com/spf13/afero"
"github.com/spf13/cobra"
atlasv2 "go.mongodb.org/atlas-sdk/v20231115008/admin"
)

var downloadMessage = "Download of %s completed.\n"

type DownloadOpts struct {
cli.GlobalOpts
cli.DownloaderOpts
tenantName string
start int64
end int64
store store.StreamsDownloader
}

func (opts *DownloadOpts) 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
}
}

func (opts *DownloadOpts) Run() error {
params := atlasv2.DownloadStreamTenantAuditLogsApiParams{
GroupId: opts.ConfigProjectID(),
TenantName: opts.tenantName,
}

if opts.start != 0 {
params.StartDate = &opts.start
}

if opts.end != 0 {
params.EndDate = &opts.end
}

f, err := opts.store.DownloadAuditLog(&params)
if err != nil {
return err
}

defer f.Close()

out, err := opts.NewWriteCloser()
if err != nil {
return err
}
defer out.Close()

_, err = io.Copy(out, f)
return err
}

// DownloadBuilder
// atlas streams download [tenantName] --projectId [projectID].
func DownloadBuilder() *cobra.Command {
const argsN = 1
opts := &DownloadOpts{}
opts.Fs = afero.NewOsFs()
cmd := &cobra.Command{
Use: "download <tenantName>",
Short: "Download a compressed file that contains the logs for the specified Atlas Stream Processing instance.",
Long: `This command downloads a file with a .gz extension. ` + fmt.Sprintf(usage.RequiredRole, "Project Data Access Read/Write"),
Args: cobra.MatchAll(
require.ExactArgs(argsN),
),
Example: ` # Download the audit log file from the instance myProcessor for the project with the ID 5e2211c17a3e5a48f5497de3:
atlas streams instance download myProcessor --projectId 5e2211c17a3e5a48f5497de3`,
Annotations: map[string]string{
"tenantNameDesc": "Label that identifies the tenant that stores the log files that you want to download.",
"output": downloadMessage,
},
PreRunE: func(cmd *cobra.Command, args []string) error {
opts.tenantName = args[0]
return opts.PreRunE(opts.ValidateProjectID, opts.initStore(cmd.Context()))
},
RunE: func(_ *cobra.Command, _ []string) error {
return opts.Run()
},
}

cmd.Flags().StringVar(&opts.Out, flag.Out, "", usage.LogOut)
cmd.Flags().Int64Var(&opts.start, flag.Start, 0, usage.LogStart)
cmd.Flags().Int64Var(&opts.end, flag.End, 0, usage.LogEnd)
cmd.Flags().BoolVar(&opts.Force, flag.Force, false, usage.ForceFile)

cmd.Flags().StringVar(&opts.ProjectID, flag.ProjectID, "", usage.ProjectID)

_ = cmd.MarkFlagRequired(flag.Out)
_ = cmd.MarkFlagFilename(flag.Out)

return cmd
}
84 changes: 84 additions & 0 deletions internal/cli/atlas/streams/instance/download_test.go
@@ -0,0 +1,84 @@
// Copyright 2024 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 instance

import (
"io"
"strings"
"testing"

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

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

const contents = "expected"
const projectID = "download-project-id"
const tenantName = "streams-tenant"

fs := afero.NewMemMapFs()

downloadOpts := &DownloadOpts{
store: mockStore,
DownloaderOpts: cli.DownloaderOpts{
Out: "auditLogs.gz",
Fs: fs,
},
}

downloadOpts.ProjectID = projectID
downloadOpts.tenantName = tenantName

downloadParams := new(atlasv2.DownloadStreamTenantAuditLogsApiParams)
downloadParams.EndDate = nil
downloadParams.StartDate = nil
downloadParams.GroupId = projectID
downloadParams.TenantName = tenantName

expected := io.NopCloser(strings.NewReader(contents))

mockStore.
EXPECT().
DownloadAuditLog(downloadParams).
Return(expected, nil).
Times(1)

if err := downloadOpts.Run(); err != nil {
t.Fatalf("Run() unexpected error: %v", err)
}

of, _ := fs.Open("auditLogs.gz")
defer of.Close()
b, _ := io.ReadAll(of)
require.Equal(t, contents, string(b))
}

func TestDownloadBuilder(t *testing.T) {
test.CmdValidator(
t,
DownloadBuilder(),
0,
[]string{flag.Out, flag.Start, flag.End, flag.Force, flag.ProjectID},
)
}
2 changes: 1 addition & 1 deletion internal/cli/atlas/streams/instance/instance.go
Expand Up @@ -27,7 +27,7 @@ func Builder() *cobra.Command {
Short: "Manage Atlas Stream Processing instances.",
Long: `Create, list, update and delete your Atlas Stream Processing instances.`,
}
cmd.AddCommand(CreateBuilder(), UpdateBuilder(), ListBuilder(), DeleteBuilder(), DescribeBuilder())
cmd.AddCommand(CreateBuilder(), UpdateBuilder(), ListBuilder(), DeleteBuilder(), DescribeBuilder(), DownloadBuilder())

return cmd
}
2 changes: 1 addition & 1 deletion internal/cli/atlas/streams/instance/instance_test.go
Expand Up @@ -24,7 +24,7 @@ func TestBuilder(t *testing.T) {
test.CmdValidator(
t,
Builder(),
5,
6,
[]string{},
)
}

0 comments on commit 6a8e6e0

Please sign in to comment.