Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for podman v2 to podman-env command #9535

Merged
merged 3 commits into from
Nov 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 110 additions & 14 deletions cmd/minikube/cmd/podman-env.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,16 @@ import (
"k8s.io/minikube/pkg/minikube/shell"
)

var podmanEnvTmpl = fmt.Sprintf("{{ .Prefix }}%s{{ .Delimiter }}{{ .VarlinkBridge }}{{ .Suffix }}{{ .Prefix }}%s{{ .Delimiter }}{{ .MinikubePodmanProfile }}{{ .Suffix }}{{ .UsageHint }}", constants.PodmanVarlinkBridgeEnv, constants.MinikubeActivePodmanEnv)
var podmanEnv1Tmpl = fmt.Sprintf("{{ .Prefix }}%s{{ .Delimiter }}{{ .VarlinkBridge }}{{ .Suffix }}{{ .Prefix }}%s{{ .Delimiter }}{{ .MinikubePodmanProfile }}{{ .Suffix }}{{ .UsageHint }}", constants.PodmanVarlinkBridgeEnv, constants.MinikubeActivePodmanEnv)

var podmanEnv2Tmpl = fmt.Sprintf("{{ .Prefix }}%s{{ .Delimiter }}{{ .ContainerHost }}{{ .Suffix }}{{ if .ContainerSSHKey }}{{ .Prefix }}%s{{ .Delimiter }}{{ .ContainerSSHKey}}{{ .Suffix }}{{ end }}{{ .Prefix }}%s{{ .Delimiter }}{{ .MinikubePodmanProfile }}{{ .Suffix }}{{ .UsageHint }}", constants.PodmanContainerHostEnv, constants.PodmanContainerSSHKeyEnv, constants.MinikubeActivePodmanEnv)

// PodmanShellConfig represents the shell config for Podman
type PodmanShellConfig struct {
shell.Config
VarlinkBridge string
ContainerHost string
ContainerSSHKey string
MinikubePodmanProfile string
}

Expand All @@ -59,17 +63,24 @@ func podmanShellCfgSet(ec PodmanEnvConfig, envMap map[string]string) *PodmanShel
Config: *shell.CfgSet(ec.EnvConfig, usgPlz, usgCmd),
}
s.VarlinkBridge = envMap[constants.PodmanVarlinkBridgeEnv]
s.ContainerHost = envMap[constants.PodmanContainerHostEnv]
s.ContainerSSHKey = envMap[constants.PodmanContainerSSHKeyEnv]
s.MinikubePodmanProfile = envMap[constants.MinikubeActivePodmanEnv]

return s
}

// isPodmanAvailable checks if Podman is available
func isPodmanAvailable(r command.Runner) bool {
// isVarlinkAvailable checks if varlink command is available
func isVarlinkAvailable(r command.Runner) bool {
if _, err := r.RunCmd(exec.Command("which", "varlink")); err != nil {
return false
}

return true
}

// isPodmanAvailable checks if podman command is available
func isPodmanAvailable(r command.Runner) bool {
if _, err := r.RunCmd(exec.Command("which", "podman")); err != nil {
return false
}
Expand Down Expand Up @@ -130,11 +141,25 @@ var podmanEnvCmd = &cobra.Command{
exit.Message(reason.Usage, `The podman-env command is incompatible with multi-node clusters. Use the 'registry' add-on: https://minikube.sigs.k8s.io/docs/handbook/registry/`)
}

if ok := isPodmanAvailable(co.CP.Runner); !ok {
r := co.CP.Runner
if ok := isPodmanAvailable(r); !ok {
exit.Message(reason.EnvPodmanUnavailable, `The podman service within '{{.cluster}}' is not active`, out.V{"cluster": cname})
}

client, err := createExternalSSHClient(co.CP.Host.Driver)
varlink := isVarlinkAvailable(r)

d := co.CP.Host.Driver
client, err := createExternalSSHClient(d)
if err != nil {
exit.Error(reason.IfSSHClient, "Error getting ssh client", err)
}

hostname, err := d.GetSSHHostname()
if err != nil {
exit.Error(reason.IfSSHClient, "Error getting ssh client", err)
}

port, err := d.GetSSHPort()
if err != nil {
exit.Error(reason.IfSSHClient, "Error getting ssh client", err)
}
Expand All @@ -143,7 +168,12 @@ var podmanEnvCmd = &cobra.Command{
EnvConfig: sh,
profile: cname,
driver: driverName,
varlink: varlink,
client: client,
username: d.GetSSHUsername(),
hostname: hostname,
port: port,
keypath: d.GetSSHKeyPath(),
}

if ec.Shell == "" {
Expand All @@ -162,23 +192,31 @@ var podmanEnvCmd = &cobra.Command{
// PodmanEnvConfig encapsulates all external inputs into shell generation for Podman
type PodmanEnvConfig struct {
shell.EnvConfig
profile string
driver string
client *ssh.ExternalClient
profile string
driver string
varlink bool
client *ssh.ExternalClient
username string
hostname string
port int
keypath string
}

// podmanSetScript writes out a shell-compatible 'podman-env' script
func podmanSetScript(ec PodmanEnvConfig, w io.Writer) error {
var podmanEnvTmpl string
if ec.varlink {
podmanEnvTmpl = podmanEnv1Tmpl
} else {
podmanEnvTmpl = podmanEnv2Tmpl
}
envVars := podmanEnvVars(ec)
return shell.SetScript(ec.EnvConfig, w, podmanEnvTmpl, podmanShellCfgSet(ec, envVars))
}

// podmanUnsetScript writes out a shell-compatible 'podman-env unset' script
func podmanUnsetScript(ec PodmanEnvConfig, w io.Writer) error {
vars := []string{
constants.PodmanVarlinkBridgeEnv,
constants.MinikubeActivePodmanEnv,
}
vars := podmanEnvNames(ec)
return shell.UnsetScript(ec.EnvConfig, w, vars)
}

Expand All @@ -190,15 +228,73 @@ func podmanBridge(client *ssh.ExternalClient) string {
return strings.Join(command, " ")
}

// podmanURL returns the url to use in a var for accessing the podman socket over ssh
func podmanURL(username string, hostname string, port int) string {
path := "/run/podman/podman.sock"
return fmt.Sprintf("ssh://%s@%s:%d%s", username, hostname, port, path)
}

// podmanEnvVars gets the necessary podman env variables to allow the use of minikube's podman service
func podmanEnvVars(ec PodmanEnvConfig) map[string]string {
env := map[string]string{
constants.PodmanVarlinkBridgeEnv: podmanBridge(ec.client),
// podman v1
env1 := map[string]string{
constants.PodmanVarlinkBridgeEnv: podmanBridge(ec.client),
}
// podman v2
env2 := map[string]string{
constants.PodmanContainerHostEnv: podmanURL(ec.username, ec.hostname, ec.port),
constants.PodmanContainerSSHKeyEnv: ec.keypath,
}
//common
env0 := map[string]string{
constants.MinikubeActivePodmanEnv: ec.profile,
}

var env map[string]string
if ec.varlink {
env = env1
} else {
env = env2
}
for k, v := range env0 {
env[k] = v
}
return env
}

// podmanEnvNames gets the necessary podman env variables to reset after using minikube's podman service
func podmanEnvNames(ec PodmanEnvConfig) []string {
// podman v1
vars1 := []string{
constants.PodmanVarlinkBridgeEnv,
}
// podman v2
vars2 := []string{
constants.PodmanContainerHostEnv,
constants.PodmanContainerSSHKeyEnv,
}
// common
vars0 := []string{
constants.MinikubeActivePodmanEnv,
}

var vars []string
if ec.client != nil || ec.hostname != "" {
// getting ec.varlink needs a running machine
if ec.varlink {
vars = vars1
} else {
vars = vars2
}
} else {
// just unset *all* of the variables instead
vars = vars1
vars = append(vars, vars2...)
}
vars = append(vars, vars0...)
return vars
}

func init() {
podmanEnvCmd.Flags().StringVar(&shell.ForceShell, "shell", "", "Force environment to be configured for a specified shell: [fish, cmd, powershell, tcsh, bash, zsh], default is auto-detect")
podmanEnvCmd.Flags().BoolVarP(&podmanUnset, "unset", "u", false, "Unset variables instead of setting them")
Expand Down
15 changes: 14 additions & 1 deletion cmd/minikube/cmd/podman-env_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func TestGeneratePodmanScripts(t *testing.T) {
}{
{
"bash",
PodmanEnvConfig{profile: "bash", driver: "kvm2", client: newFakeClient()},
PodmanEnvConfig{profile: "bash", driver: "kvm2", varlink: true, client: newFakeClient()},
nil,
`export PODMAN_VARLINK_BRIDGE="/usr/bin/ssh root@host -- sudo varlink -A \'podman varlink \\\$VARLINK_ADDRESS\' bridge"
export MINIKUBE_ACTIVE_PODMAN="bash"
Expand All @@ -50,6 +50,19 @@ export MINIKUBE_ACTIVE_PODMAN="bash"
# eval $(minikube -p bash podman-env)
`,
`unset PODMAN_VARLINK_BRIDGE MINIKUBE_ACTIVE_PODMAN
`,
},
{
"bash",
PodmanEnvConfig{profile: "bash", driver: "kvm2", client: newFakeClient(), username: "root", hostname: "host", port: 22},
nil,
`export CONTAINER_HOST="ssh://root@host:22/run/podman/podman.sock"
export MINIKUBE_ACTIVE_PODMAN="bash"

# To point your shell to minikube's podman service, run:
# eval $(minikube -p bash podman-env)
`,
`unset CONTAINER_HOST CONTAINER_SSHKEY MINIKUBE_ACTIVE_PODMAN
`,
},
}
Expand Down
4 changes: 4 additions & 0 deletions pkg/minikube/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ const (
MinikubeActiveDockerdEnv = "MINIKUBE_ACTIVE_DOCKERD"
// PodmanVarlinkBridgeEnv is used for podman settings
PodmanVarlinkBridgeEnv = "PODMAN_VARLINK_BRIDGE"
// PodmanContainerHostEnv is used for podman settings
PodmanContainerHostEnv = "CONTAINER_HOST"
// PodmanContainerSSHKeyEnv is used for podman settings
PodmanContainerSSHKeyEnv = "CONTAINER_SSHKEY"
// MinikubeActivePodmanEnv holds the podman service that the user's shell is pointing at
// value would be profile or empty if pointing to the user's host.
MinikubeActivePodmanEnv = "MINIKUBE_ACTIVE_PODMAN"
Expand Down