Skip to content

Commit

Permalink
Merge pull request #2 from pabateman/feature/add-cri-o
Browse files Browse the repository at this point in the history
CRI-O support
  • Loading branch information
pabateman authored Jun 4, 2022
2 parents 244dacc + 6c1a00d commit c3696c0
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 79 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/build-by-tag.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,6 @@ jobs:
tag: ${{ github.ref }}
overwrite: true
file_glob: true

- name: Update new version in krew-index
uses: rajatjindal/krew-release-bot@v0.0.43
50 changes: 50 additions & 0 deletions .krew.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
apiVersion: krew.googlecontainertools.github.com/v1alpha2
kind: Plugin
metadata:
name: nsenter
spec:
version: {{ .TagName }}
homepage: https://github.com/pabateman/kubectl-nsenter
shortDescription: "Run shell command in Pod's namespace on the node over SSH connection"
description: |
This plugin establishes a connection to node that's running the Pod over SSH and uses
nsenter to run commands in the container's namespace. You would need something
like this to run programs that are missing in the container image but presents on node.
caveats: |
* This plugin needs SSH access to nodes
* Remote user must have root access
* Nodes need to have 'nsenter'
platforms:
- selector:
matchLabels:
os: linux
arch: amd64
{{addURIAndSha "https://github.com/pabateman/kubectl-nsenter/releases/download/{{ .TagName }}/kubectl-nsenter-linux-amd64.tar.gz" .TagName }}
bin: kubectl-nsenter
files:
- from: kubectl-nsenter-linux-amd64
to: kubectl-nsenter
- from: LICENSE
to: .
- selector:
matchLabels:
os: darwin
arch: amd64
{{addURIAndSha "https://github.com/pabateman/kubectl-nsenter/releases/download/{{ .TagName }}/kubectl-nsenter-darwin-amd64.tar.gz" .TagName }}
bin: kubectl-nsenter
files:
- from: kubectl-nsenter-darwin-amd64
to: kubectl-nsenter
- from: LICENSE
to: .
- selector:
matchLabels:
os: darwin
arch: arm64
{{addURIAndSha "https://github.com/pabateman/kubectl-nsenter/releases/download/{{ .TagName }}/kubectl-nsenter-darwin-arm64.tar.gz" .TagName }}
bin: kubectl-nsenter
files:
- from: kubectl-nsenter-darwin-arm64
to: kubectl-nsenter
- from: LICENSE
to: .
49 changes: 0 additions & 49 deletions .krew/nsenter.yaml

This file was deleted.

7 changes: 6 additions & 1 deletion cmd/kubectl-nsenter/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
func main() {
app := &cli.App{
Name: "kubectl-nsenter",
Version: "v0.1.0",
Version: "v0.1.1",
Compiled: time.Now(),
Authors: []*cli.Author{
{
Expand Down Expand Up @@ -78,6 +78,11 @@ func main() {
DefaultText: "current shell auth sock",
Required: false,
},
&cli.StringFlag{
Name: "host",
Usage: "override node ip",
Required: false,
},
&cli.StringFlag{
Name: "port",
Aliases: []string{"p"},
Expand Down
45 changes: 28 additions & 17 deletions internal/nsenter/containerinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"strings"

"github.com/pkg/errors"
"github.com/urfave/cli/v2"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
Expand All @@ -18,41 +19,51 @@ type ContainerInfo struct {
ContainerRuntime string
}

func GetContainerInfo(kubeconfigFiles []string, contextOverride string, namespaceOverride string, pod string, container string) (*ContainerInfo, error) {

func GetClientSet(clictx *cli.Context) (*kubernetes.Clientset, string, error) {
config := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
&clientcmd.ClientConfigLoadingRules{Precedence: kubeconfigFiles},
&clientcmd.ClientConfigLoadingRules{Precedence: strings.Split(clictx.String("kubeconfig"), ":")},
&clientcmd.ConfigOverrides{
CurrentContext: contextOverride,
CurrentContext: clictx.String("context"),
})

var namespace string
var err error
if namespaceOverride == "" {
namespace, _, err = config.Namespace()
if err != nil {
return nil, errors.Wrap(err, "can't get current namespace")
}
} else {
namespace = namespaceOverride
}

clientConfig, err := config.ClientConfig()
if err != nil {
return nil, errors.Wrap(err, "can't build config")
return nil, "", errors.Wrap(err, "can't build config")
}

clientset, err := kubernetes.NewForConfig(clientConfig)
if err != nil {
return nil, "", errors.Wrap(err, "can't build client")
}

namespace, _, err := config.Namespace()
if err != nil {
return nil, "", errors.Wrap(err, "can't get current namespace")
}

return clientset, namespace, nil
}

func GetContainerInfo(clictx *cli.Context) (*ContainerInfo, error) {

kubeClient, namespace, err := GetClientSet(clictx)
if err != nil {
return nil, errors.Wrap(err, "can't build client")
}

podSpec, err := clientset.CoreV1().Pods(namespace).Get(context.TODO(), pod, metav1.GetOptions{})
if clictx.String("namespace") != "" {
namespace = clictx.String("namespace")
}

podSpec, err := kubeClient.CoreV1().Pods(namespace).Get(context.TODO(), clictx.Args().First(), metav1.GetOptions{})
if err != nil {
return nil, errors.Wrap(err, "can't get pod spec")
}

var containerID string
var containerRuntime string
container := clictx.String("container")

if container != "" {
for _, containerStatus := range podSpec.Status.ContainerStatuses {
if containerStatus.Name == container {
Expand Down
20 changes: 8 additions & 12 deletions internal/nsenter/nsenter.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,19 @@ func requestPassword(user, host string) (string, error) {
}

func Nsenter(clictx *cli.Context) error {
container := clictx.String("container")
kubeconfigPath := clictx.String("kubeconfig")
contextOverride := clictx.String("context")
namespaceOverride := clictx.String("namespace")
podName := clictx.Args().First()
if podName == "" {
fmt.Println("you must specify pod name!")
return cli.ShowAppHelp(clictx)
}

command := clictx.Args().Tail()
if len(command) == 0 {
fmt.Println("you must provide a command!")
return cli.ShowAppHelp(clictx)
}
kubeconfigFiles := strings.Split(kubeconfigPath, ":")
containerInfo, err := GetContainerInfo(
kubeconfigFiles,
contextOverride,
namespaceOverride,
podName,
container)

containerInfo, err := GetContainerInfo(clictx)
if err != nil {
return errors.WithMessage(err, "can't get container info")
}
Expand Down Expand Up @@ -74,6 +66,10 @@ func Nsenter(clictx *cli.Context) error {
}
}

if clictx.String("host") != "" {
containerInfo.NodeIP = clictx.String("host")
}

sshPort := clictx.String("port")
sshHost := net.JoinHostPort(containerInfo.NodeIP, sshPort)

Expand Down Expand Up @@ -112,7 +108,7 @@ func Nsenter(clictx *cli.Context) error {
switch containerInfo.ContainerRuntime {
case "docker":
pidDiscoverCommand = fmt.Sprintf("sudo docker inspect %s --format {{.State.Pid}}", containerInfo.ContainerID)
case "containerd":
case "containerd", "cri-o":
pidDiscoverCommand = fmt.Sprintf("sudo crictl inspect --output go-template --template={{.info.pid}} %s", containerInfo.ContainerID)
default:
return fmt.Errorf("unsupported container runtime")
Expand Down

0 comments on commit c3696c0

Please sign in to comment.