Skip to content
This repository has been archived by the owner on Jul 11, 2023. It is now read-only.

Commit

Permalink
chore(cli): Refactor envoy helpers to cli pkg (#3881)
Browse files Browse the repository at this point in the history
Signed-off-by: Johnson Shi <[email protected]>
  • Loading branch information
johnsonshi authored Jul 30, 2021
1 parent 14eae58 commit 9be2511
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 131 deletions.
65 changes: 12 additions & 53 deletions cmd/cli/proxy_get.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package main

import (
"context"
"fmt"
"bufio"
"io"
"net/http"
"os"

"github.com/pkg/errors"
Expand All @@ -15,8 +13,8 @@ import (
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"

"github.com/openservicemesh/osm/pkg/cli"
"github.com/openservicemesh/osm/pkg/constants"
"github.com/openservicemesh/osm/pkg/k8s"
)

const getCmdDescription = `
Expand Down Expand Up @@ -86,58 +84,24 @@ func newProxyGetCmd(config *action.Configuration, out io.Writer) *cobra.Command
}

func (cmd *proxyGetCmd) run() error {
// Check if the pod belongs to a mesh
pod, err := cmd.clientSet.CoreV1().Pods(cmd.namespace).Get(context.TODO(), cmd.pod, metav1.GetOptions{})
if err != nil {
return annotateErrMsgWithPodNamespaceMsg("Could not find pod %s in namespace %s", cmd.pod, cmd.namespace)
}
if !isMeshedPod(*pod) {
return annotateErrMsgWithPodNamespaceMsg("Pod %s in namespace %s is not a part of a mesh", cmd.pod, cmd.namespace)
}
if pod.Status.Phase != corev1.PodRunning {
return annotateErrMsgWithPodNamespaceMsg("Pod %s in namespace %s is not running", cmd.pod, cmd.namespace)
}

dialer, err := k8s.DialerToPod(cmd.config, cmd.clientSet, cmd.pod, cmd.namespace)
envoyProxyConfig, err := cli.GetEnvoyProxyConfig(cmd.clientSet, cmd.config, cmd.namespace, cmd.pod, cmd.localPort, cmd.query)
if err != nil {
return err
}

portForwarder, err := k8s.NewPortForwarder(dialer, fmt.Sprintf("%d:%d", cmd.localPort, constants.EnvoyAdminPort))
if err != nil {
return errors.Errorf("Error setting up port forwarding: %s", err)
}

err = portForwarder.Start(func(pf *k8s.PortForwarder) error {
defer pf.Stop()
url := fmt.Sprintf("http://localhost:%d/%s", cmd.localPort, cmd.query)

// #nosec G107: Potential HTTP request made with variable url
resp, err := http.Get(url)
out := cmd.out // By default, output is written to stdout
if cmd.outFile != "" {
fd, err := os.Create(cmd.outFile)
if err != nil {
return errors.Errorf("Error fetching url %s: %s", url, err)
return errors.Errorf("Error opening file %s: %s", cmd.outFile, err)
}

out := cmd.out // By default, output is written to stdout
if cmd.outFile != "" {
fd, err := os.Create(cmd.outFile)
if err != nil {
return errors.Errorf("Error opening file %s: %s", cmd.outFile, err)
}
defer fd.Close() //nolint: errcheck, gosec
out = fd // write output to file
}

if _, err := io.Copy(out, resp.Body); err != nil {
return errors.Errorf("Error rendering HTTP response: %s", err)
}
return nil
})
if err != nil {
return annotateErrMsgWithPodNamespaceMsg("Error retrieving proxy config for pod %s in namespace %s: %s", cmd.pod, cmd.namespace, err)
defer fd.Close() //nolint: errcheck, gosec
out = fd // write output to file
}

return nil
w := bufio.NewWriter(out)
_, err = w.WriteString(string(envoyProxyConfig))
return err
}

// isMeshedPod returns a boolean indicating if the pod is part of a mesh
Expand All @@ -146,8 +110,3 @@ func isMeshedPod(pod corev1.Pod) bool {
_, proxyLabelSet := pod.Labels[constants.EnvoyUniqueIDLabelName]
return proxyLabelSet
}

// annotateProxyGetErrorMessage returns a formatted err msg with an actionable message regarding pod details
func annotateErrMsgWithPodNamespaceMsg(errMsgFormat string, args ...interface{}) error {
return annotateErrorMessageWithActionableMessage("Note: Use the flag --namespace to modify the intended pod namespace.", errMsgFormat, args...)
}
78 changes: 0 additions & 78 deletions cmd/cli/proxy_get_test.go

This file was deleted.

78 changes: 78 additions & 0 deletions pkg/cli/proxy_get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package cli

import (
"context"
"fmt"
"io/ioutil"
"net/http"

"github.com/google/uuid"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"

"github.com/openservicemesh/osm/pkg/constants"
"github.com/openservicemesh/osm/pkg/k8s"
)

// GetEnvoyProxyConfig returns the sidecar envoy proxy config of a pod
func GetEnvoyProxyConfig(clientSet kubernetes.Interface, config *rest.Config, namespace string, podName string, localPort uint16, query string) ([]byte, error) {
// Check if the pod belongs to a mesh
pod, err := clientSet.CoreV1().Pods(namespace).Get(context.TODO(), podName, metav1.GetOptions{})
if err != nil {
return nil, errors.Errorf("Could not find pod %s in namespace %s", podName, namespace)
}
if !proxyLabelExists(*pod) {
return nil, errors.Errorf("Pod %s in namespace %s is not a part of a mesh", podName, namespace)
}
if pod.Status.Phase != corev1.PodRunning {
return nil, errors.Errorf("Pod %s in namespace %s is not running", podName, namespace)
}

dialer, err := k8s.DialerToPod(config, clientSet, podName, namespace)
if err != nil {
return nil, err
}

portForwarder, err := k8s.NewPortForwarder(dialer, fmt.Sprintf("%d:%d", localPort, constants.EnvoyAdminPort))
if err != nil {
return nil, errors.Errorf("Error setting up port forwarding: %s", err)
}

var envoyProxyConfig []byte
err = portForwarder.Start(func(pf *k8s.PortForwarder) error {
defer pf.Stop()
url := fmt.Sprintf("http://localhost:%d/%s", localPort, query)

// #nosec G107: Potential HTTP request made with variable url
resp, err := http.Get(url)
if err != nil {
return errors.Errorf("Error fetching url %s: %s", url, err)
}

envoyProxyConfig, err = ioutil.ReadAll(resp.Body)
if err != nil {
return errors.Errorf("Error rendering HTTP response: %s", err)
}
return nil
})
if err != nil {
return nil, errors.Errorf("Error retrieving proxy config for pod %s in namespace %s: %s", podName, namespace, err)
}

return envoyProxyConfig, nil
}

// proxyLabelExists returns a boolean indicating if the pod is part of a mesh
func proxyLabelExists(pod corev1.Pod) bool {
// osm-controller adds a unique label to each pod that belongs to a mesh
proxyUUID, proxyLabelSet := pod.Labels[constants.EnvoyUniqueIDLabelName]
return proxyLabelSet && isValidUUID(proxyUUID)
}

func isValidUUID(u string) bool {
_, err := uuid.Parse(u)
return err == nil
}
48 changes: 48 additions & 0 deletions pkg/cli/proxy_get_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package cli

import (
"fmt"
"testing"

tassert "github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/openservicemesh/osm/pkg/constants"
)

func TestIsMeshedPod(t *testing.T) {
type test struct {
pod corev1.Pod
isMeshed bool
}

testCases := []test{
{
pod: corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod-1",
Labels: map[string]string{constants.EnvoyUniqueIDLabelName: "test"},
},
},
isMeshed: true,
},
{
pod: corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod-2",
},
},
isMeshed: false,
},
}

for _, tc := range testCases {
t.Run(fmt.Sprintf("Testing if pod %s is meshed", tc.pod.Name), func(t *testing.T) {
assert := tassert.New(t)

isMeshed := proxyLabelExists(tc.pod)
assert.Equal(isMeshed, tc.isMeshed)
})
}
}

0 comments on commit 9be2511

Please sign in to comment.