Skip to content

Commit eeba392

Browse files
CLOUDP-57855: List all available measurements for a given process, Atlas (#85)
1 parent 6db5fcd commit eeba392

File tree

12 files changed

+395
-0
lines changed

12 files changed

+395
-0
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ gen-mocks: ## Generate mocks
6565
mockgen -source=internal/store/alerts.go -destination=internal/mocks/mock_alerts.go -package=mocks
6666
mockgen -source=internal/store/global_alerts.go -destination=internal/mocks/mock_global_alerts.go -package=mocks
6767
mockgen -source=internal/store/events.go -destination=internal/mocks/mock_events.go -package=mocks
68+
mockgen -source=internal/store/process_measurements.go -destination=internal/mocks/mock_process_measurements.go -package=mocks
6869

6970
.PHONY: build
7071
build: ## Generate a binary in ./bin

internal/cli/atlas.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ func AtlasBuilder() *cobra.Command {
3030
cmd.AddCommand(AtlasAlertsBuilder())
3131
cmd.AddCommand(AtlasBackupsBuilder())
3232
cmd.AddCommand(AtlasEventsBuilder())
33+
cmd.AddCommand(AtlasMeasurementsBuilder())
3334

3435
return cmd
3536
}

internal/cli/atlas_measurements.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2020 MongoDB Inc
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package cli
16+
17+
import (
18+
"github.com/mongodb/mongocli/internal/description"
19+
"github.com/spf13/cobra"
20+
)
21+
22+
func AtlasMeasurementsBuilder() *cobra.Command {
23+
cmd := &cobra.Command{
24+
Use: "measurements",
25+
Short: description.Measurements,
26+
}
27+
28+
cmd.AddCommand(AtlasMeasurementsProcessBuilder())
29+
30+
return cmd
31+
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// Copyright 2020 MongoDB Inc
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package cli
16+
17+
import (
18+
atlas "github.com/mongodb/go-client-mongodb-atlas/mongodbatlas"
19+
"github.com/mongodb/mongocli/internal/description"
20+
"github.com/mongodb/mongocli/internal/flags"
21+
"github.com/mongodb/mongocli/internal/json"
22+
"github.com/mongodb/mongocli/internal/store"
23+
"github.com/mongodb/mongocli/internal/usage"
24+
"github.com/spf13/cobra"
25+
)
26+
27+
type atlasMeasurementsProcessOpts struct {
28+
*globalOpts
29+
pageNum int
30+
itemsPerPage int
31+
host string
32+
port int
33+
granularity string
34+
period string
35+
start string
36+
end string
37+
measurementType string
38+
store store.ProcessMeasurementLister
39+
}
40+
41+
func (opts *atlasMeasurementsProcessOpts) init() error {
42+
if opts.ProjectID() == "" {
43+
return errMissingProjectID
44+
}
45+
46+
var err error
47+
opts.store, err = store.New()
48+
return err
49+
}
50+
51+
func (opts *atlasMeasurementsProcessOpts) Run() error {
52+
listOpts := opts.newProcessMeasurementListOptions()
53+
result, err := opts.store.ListProcessMeasurements(opts.ProjectID(), opts.host, opts.port, listOpts)
54+
55+
if err != nil {
56+
return err
57+
}
58+
59+
return json.PrettyPrint(result)
60+
}
61+
62+
func (opts *atlasMeasurementsProcessOpts) newProcessMeasurementListOptions() *atlas.ProcessMeasurementListOptions {
63+
return &atlas.ProcessMeasurementListOptions{
64+
ListOptions: &atlas.ListOptions{
65+
PageNum: opts.pageNum,
66+
ItemsPerPage: opts.itemsPerPage,
67+
},
68+
Granularity: opts.granularity,
69+
Period: opts.period,
70+
Start: opts.start,
71+
End: opts.end,
72+
M: opts.measurementType,
73+
}
74+
}
75+
76+
// mongocli atlas measurements process(es) host:port [--granularity granularity] [--period period] [--start start] [--end end] [--type type][--projectId projectId]
77+
func AtlasMeasurementsProcessBuilder() *cobra.Command {
78+
opts := &atlasMeasurementsProcessOpts{
79+
globalOpts: newGlobalOpts(),
80+
}
81+
cmd := &cobra.Command{
82+
Use: "process",
83+
Short: description.ProcessMeasurements,
84+
Aliases: []string{"processes"},
85+
Args: cobra.ExactArgs(1),
86+
PreRunE: func(cmd *cobra.Command, args []string) error {
87+
return opts.init()
88+
},
89+
RunE: func(cmd *cobra.Command, args []string) error {
90+
var err error
91+
opts.host, opts.port, err = GetHostNameAndPort(args[0])
92+
if err != nil {
93+
return err
94+
}
95+
96+
return opts.Run()
97+
},
98+
}
99+
100+
cmd.Flags().StringVar(&opts.granularity, flags.Granularity, "", usage.Granularity)
101+
cmd.Flags().StringVar(&opts.period, flags.Period, "", usage.Period)
102+
cmd.Flags().StringVar(&opts.start, flags.Start, "", usage.Start)
103+
cmd.Flags().StringVar(&opts.end, flags.End, "", usage.End)
104+
cmd.Flags().StringVar(&opts.measurementType, flags.MeasurementType, "", usage.MeasurementType)
105+
106+
cmd.Flags().StringVar(&opts.projectID, flags.ProjectID, "", usage.ProjectID)
107+
108+
return cmd
109+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright 2020 MongoDB Inc
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
package cli
15+
16+
import (
17+
"testing"
18+
19+
"github.com/golang/mock/gomock"
20+
"github.com/mongodb/mongocli/internal/fixtures"
21+
"github.com/mongodb/mongocli/internal/mocks"
22+
)
23+
24+
func TestAtlasMeasurementsProcess_Run(t *testing.T) {
25+
ctrl := gomock.NewController(t)
26+
mockStore := mocks.NewMockProcessMeasurementLister(ctrl)
27+
28+
defer ctrl.Finish()
29+
30+
expected := fixtures.ProcessMeasurements()
31+
32+
listOpts := &atlasMeasurementsProcessOpts{
33+
globalOpts: newGlobalOpts(),
34+
host: "hard-00-00.mongodb.net",
35+
port: 27017,
36+
granularity: "PT1M",
37+
period: "PT1M",
38+
store: mockStore,
39+
}
40+
41+
hostName, port, err := GetHostNameAndPort("hard-00-00.mongodb.net:27017")
42+
if err != nil {
43+
t.Fatalf("Run() unexpected error: %v", err)
44+
}
45+
46+
opts := listOpts.newProcessMeasurementListOptions()
47+
mockStore.
48+
EXPECT().ListProcessMeasurements(listOpts.projectID, hostName, port, opts).
49+
Return(expected, nil).
50+
Times(1)
51+
52+
err = listOpts.Run()
53+
if err != nil {
54+
t.Fatalf("Run() unexpected error: %v", err)
55+
}
56+
}

internal/cli/cli.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package cli
1717
import (
1818
"errors"
1919
"fmt"
20+
"strconv"
2021
"strings"
2122

2223
"github.com/AlecAivazis/survey/v2"
@@ -251,3 +252,18 @@ func (opts *atlasAlertsConfigOpts) newMatcher() *atlas.Matcher {
251252
Value: strings.ToUpper(opts.matcherValue),
252253
}
253254
}
255+
256+
// GetHostNameAndPort return the hostname and the port starting from the string hostname:port
257+
func GetHostNameAndPort(hostInfo string) (string, int, error) {
258+
host := strings.SplitN(hostInfo, ":", -1)
259+
if len(host) != 2 {
260+
return "", 0, fmt.Errorf("expected hostname:port, got %s", host)
261+
}
262+
263+
port, err := strconv.Atoi(host[1])
264+
if err != nil {
265+
return "", 0, fmt.Errorf("invalid port number, got %s", host[1])
266+
}
267+
268+
return host[0], port, nil
269+
}

internal/description/description.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ A user’s roles apply to all the clusters in the project.`
5353
ListDBUsers = "List Atlas database users for a project."
5454
ListEvents = "List events for an organization or project"
5555
UpdateDBUser = "Update a MongoDB dbuser in Atlas."
56+
ProcessMeasurements = "Get measurements for a given host."
5657
Whitelist = "Manage the IP whitelist for a project."
5758
CreateWhitelist = "Create an IP whitelist for a project."
5859
DeleteWhitelist = "Delete a database user for a project."
@@ -87,4 +88,5 @@ A user’s roles apply to all the clusters in the project.`
8788
Security = "Manage clusters security configuration."
8889
EnableSecurity = "Enable authentication mechanisms for the project."
8990
Events = "Manage events for your project."
91+
Measurements = "Get measurements on the state of the MongoDB process."
9092
)

internal/fixtures/measurements.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package fixtures
2+
3+
import atlas "github.com/mongodb/go-client-mongodb-atlas/mongodbatlas"
4+
5+
func ProcessMeasurements() *atlas.ProcessMeasurements {
6+
return &atlas.ProcessMeasurements{
7+
End: "2017-08-22T20:31:14Z",
8+
Granularity: "PT1M",
9+
GroupID: "12345678",
10+
HostID: "shard-00-00.mongodb.net:27017",
11+
Links: []*atlas.Link{
12+
{
13+
Rel: "self",
14+
Href: "https://cloud.mongodb.com/api/atlas/v1.0/groups/12345678/processes/shard-00-00.mongodb.net:27017/measurements?granularity=PT1M&period=PT1M",
15+
},
16+
{
17+
Href: "https://cloud.mongodb.com/api/atlas/v1.0/groups/12345678/processes/shard-00-00.mongodb.net:27017",
18+
Rel: "http://mms.mongodb.com/host",
19+
},
20+
},
21+
Measurements: []*atlas.Measurements{
22+
{
23+
DataPoints: []*atlas.DataPoints{
24+
{
25+
Timestamp: "2017-08-22T20:31:12Z",
26+
Value: nil,
27+
},
28+
{
29+
Timestamp: "2017-08-22T20:31:14Z",
30+
Value: nil,
31+
},
32+
},
33+
Name: "ASSERT_REGULAR",
34+
Units: "SCALAR_PER_SECOND",
35+
},
36+
},
37+
ProcessID: "shard-00-00.mongodb.net:27017",
38+
Start: "2017-08-22T20:30:45Z",
39+
}
40+
}

internal/flags/flags.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,13 @@ const (
3333
Username = "username" // Username flag
3434
UsernameShort = "u" // UsernameShort flag
3535
Password = "password" // Password flag
36+
Period = "period" // Period flag
3637
PasswordShort = "p" // PasswordShort flag
3738
Email = "email" // Email flag
3839
Status = "status" // Status flag
40+
Start = "start" // Start flag
41+
End = "end" // End flag
42+
MeasurementType = "type" // MeasurementType flag
3943
FirstName = "firstName" // FirstName flag
4044
LastName = "lastName" // LastName flag
4145
Role = "role" // Role flag
@@ -91,4 +95,5 @@ const (
9195
ExpirationHours = "expirationHours" // ExpirationHours flag
9296
MaxDate = "maxDate" // MaxDate flag
9397
MinDate = "minDate" // MinDate flag
98+
Granularity = "granularity" // Granularity flag
9499
)

0 commit comments

Comments
 (0)