Skip to content

Commit

Permalink
Restructure and add commands for endpoints and certificates (#94)
Browse files Browse the repository at this point in the history
This PR achieves the following:

* updates documentation (needs more work)
* complete the rename from configure to auth (we left some artifacts behind)
* adds support for downloading the root CA cert via cluster cert download
* adds support for listing the cluster endpoints via cluster network endpoint list
* moves NAL assign to cluster network allow-list assign/unassign
* moves read-replica from top level to cluster read-replica
* moves regions from cluster describe-regions to region list
* moves instance-types from cluster describe-instances to region instance list
* moves vpc-peering from top-level to vpc peering
  • Loading branch information
cdavid authored Mar 14, 2023
1 parent 7dc4602 commit 4509600
Show file tree
Hide file tree
Showing 23 changed files with 505 additions and 106 deletions.
40 changes: 20 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ This CLI support 3 possibles configurations:
```

* Using a configuration file called `.ybm-cli.yaml` under your `$HOME` directory.
You can use the command `ybm configure` to help to setup the file
You can use the command `ybm auth` to help to setup the file

* Using environment variables (all need to start with `YBM_`)
```sh
Expand Down Expand Up @@ -56,12 +56,12 @@ ybm cluster create

#### List Clusters
```sh
ybm cluster get
ybm cluster list
```

#### Get Cluster
#### Describe Cluster
```sh
ybm cluster get \
ybm cluster describe \
--cluster-name=test-cluster-1
```

Expand All @@ -83,18 +83,18 @@ ybm network-allow-list create \

#### List Network Allow Lists
```sh
ybm network-allow-list get
ybm network-allow-list list
```

#### Get Network Allow List
#### Filter Network Allow List
```sh
ybm network-allow-list get \
ybm network-allow-list list \
--name=admins
```

#### Assign network allow list to cluster
```sh
ybm cluster assign network-allow-list \
ybm cluster network allow-list assign \
--cluster-name=test-cluster \
--network-allow-list=admins
```
Expand All @@ -109,28 +109,28 @@ ybm network-allow-list delete \

#### Create Read Replica
```sh
ybm read-replica create \
ybm cluster read-replica create \
--cluster-name=test-cluster \
--replica=num-cores=<num-cores>,memory-mb=<memory-mb>,disk-size-gb=<disk-size-gb>,code=<GCP or AWS>,region=<region>,num-nodes=<num-nodes>,vpc=<vpc-name>,num-replicas=<num-replicas>,multi-zone=<multi-zone>
```
The `--replica` tag is optional. If omitted, a single read replica will be created for the given cluster with default values. Additional replicas can be created by repeating the `--replica` flag but each replica must be in a distinct region. For now all the replicas need to be specified while updating.

#### List Read Replicas
```sh
ybm read-replica get \
ybm cluster read-replica list \
--cluster-name=test-cluster
```
#### Update Read Replicas
```sh
ybm read-replica update \
ybm cluster read-replica update \
--cluster-name=test-cluster \
--replica=num-cores=<num-cores>,memory-mb=<memory-mb>,disk-size-gb=<disk-size-gb>,code=<GCP or AWS>,region=<region>,num-nodes=<num-nodes>,vpc=<vpc-name>,num-replicas=<num-replicas>,multi-zone=<multi-zone>
```
The `--replica` tag is optional. If omitted, the cluster will be updated with a single read replica with default values. Additional replicas can be created by repeating the `--replica` flag but each replica must be in a distinct region. For now all the replicas need to be specified while updating.

#### Delete Read Replicas
```sh
ybm read-replica delete \
ybm cluster read-replica delete \
--cluster-name=test-cluster

```
Expand All @@ -148,11 +148,11 @@ ybm vpc create \

#### List VPCs
```sh
ybm vpc get
ybm vpc list
```
#### Get VPC
#### Filter VPC
```sh
ybm vpc get \
ybm vpc list \
--name=demo-vpc
```

Expand All @@ -167,7 +167,7 @@ ybm vpc delete \

#### Create VPC Peering
```sh
ybm vpc-peering create \
ybm vpc peering create \
--name=demo-peer \
--vpc-name=demo-vpc \
--cloud=GCP \
Expand All @@ -179,18 +179,18 @@ ybm vpc-peering create \

#### List VPC Peerings
```sh
ybm vpc-peering get
ybm vpc peering list
```

#### Get VPC Peering
#### Filter VPC Peering
```sh
ybm vpc-peering get \
ybm vpc peering list \
--name=demo-peer
```

#### Delete VPC Peering
```sh
ybm vpc-peering delete \
ybm vpc peering delete \
--name=demo-peer
```

Expand Down
3 changes: 1 addition & 2 deletions cmd/configure.go → cmd/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ import (
"golang.org/x/term"
)

// configureCmd represents the configure command
var configureCmd = &cobra.Command{
var authCmd = &cobra.Command{
Use: "auth",
Short: "Authenticate ybm CLI",
Long: "Authenticate the ybm CLI through this command by providing the API Key.",
Expand Down
80 changes: 80 additions & 0 deletions cmd/cluster/cert/cert.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// Licensed to Yugabyte, Inc. under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership. Yugabyte
// licenses this file to you 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 cert

import (
"fmt"
"os"

"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
ybmAuthClient "github.com/yugabyte/ybm-cli/internal/client"
)

var CertCmd = &cobra.Command{
Use: "cert",
Short: "Get the root CA certificate",
Long: "Get the root CA certificate for your YBM clusters",
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
},
}

var downloadCertificate = &cobra.Command{
Use: "download",
Short: "Download the root CA certificate",
Long: `Download the root CA certificate`,
Run: func(cmd *cobra.Command, args []string) {
authApi, err := ybmAuthClient.NewAuthApiClient()
if err != nil {
logrus.Fatalf("Could not initiate api client: %s", err.Error())
}
authApi.GetInfo("", "")
certificate, err := authApi.GetConnectionCertificate()
if err != nil {
logrus.Fatal("Fail to retrieve connection certificate: ", err)
}

if output, _ := cmd.Flags().GetString("out"); output != "" {
// check if the file exists
if _, err := os.Stat(output); err == nil {
// Only overwrite if force is set
if !cmd.Flags().Changed("force") {
logrus.Fatalf("File %s already exists", output)
}
}

f, err := os.Create(output)
if err != nil {
logrus.Fatal("Fail to create output file: ", err)
}
defer f.Close()
_, err = f.WriteString(certificate)
if err != nil {
logrus.Fatal("Fail to write to output file: ", err)
}
} else {
fmt.Println(certificate)
}

},
}

func init() {
CertCmd.AddCommand(downloadCertificate)
downloadCertificate.Flags().StringP("out", "", "", "[OPTIONAL] Output file name (default: stdout)")
downloadCertificate.Flags().BoolP("force", "f", false, "[OPTIONAL] Overwrite the output file if it exists")
}
19 changes: 10 additions & 9 deletions cmd/cluster/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ package cluster

import (
"github.com/spf13/cobra"
"github.com/yugabyte/ybm-cli/cmd/cluster/cert"
"github.com/yugabyte/ybm-cli/cmd/cluster/network"
readreplica "github.com/yugabyte/ybm-cli/cmd/cluster/read-replica"
)

// getCmd represents the list command
Expand All @@ -30,15 +33,13 @@ var ClusterCmd = &cobra.Command{
}

func init() {
ClusterCmd.AddCommand()
ClusterCmd.AddCommand(cert.CertCmd)

// Here you will define your flags and configuration settings.
ClusterCmd.AddCommand(network.NetworkCmd)
network.NetworkCmd.PersistentFlags().StringVarP(&network.ClusterName, "cluster-name", "c", "", "[REQUIRED] The name of the cluster.")
network.NetworkCmd.MarkPersistentFlagRequired("cluster-name")

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// listCmd.PersistentFlags().String("foo", "", "A help for foo")

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// listCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
ClusterCmd.AddCommand(readreplica.ReadReplicaCmd)
readreplica.ReadReplicaCmd.PersistentFlags().StringVarP(&readreplica.ClusterName, "cluster-name", "c", "", "[REQUIRED] The name of the cluster.")
readreplica.ReadReplicaCmd.MarkPersistentFlagRequired("cluster-name")
}
2 changes: 1 addition & 1 deletion cmd/cluster/describe_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (

var describeClusterCmd = &cobra.Command{
Use: "describe",
Short: "Describe a cluster in YugabyteDB Managed",
Short: "Describe a cluster",
Long: "Describe a cluster in YugabyteDB Managed",
Run: func(cmd *cobra.Command, args []string) {
authApi, err := ybmAuthClient.NewAuthApiClient()
Expand Down
2 changes: 1 addition & 1 deletion cmd/cluster/list_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (

var listClusterCmd = &cobra.Command{
Use: "list",
Short: "List clusters in YugabyteDB Managed",
Short: "List clusters",
Long: "List clusters in YugabyteDB Managed",
Run: func(cmd *cobra.Command, args []string) {
authApi, err := ybmAuthClient.NewAuthApiClient()
Expand Down
33 changes: 33 additions & 0 deletions cmd/cluster/network/endpoint/endpoint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Licensed to Yugabyte, Inc. under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership. Yugabyte
// licenses this file to you 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 endpoint

import (
"github.com/spf13/cobra"
)

var EndpointCmd = &cobra.Command{
Use: "endpoint",
Short: "Manage endpoints for a cluster",
Long: "Manage endpoints for a cluster",
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
},
}

func init() {
EndpointCmd.AddCommand()
}
89 changes: 89 additions & 0 deletions cmd/cluster/network/endpoint/list_endpoint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Licensed to Yugabyte, Inc. under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership. Yugabyte
// licenses this file to you 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 endpoint

import (
"os"

"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/yugabyte/ybm-cli/cmd/util"
ybmAuthClient "github.com/yugabyte/ybm-cli/internal/client"
ybmclient "github.com/yugabyte/yugabytedb-managed-go-client-internal"

"github.com/yugabyte/ybm-cli/internal/formatter"
)

var listEndpointCmd = &cobra.Command{
Use: "list",
Short: "List endpoints for a cluster",
Long: "List endpoints for a cluster",
Run: func(cmd *cobra.Command, args []string) {
authApi, err := ybmAuthClient.NewAuthApiClient()
if err != nil {
logrus.Fatalf("Could not initiate api client: %s", err.Error())
}
authApi.GetInfo("", "")

clusterName, _ := cmd.Flags().GetString("cluster-name")
clusterListRequest := authApi.ListClusters()
// if user filters by name, add it to the request
clusterListRequest = clusterListRequest.Name(clusterName)

resp, r, err := clusterListRequest.Execute()
if err != nil {
logrus.Debugf("Full HTTP response: %v", r)
logrus.Fatalf("Error when calling `ClusterApi.ListClusters`: %s", ybmAuthClient.GetApiErrorDetails(err))
}

if len(resp.GetData()) == 0 {
logrus.Fatalf("Cluster not found")
}

clusterEndpoints := resp.GetData()[0].Info.ClusterEndpoints

region, _ := cmd.Flags().GetString("region")
if region != "" {
clusterEndpoints = util.Filter(clusterEndpoints, func(endpoint ybmclient.Endpoint) bool {
return endpoint.GetRegion() == region
})
}

accessibility, _ := cmd.Flags().GetString("accessibility")
if accessibility != "" {
clusterEndpoints = util.Filter(clusterEndpoints, func(endpoint ybmclient.Endpoint) bool {
return string(endpoint.GetAccessibilityType()) == accessibility
})
}

if len(clusterEndpoints) == 0 {
logrus.Fatalf("No endpoints found")
}

endpointsCtx := formatter.Context{
Output: os.Stdout,
Format: formatter.NewEndpointFormat(viper.GetString("output")),
}
formatter.EndpointWrite(endpointsCtx, clusterEndpoints)
},
}

func init() {
EndpointCmd.AddCommand(listEndpointCmd)
listEndpointCmd.Flags().String("accessibility", "", "[OPTIONAL] Accessibility of the endpoint")
listEndpointCmd.Flags().String("region", "", "[OPTIONAL] Region of the endpoint")
}
Loading

0 comments on commit 4509600

Please sign in to comment.