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 podman version to odo version output #6913

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
30 changes: 29 additions & 1 deletion docs/website/docs/command-reference/json-output.md
Original file line number Diff line number Diff line change
Expand Up @@ -906,4 +906,32 @@ If odo can't find any projects on the cluster that you have access to, it will s
```shell
$ odo list projects -o json
{}
```
```

## odo version -o json
The `odo version -o json` returns the version information about `odo`, cluster server and podman client.
Use `--client` flag to only obtain version information about `odo`.
```shell
odo version -o json [--client]
```
```shell
$ odo version -o json
{
"version": "v3.11.0",
"gitCommit": "ea2d256e8",
"cluster": {
"serverURL": "https://kubernetes.docker.internal:6443",
"kubernetes": {
"version": "v1.25.9"
},
"openshift": {
"version": "4.13.0"
},
},
"podman": {
"client": {
"version": "4.5.1"
}
}
}
```
28 changes: 28 additions & 0 deletions docs/website/docs/command-reference/version.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
title: odo version
---

## Description
The `odo version` command returns the version information about `odo`, cluster server and podman client.

## Running the Command
The command takes an optional `--client` flag that only returns version information about `odo`.

The command will only print Openshift version if it is available.
```shell
odo version [--client] [-o json]
```

<details>
<summary>Example</summary>

```shell
$ odo version
odo v3.11.0 (a9e6cdc34)

Server: https://ab0bc42973f0043e7a2b9c24f5acddd6-9c1554c20c1ec323.elb.us-east-1.amazonaws.com:6443
OpenShift: 4.13.0
Kubernetes: v1.27.2+b451817
Podman Client: 4.5.1
```
</details>
47 changes: 47 additions & 0 deletions pkg/api/version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package api

/*
{
"version": "v3.11.0",
"gitCommit": "0acf1a5af",
"cluster": {
"serverURL": "https://kubernetes.docker.internal:6443",
"kubernetes": {
"version": "v1.25.9"
},
"openshift": {
"version": "4.13.0"
}
},
"podman": {
"client": {
"version": "4.5.1"
}
}
}
*/

type OdoVersion struct {
Version string `json:"version"`
GitCommit string `json:"gitCommit"`
Cluster *ClusterInfo `json:"cluster,omitempty"`
Podman *PodmanInfo `json:"podman,omitempty"`
}

type ClusterInfo struct {
ServerURL string `json:"serverURL,omitempty"`
Kubernetes *ClusterClientInfo `json:"kubernetes,omitempty"`
OpenShift *ClusterClientInfo `json:"openshift,omitempty"`
}

type ClusterClientInfo struct {
Version string `json:"version,omitempty"`
}

type PodmanInfo struct {
Client *PodmanClientInfo `json:"client,omitempty"`
}

type PodmanClientInfo struct {
Version string `json:"version,omitempty"`
}
6 changes: 3 additions & 3 deletions pkg/kclient/oc_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,15 @@ func (c *Client) GetServerVersion(timeout time.Duration) (*ServerInfo, error) {

// This will fetch the information about OpenShift Version
coreGet := c.GetClient().CoreV1().RESTClient().Get()
rawOpenShiftVersion, err := coreGet.AbsPath("/version/openshift").Do(context.TODO()).Raw()
rawOpenShiftVersion, err := coreGet.AbsPath("/apis/config.openshift.io/v1/clusterversions/version").Do(context.TODO()).Raw()
if err != nil {
klog.V(3).Info("Unable to get OpenShift Version: ", err)
} else {
var openShiftVersion version.Info
var openShiftVersion configv1.ClusterVersion
if e := json.Unmarshal(rawOpenShiftVersion, &openShiftVersion); e != nil {
return nil, fmt.Errorf("unable to unmarshal OpenShift version %v: %w", string(rawOpenShiftVersion), e)
}
info.OpenShiftVersion = openShiftVersion.GitVersion
info.OpenShiftVersion = openShiftVersion.Status.Desired.Version
}

// This will fetch the information about Kubernetes Version
Expand Down
115 changes: 89 additions & 26 deletions pkg/odo/cli/version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ package version
import (
"context"
"fmt"
"github.com/redhat-developer/odo/pkg/api"
"github.com/redhat-developer/odo/pkg/log"
"github.com/redhat-developer/odo/pkg/odo/commonflags"
"github.com/redhat-developer/odo/pkg/podman"
"os"
"strings"

Expand Down Expand Up @@ -39,11 +43,12 @@ type VersionOptions struct {

// serverInfo contains the remote server information if the user asked for it, nil otherwise
serverInfo *kclient.ServerInfo

clientset *clientset.Clientset
podmanInfo podman.SystemVersionReport
clientset *clientset.Clientset
}

var _ genericclioptions.Runnable = (*VersionOptions)(nil)
var _ genericclioptions.JsonOutputter = (*VersionOptions)(nil)

// NewVersionOptions creates a new VersionOptions instance
func NewVersionOptions() *VersionOptions {
Expand All @@ -56,17 +61,31 @@ func (o *VersionOptions) SetClientset(clientset *clientset.Clientset) {

// Complete completes VersionOptions after they have been created
func (o *VersionOptions) Complete(ctx context.Context, cmdline cmdline.Cmdline, args []string) (err error) {
if !o.clientFlag {
// Let's fetch the info about the server, ignoring errors
client, err := kclient.New()

if err == nil {
o.serverInfo, err = client.GetServerVersion(o.clientset.PreferenceClient.GetTimeout())
if err != nil {
klog.V(4).Info("unable to fetch the server version: ", err)
}
if o.clientFlag {
return nil
}

// Fetch the info about the server, ignoring errors
if o.clientset.KubernetesClient != nil {
o.serverInfo, err = o.clientset.KubernetesClient.GetServerVersion(o.clientset.PreferenceClient.GetTimeout())
if err != nil {
klog.V(4).Info("unable to fetch the server version: ", err)
}
}

if o.clientset.PodmanClient != nil {
o.podmanInfo, err = o.clientset.PodmanClient.Version(ctx)
if err != nil {
klog.V(4).Info("unable to fetch the podman client version: ", err)
}
}

if o.serverInfo == nil {
log.Warning("unable to fetch the cluster server version")
}
if o.podmanInfo.Client == nil {
log.Warning("unable to fetch the podman client version")
}
return nil
}

Expand All @@ -75,33 +94,76 @@ func (o *VersionOptions) Validate(ctx context.Context) (err error) {
return nil
}

func (o *VersionOptions) RunForJsonOutput(ctx context.Context) (out interface{}, err error) {
return o.run(), nil
}

func (o *VersionOptions) run() api.OdoVersion {
result := api.OdoVersion{
Version: odoversion.VERSION,
GitCommit: odoversion.GITCOMMIT,
}

if o.clientFlag {
return result
}

if o.serverInfo != nil {
clusterInfo := &api.ClusterInfo{
ServerURL: o.serverInfo.Address,
Kubernetes: &api.ClusterClientInfo{Version: o.serverInfo.KubernetesVersion},
}
if o.serverInfo.OpenShiftVersion != "" {
clusterInfo.OpenShift = &api.ClusterClientInfo{Version: o.serverInfo.OpenShiftVersion}
}
result.Cluster = clusterInfo
}

if o.podmanInfo.Client != nil {
podmanInfo := &api.PodmanInfo{Client: &api.PodmanClientInfo{Version: o.podmanInfo.Client.Version}}
result.Podman = podmanInfo
}

return result
}

// Run contains the logic for the odo service create command
func (o *VersionOptions) Run(ctx context.Context) (err error) {
// If verbose mode is enabled, dump all KUBECLT_* env variables
// this is usefull for debuging oc plugin integration
// If verbose mode is enabled, dump all KUBECTL_* env variables
// this is useful for debugging oc plugin integration
for _, v := range os.Environ() {
if strings.HasPrefix(v, "KUBECTL_") {
klog.V(4).Info(v)
}
}

fmt.Println("odo " + odoversion.VERSION + " (" + odoversion.GITCOMMIT + ")")
odoVersion := o.run()
fmt.Println("odo " + odoVersion.Version + " (" + odoVersion.GitCommit + ")")

if o.clientFlag {
return nil
}

message := "\n"
if odoVersion.Cluster != nil {
cluster := odoVersion.Cluster
message += fmt.Sprintf("Server: %v\n", cluster.ServerURL)

if !o.clientFlag && o.serverInfo != nil {
// make sure we only include OpenShift info if we actually have it
openshiftStr := ""
if len(o.serverInfo.OpenShiftVersion) > 0 {
openshiftStr = fmt.Sprintf("OpenShift: %v\n", o.serverInfo.OpenShiftVersion)
if cluster.OpenShift != nil && cluster.OpenShift.Version != "" {
message += fmt.Sprintf("OpenShift: %v\n", cluster.OpenShift.Version)
}
if cluster.Kubernetes != nil {
message += fmt.Sprintf("Kubernetes: %v\n", cluster.Kubernetes.Version)
}
fmt.Printf("\n"+
"Server: %v\n"+
"%v"+
"Kubernetes: %v\n",
o.serverInfo.Address,
openshiftStr,
o.serverInfo.KubernetesVersion)
}

if odoVersion.Podman != nil && odoVersion.Podman.Client != nil {
message += fmt.Sprintf("Podman Client: %v\n", odoVersion.Podman.Client.Version)
}

fmt.Print(message)

return nil
}

Expand All @@ -118,7 +180,8 @@ func NewCmdVersion(name, fullName string, testClientset clientset.Clientset) *co
return genericclioptions.GenericRun(o, testClientset, cmd, args)
},
}
clientset.Add(versionCmd, clientset.PREFERENCE)
commonflags.UseOutputFlag(versionCmd)
clientset.Add(versionCmd, clientset.PREFERENCE, clientset.KUBERNETES_NULLABLE, clientset.PODMAN_NULLABLE)
util.SetCommandGroup(versionCmd, util.UtilityGroup)

versionCmd.SetUsageTemplate(util.CmdUsageTemplate)
Expand Down
7 changes: 7 additions & 0 deletions tests/helper/helper_generic.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"context"
"encoding/json"
"fmt"
"github.com/onsi/gomega/types"
"os"
"path/filepath"
"regexp"
Expand Down Expand Up @@ -324,6 +325,12 @@ func JsonPathContentContain(json string, path string, value string) {
Expect(result.String()).To(ContainSubstring(value), fmt.Sprintf("content of path %q should contain %q but is %q", path, value, result.String()))
}

// JsonPathSatisfies expects content of the path to satisfy all the matchers passed to it
func JsonPathSatisfies(json string, path string, matchers ...types.GomegaMatcher) {
result := gjson.Get(json, path)
Expect(result.String()).Should(SatisfyAll(matchers...))
}

// JsonPathDoesNotExist expects that the content of the path does not exist in the JSON string
func JsonPathDoesNotExist(json string, path string) {
result := gjson.Get(json, path)
Expand Down
15 changes: 15 additions & 0 deletions tests/helper/helper_podman.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,18 @@ func GetPodmanVersion() string {
Expect(err).ToNot(HaveOccurred())
return result.Client.Version
}

// GenerateDelayedPodman returns a podman cmd that sleeps for delaySecond before responding;
// this function is usually used in combination with PODMAN_CMD_INIT_TIMEOUT odo preference
func GenerateDelayedPodman(commonVarContext string, delaySecond int) string {
delayer := filepath.Join(commonVarContext, "podman-cmd-delayer")
fileContent := fmt.Sprintf(`#!/bin/bash

echo Delaying command execution... >&2
sleep %d
echo "$@"
`, delaySecond)
err := CreateFileWithContentAndPerm(delayer, fileContent, 0755)
Expect(err).ToNot(HaveOccurred())
return delayer
}
9 changes: 1 addition & 8 deletions tests/integration/cmd_dev_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,7 @@ var _ = Describe("odo dev command tests", func() {
// odo dev on cluster should not wait for the Podman client to initialize properly, if this client takes very long.
// See https://github.com/redhat-developer/odo/issues/6575.
// StartDevMode will time out if Podman client takes too long to initialize.
delayer := filepath.Join(commonVar.Context, "podman-cmd-delayer")
err = helper.CreateFileWithContentAndPerm(delayer, `#!/bin/bash

echo Delaying command execution... >&2
sleep 10
echo "$@"
`, 0755)
Expect(err).ShouldNot(HaveOccurred())
delayer := helper.GenerateDelayedPodman(commonVar.Context, 10)

var devSession helper.DevSession
devSession, err = helper.StartDevMode(helper.DevSessionOpts{
Expand Down
Loading