Skip to content

Commit

Permalink
Private Service Endpoint (#106)
Browse files Browse the repository at this point in the history
* wip

* Private Service Endpoint

* PR comments

* fix go vet
  • Loading branch information
cdavid authored Mar 22, 2023
1 parent e51d0e9 commit 3793a9a
Show file tree
Hide file tree
Showing 9 changed files with 623 additions and 19 deletions.
107 changes: 107 additions & 0 deletions cmd/cluster/network/endpoint/create_endpoint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// 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 (
"encoding/json"
"fmt"
"strings"

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

var createEndpointCmd = &cobra.Command{
Use: "create",
Short: "Create a new endpoint",
Long: `Create a new endpoint`,
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("", "")

clusterData := getCluster(cmd, authApi)
accessibilityType, _ := cmd.Flags().GetString("accessibility-type")
reg, _ := cmd.Flags().GetString("region")

switch accessibilityType {
case string(ybmclient.ACCESSIBILITYTYPE_PRIVATE_SERVICE_ENDPOINT):
logrus.Debugln("Endpoint is a private service endpoint")
if cmd.Flags().Changed("security-principals") {
logrus.Debugln("Security principals are set, attempting to create")
} else {
logrus.Fatalln("Security principals are not set and are mandatory for Private Service Endpoints.")
}
securityPrincipalsString, _ := cmd.Flags().GetString("security-principals")
securityPrincipalsList := strings.Split(securityPrincipalsString, ",")

allClusterRegions := clusterData.Info.ClusterRegionInfoDetails
desiredRegions := util.Filter(allClusterRegions, func(regionInfo ybmclient.ClusterRegionInfoDetails) bool {
return regionInfo.Region == reg
})

if len(desiredRegions) == 0 {
logrus.Fatalf("No region found for cluster %s with name %s\n", clusterData.Spec.Name, reg)
}
if len(desiredRegions) > 1 {
logrus.Fatalf("Multiple regions found for cluster %s with name %s\n", clusterData.Spec.Name, reg)
}

regionArnMap := make(map[string][]string)
regionArnMap[desiredRegions[0].Id] = securityPrincipalsList
createPseSpec := authApi.CreatePrivateServiceEndpointSpec(regionArnMap)

jsonSpec, _ := json.Marshal(createPseSpec[0])
logrus.Debugf("Private service endpoint spec: %s", jsonSpec)

createResp, r, err := authApi.CreatePrivateServiceEndpoint(clusterData.Info.Id).PrivateServiceEndpointSpec(createPseSpec[0]).Execute()
if err != nil {
logrus.Debugf("Full HTTP response: %v", r)
logrus.Fatalf("Could not create private service endpoint: %s", err.Error())
}

psEps := util.Filter(createResp.GetData(), func(ep ybmclient.PrivateServiceEndpointRegionData) bool {
return ep.GetSpec().ClusterRegionInfoId == desiredRegions[0].Id
})

if len(psEps) == 0 {
logrus.Fatalf("No private service endpoint found for cluster %s with region %s\n", clusterData.Spec.Name, reg)
}

msg := fmt.Sprintf("Created private service endpoint in region %v\n", reg)
fmt.Println(msg)

default:
logrus.Fatalf("Endpoint is not a private service endpoint. Only private service endpoints are currently supported.\n")

}

},
}

func init() {
EndpointCmd.AddCommand(createEndpointCmd)
createEndpointCmd.Flags().String("accessibility-type", "", "[REQUIRED] The accessibility of the endpoint.")
createEndpointCmd.MarkFlagRequired("accessibility-type")
createEndpointCmd.Flags().String("region", "", "[REQUIRED] The region of the endpoint.")
createEndpointCmd.MarkFlagRequired("region")
createEndpointCmd.Flags().String("security-principals", "", "[OPTIONAL] The security principals of the endpoint.")
}
65 changes: 65 additions & 0 deletions cmd/cluster/network/endpoint/delete_endpoint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// 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 (
"fmt"

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

var deleteEndpointCmd = &cobra.Command{
Use: "delete",
Short: "Delete a private service endpoint",
Long: `Delete a private service endpoint.`,
Run: func(cmd *cobra.Command, args []string) {
authApi, err := ybmAuthClient.NewAuthApiClient()
if err != nil {
logrus.Fatalf("Could not initiate api client: %s\n", err.Error())
}
authApi.GetInfo("", "")

clusterEndpoints, clusterId, endpointId := getEndpointById(cmd, authApi)

// We currently support fetching just Private Service Endpoints
switch clusterEndpoints[0].GetAccessibilityType() {

case ybmclient.ACCESSIBILITYTYPE_PRIVATE_SERVICE_ENDPOINT:
logrus.Debugln("Endpoint is a private service endpoint, attempting to delete")
r, err := authApi.DeletePrivateServiceEndpoint(clusterId, endpointId).Execute()
if err != nil {
logrus.Debugf("Full HTTP response: %v", r)
logrus.Fatalf("Error when calling `ClusterApi.DeletePrivateServiceEndpoint`: %s\n", ybmAuthClient.GetApiErrorDetails(err))
}

msg := fmt.Sprintf("Deleted endpoint %s", endpointId)
fmt.Println(msg)

default:
logrus.Fatalf("Endpoint is not a private service endpoint. Only private service endpoints are currently supported.\n")
}

},
}

func init() {
EndpointCmd.AddCommand(deleteEndpointCmd)
deleteEndpointCmd.Flags().String("endpoint-id", "", "[REQUIRED] THe ID of the endpoint")
deleteEndpointCmd.MarkFlagRequired("endpoint-id")
}
77 changes: 77 additions & 0 deletions cmd/cluster/network/endpoint/describe_endpoint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// 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"
ybmAuthClient "github.com/yugabyte/ybm-cli/internal/client"
"github.com/yugabyte/ybm-cli/internal/formatter"
ybmclient "github.com/yugabyte/yugabytedb-managed-go-client-internal"
)

var describeEndpointCmd = &cobra.Command{
Use: "describe",
Short: "Describe a network endpoint for a cluster",
Long: `Describe a network endpoint 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\n", err.Error())
}
authApi.GetInfo("", "")

clusterEndpoints, clusterId, endpointId := getEndpointById(cmd, authApi)

// We currently support fetching just Private Service Endpoints
switch clusterEndpoints[0].GetAccessibilityType() {

case ybmclient.ACCESSIBILITYTYPE_PRIVATE_SERVICE_ENDPOINT:
logrus.Debugln("Endpoint is a private service endpoint, getting more data")
pseGetResponse, r, err := authApi.GetPrivateServiceEndpoint(clusterId, endpointId).Execute()
if err != nil {
logrus.Debugf("Full HTTP response: %v", r)
logrus.Fatalf("Error when calling `ClusterApi.GetPrivateServiceEndpoint`: %s\n", ybmAuthClient.GetApiErrorDetails(err))
}
if viper.GetString("output") == "table" {
psEndpointContext := *formatter.NewPSEndpointContext()
psEndpointContext.Output = os.Stdout
psEndpointContext.Format = formatter.NewPSEndpointFormat(viper.GetString("output"))
psEndpointContext.SetFullPSEndpoint(*authApi, pseGetResponse.GetData(), clusterEndpoints[0])
psEndpointContext.Write()
return
}

psEndpointContext := formatter.Context{
Output: os.Stdout,
Format: formatter.NewPSEndpointFormat(viper.GetString("output")),
}
formatter.PSEndpointWrite(psEndpointContext, pseGetResponse.GetData(), clusterEndpoints[0])

default:
logrus.Fatalf("Endpoint is not a private service endpoint. Only private service endpoints are currently supported.\n")
}
},
}

func init() {
EndpointCmd.AddCommand(describeEndpointCmd)
describeEndpointCmd.Flags().String("endpoint-id", "", "[REQUIRED] The ID of the endpoint")
describeEndpointCmd.MarkFlagRequired("endpoint-id")
}
21 changes: 3 additions & 18 deletions cmd/cluster/network/endpoint/list_endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,26 +35,11 @@ var listEndpointCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
authApi, err := ybmAuthClient.NewAuthApiClient()
if err != nil {
logrus.Fatalf("Could not initiate api client: %s", err.Error())
logrus.Fatalf("Could not initiate api client: %s\n", 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
clusterEndpoints, _ := getEndpoints(cmd, authApi)

region, _ := cmd.Flags().GetString("region")
if region != "" {
Expand All @@ -71,7 +56,7 @@ var listEndpointCmd = &cobra.Command{
}

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

endpointsCtx := formatter.Context{
Expand Down
86 changes: 86 additions & 0 deletions cmd/cluster/network/endpoint/update_endpoint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// 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 (
"fmt"
"strings"

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

var updateEndpointCmd = &cobra.Command{
Use: "update",
Short: "Update a network endpoint for a cluster",
Long: `Update a network endpoint 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\n", err.Error())
}
authApi.GetInfo("", "")

clusterEndpoints, clusterId, endpointId := getEndpointById(cmd, authApi)

// We currently support fetching just Private Service Endpoints
switch clusterEndpoints[0].GetAccessibilityType() {

case ybmclient.ACCESSIBILITYTYPE_PRIVATE_SERVICE_ENDPOINT:
if !cmd.Flags().Changed("security-principals") {
logrus.Fatalf("security-principals is required for private service endpoints\n")
}

pseGetResponse, r, err := authApi.GetPrivateServiceEndpoint(clusterId, endpointId).Execute()
if err != nil {
logrus.Debugf("Full HTTP response: %v", r)
logrus.Fatalf("Error when calling `ClusterApi.GetPrivateServiceEndpoint`: %s\n", ybmAuthClient.GetApiErrorDetails(err))
}

securityPrincipalsString, _ := cmd.Flags().GetString("security-principals")
securityPrincipalsList := strings.Split(securityPrincipalsString, ",")

regionArnMap := make(map[string][]string)
regionArnMap[pseGetResponse.Data.Spec.ClusterRegionInfoId] = securityPrincipalsList

// we create a spec that has a single element
pseSpec := authApi.CreatePrivateServiceEndpointRegionSpec(regionArnMap)

// we pass the only element in the spec to the update endpoint call
updateResp, r, err := authApi.EditPrivateServiceEndpoint(clusterId, endpointId).PrivateServiceEndpointRegionSpec(pseSpec[0]).Execute()
if err != nil {
logrus.Debugf("Full HTTP response: %v", r)
logrus.Fatalf("Error when calling `ClusterApi.EditPrivateServiceEndpoint`: %s\n", ybmAuthClient.GetApiErrorDetails(err))
}

msg := fmt.Sprintf("Updated endpoint %s", updateResp.Data.Info.Id)
fmt.Println(msg)

default:
logrus.Fatalf("Endpoint is not a private service endpoint. Only private service endpoints are currently supported.\n")
}

},
}

func init() {
EndpointCmd.AddCommand(updateEndpointCmd)
updateEndpointCmd.Flags().String("endpoint-id", "", "[REQUIRED] The ID of the endpoint")
updateEndpointCmd.MarkFlagRequired("endpoint-id")
updateEndpointCmd.Flags().String("security-principals", "", "[OPTIONAL] The list of security principals that have access to this endpoint (comma separated). Required for private service endpoints")
}
Loading

0 comments on commit 3793a9a

Please sign in to comment.