Merge pull request #39858 from alejandroEsc/ae/issue/39427

Automatic merge from submit-queue

addressing issue #39427 adding a flag --output to 'kubectl version'

**What this PR does / why we need it**:
Addressing Issue https://github.com/kubernetes/kubernetes/issues/39427 we all

**Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes #39427 


**Release note**:
```
kubectl version has new flag --output (=json or yaml) allowing result of the command to be parsed in either json format or yaml. 
```
This commit is contained in:
Kubernetes Submit Queue 2017-03-28 12:12:22 -07:00 committed by GitHub
commit c01baaf54f
4 changed files with 213 additions and 20 deletions

View File

@ -303,3 +303,100 @@ kube::test::if_supports_resource() {
done
return 1
}
kube::test::version::object_to_file() {
name=$1
flags=${2:-""}
file=$3
kubectl version $flags | grep "$name Version:" | sed -e s/"$name Version: version.Info{"/'/' -e s/'}'/'/' -e s/', '/','/g -e s/':'/'=/g' -e s/'"'/""/g | tr , '\n' > "${file}"
}
kube::test::version::json_object_to_file() {
flags=$1
file=$2
kubectl version $flags --output json | sed -e s/'\"'/''/g -e s/'}'/''/g -e s/'{'/''/g -e s/'clientVersion:'/'clientVersion:,'/ -e s/'serverVersion:'/'serverVersion:,'/ | tr , '\n' > "${file}"
}
kube::test::version::json_client_server_object_to_file() {
flags=$1
name=$2
file=$3
kubectl version $flags --output json | jq -r ".${name}" | sed -e s/'\"'/''/g -e s/'}'/''/g -e s/'{'/''/g -e /^$/d -e s/','/''/g -e s/':'/'='/g > "${file}"
}
kube::test::version::yaml_object_to_file() {
flags=$1
file=$2
kubectl version $flags --output yaml | sed -e s/' '/''/g -e s/'\"'/''/g -e /^$/d > "${file}"
}
kube::test::version::diff_assert() {
local original=$1
local comparator=${2:-"eq"}
local latest=$3
local diff_msg=${4:-""}
local res=""
if [ ! -f $original ]; then
echo ${bold}${red}
echo "FAIL! ${diff_msg}"
echo "the file '${original}' does not exit"
echo ${reset}${red}
caller
echo ${reset}
return 1
fi
if [ ! -f $latest ]; then
echo ${bold}${red}
echo "FAIL! ${diff_msg}"
echo "the file '${latest}' does not exit"
echo ${reset}${red}
caller
echo ${reset}
return 1
fi
sort ${original} > "${original}.sorted"
sort ${latest} > "${latest}.sorted"
if [ "$comparator" == "eq" ]; then
if [ "$(diff -iwB ${original}.sorted ${latest}.sorted)" == "" ] ; then
echo -n ${green}
echo "Successful: ${diff_msg}"
echo -n ${reset}
return 0
else
echo ${bold}${red}
echo "FAIL! ${diff_msg}"
echo " Expected: "
echo "$(cat ${original})"
echo " Got: "
echo "$(cat ${latest})"
echo ${reset}${red}
caller
echo ${reset}
return 1
fi
else
if [ ! -z "$(diff -iwB ${original}.sorted ${latest}.sorted)" ] ; then
echo -n ${green}
echo "Successful: ${diff_msg}"
echo -n ${reset}
return 0
else
echo ${bold}${red}
echo "FAIL! ${diff_msg}"
echo " Expected: "
echo "$(cat ${original})"
echo " Got: "
echo "$(cat ${latest})"
echo ${reset}${red}
caller
echo ${reset}
return 1
fi
fi
}

View File

@ -223,6 +223,48 @@ setup() {
kube::log::status "Setup complete"
}
########################################################
# Kubectl version (--short, --client, --output) #
########################################################
run_kubectl_version_tests() {
kube::log::status "Testing kubectl version"
TEMP="${KUBE_TEMP}"
# create version files, one for the client, one for the server.
# these are the files we will use to ensure that the remainder output is correct
kube::test::version::object_to_file "Client" "" "${TEMP}/client_version_test"
kube::test::version::object_to_file "Server" "" "${TEMP}/server_version_test"
kube::log::status "Testing kubectl version: check client only output matches expected output"
kube::test::version::object_to_file "Client" "--client" "${TEMP}/client_only_version_test"
kube::test::version::object_to_file "Client" "--client" "${TEMP}/server_client_only_version_test"
kube::test::version::diff_assert "${TEMP}/client_version_test" "eq" "${TEMP}/client_only_version_test" "the flag '--client' shows correct client info"
kube::test::version::diff_assert "${TEMP}/server_version_test" "ne" "${TEMP}/server_client_only_version_test" "the flag '--client' correctly has no server version info"
kube::log::status "Testing kubectl version: verify json output"
kube::test::version::json_client_server_object_to_file "" "clientVersion" "${TEMP}/client_json_version_test"
kube::test::version::json_client_server_object_to_file "" "serverVersion" "${TEMP}/server_json_version_test"
kube::test::version::diff_assert "${TEMP}/client_version_test" "eq" "${TEMP}/client_json_version_test" "--output json has correct client info"
kube::test::version::diff_assert "${TEMP}/server_version_test" "eq" "${TEMP}/server_json_version_test" "--output json has correct server info"
kube::log::status "Testing kubectl version: verify json output using additional --client flag does not contain serverVersion"
kube::test::version::json_client_server_object_to_file "--client" "clientVersion" "${TEMP}/client_only_json_version_test"
kube::test::version::json_client_server_object_to_file "--client" "serverVersion" "${TEMP}/server_client_only_json_version_test"
kube::test::version::diff_assert "${TEMP}/client_version_test" "eq" "${TEMP}/client_only_json_version_test" "--client --output json has correct client info"
kube::test::version::diff_assert "${TEMP}/server_version_test" "ne" "${TEMP}/server_client_only_json_version_test" "--client --output json has no server info"
kube::log::status "Testing kubectl version: compare json output using additional --short flag"
kube::test::version::json_client_server_object_to_file "--short" "clientVersion" "${TEMP}/client_short_json_version_test"
kube::test::version::json_client_server_object_to_file "--short" "serverVersion" "${TEMP}/server_short_json_version_test"
kube::test::version::diff_assert "${TEMP}/client_version_test" "eq" "${TEMP}/client_short_json_version_test" "--short --output client json info is equal to non short result"
kube::test::version::diff_assert "${TEMP}/server_version_test" "eq" "${TEMP}/server_short_json_version_test" "--short --output server json info is equal to non short result"
kube::log::status "Testing kubectl version: compare json output with yaml output"
kube::test::version::json_object_to_file "" "${TEMP}/client_server_json_version_test"
kube::test::version::yaml_object_to_file "" "${TEMP}/client_server_yaml_version_test"
kube::test::version::diff_assert "${TEMP}/client_server_json_version_test" "eq" "${TEMP}/client_server_yaml_version_test" "--output json/yaml has identical information"
}
# Runs all pod related tests.
run_pod_tests() {
kube::log::status "Testing kubectl(v1:pods)"
@ -2819,6 +2861,11 @@ runTests() {
kubectl get "${kube_flags[@]}" -f hack/testdata/kubernetes-service.yaml
fi
#########################
# Kubectl version #
#########################
run_kubectl_version_tests
# Passing no arguments to create is an error
! kubectl create

View File

@ -133,6 +133,7 @@ go_library(
"//vendor:k8s.io/apimachinery/pkg/util/validation/field",
"//vendor:k8s.io/apimachinery/pkg/util/wait",
"//vendor:k8s.io/apimachinery/pkg/util/yaml",
"//vendor:k8s.io/apimachinery/pkg/version",
"//vendor:k8s.io/apimachinery/pkg/watch",
"//vendor:k8s.io/apiserver/pkg/util/flag",
"//vendor:k8s.io/client-go/discovery",

View File

@ -17,17 +17,26 @@ limitations under the License.
package cmd
import (
"encoding/json"
"errors"
"fmt"
"io"
"github.com/ghodss/yaml"
"github.com/spf13/cobra"
apimachineryversion "k8s.io/apimachinery/pkg/version"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/util/i18n"
"k8s.io/kubernetes/pkg/version"
)
type Version struct {
ClientVersion *apimachineryversion.Info `json:"clientVersion,omitempty" yaml:"clientVersion,omitempty"`
ServerVersion *apimachineryversion.Info `json:"serverVersion,omitempty" yaml:"serverVersion,omitempty"`
}
var (
version_example = templates.Examples(`
# Print the client and server versions for the current context
@ -47,36 +56,75 @@ func NewCmdVersion(f cmdutil.Factory, out io.Writer) *cobra.Command {
}
cmd.Flags().BoolP("client", "c", false, "Client version only (no server required).")
cmd.Flags().BoolP("short", "", false, "Print just the version number.")
cmd.Flags().String("output", "", "output format, options available are yaml and json")
cmd.Flags().MarkShorthandDeprecated("client", "please use --client instead.")
return cmd
}
func RunVersion(f cmdutil.Factory, out io.Writer, cmd *cobra.Command) error {
v := fmt.Sprintf("%#v", version.Get())
if cmdutil.GetFlagBool(cmd, "short") {
v = version.Get().GitVersion
var serverVersion *apimachineryversion.Info = nil
var serverErr error = nil
vo := Version{nil, nil}
clientVersion := version.Get()
vo.ClientVersion = &clientVersion
if !cmdutil.GetFlagBool(cmd, "client") {
serverVersion, serverErr = retrieveServerVersion(f)
vo.ServerVersion = serverVersion
}
fmt.Fprintf(out, "Client Version: %s\n", v)
if cmdutil.GetFlagBool(cmd, "client") {
return nil
switch of := cmdutil.GetFlagString(cmd, "output"); of {
case "":
if cmdutil.GetFlagBool(cmd, "short") {
fmt.Fprintf(out, "Client Version: %s\n", clientVersion.GitVersion)
if serverVersion != nil {
fmt.Fprintf(out, "Server Version: %s\n", serverVersion.GitVersion)
}
} else {
fmt.Fprintf(out, "Client Version: %s\n", fmt.Sprintf("%#v", clientVersion))
if serverVersion != nil {
fmt.Fprintf(out, "Server Version: %s\n", fmt.Sprintf("%#v", *serverVersion))
}
}
case "yaml":
y, err := yaml.Marshal(&vo)
if err != nil {
return err
}
fmt.Fprintln(out, string(y))
case "json":
y, err := json.Marshal(&vo)
if err != nil {
return err
}
fmt.Fprintln(out, string(y))
default:
return errors.New("invalid output format: " + of)
}
discoveryclient, err := f.DiscoveryClient()
if err != nil {
return err
if serverErr != nil {
return serverErr
}
serverVersion, err := discoveryclient.ServerVersion()
if err != nil {
return err
}
v = fmt.Sprintf("%#v", *serverVersion)
if cmdutil.GetFlagBool(cmd, "short") {
v = serverVersion.GitVersion
}
fmt.Fprintf(out, "Server Version: %s\n", v)
return nil
}
func retrieveServerVersion(f cmdutil.Factory) (*apimachineryversion.Info, error) {
discoveryClient, err := f.DiscoveryClient()
if err != nil {
return nil, err
}
serverVersion, err := discoveryClient.ServerVersion()
if err != nil {
return nil, err
}
return serverVersion, nil
}