From 0fee1a203e9baeda8c9f53bff4773f22da730222 Mon Sep 17 00:00:00 2001 From: Kamesh Date: Sun, 14 Aug 2022 20:14:24 +0530 Subject: [PATCH] fix: ability to load configuration from stdin fixes: [BUG] Honor stdin for config k3d cluster create -c #1123 --- cmd/util/config/config.go | 25 ++++- cmd/util/iostreams.go | 28 ++++++ tests/test_config_file_from_stdin.sh | 140 +++++++++++++++++++++++++++ 3 files changed, 189 insertions(+), 4 deletions(-) create mode 100644 cmd/util/iostreams.go create mode 100755 tests/test_config_file_from_stdin.sh diff --git a/cmd/util/config/config.go b/cmd/util/config/config.go index c9e406241..e727c3761 100644 --- a/cmd/util/config/config.go +++ b/cmd/util/config/config.go @@ -23,6 +23,7 @@ package config import ( "fmt" + "io/ioutil" "os" "path/filepath" "strings" @@ -31,6 +32,7 @@ import ( "github.com/spf13/viper" "sigs.k8s.io/yaml" + "github.com/k3d-io/k3d/v5/cmd/util" "github.com/k3d-io/k3d/v5/pkg/config" l "github.com/k3d-io/k3d/v5/pkg/logger" ) @@ -46,7 +48,12 @@ func InitViperWithConfigFile(cfgViper *viper.Viper, configFile string) error { // Set config file, if specified if configFile != "" { - if _, err := os.Stat(configFile); err != nil { + streams := util.StandardIOStreams() + //flag to mark from where we read the config + fromStdIn := false + if configFile == "-" { + fromStdIn = true + } else if _, err := os.Stat(configFile); err != nil { l.Log().Fatalf("Failed to stat config file %s: %+v", configFile, err) } @@ -58,10 +65,20 @@ func InitViperWithConfigFile(cfgViper *viper.Viper, configFile string) error { } defer tmpfile.Close() - originalcontent, err := os.ReadFile(configFile) - if err != nil { - l.Log().Fatalf("error reading config file %s: %v", configFile, err) + var originalcontent []byte + if fromStdIn { + // otherwise read from stdin + originalcontent, err = ioutil.ReadAll(streams.In) + if err != nil { + l.Log().Fatalf("Failed to read config file from stdin: %+v", configFile, err) + } + } else { + originalcontent, err = os.ReadFile(configFile) + if err != nil { + l.Log().Fatalf("error reading config file %s: %v", configFile, err) + } } + expandedcontent := os.ExpandEnv(string(originalcontent)) if _, err := tmpfile.WriteString(expandedcontent); err != nil { l.Log().Fatalf("error writing expanded config file contents to temp file %s: %v", tmpfile.Name(), err) diff --git a/cmd/util/iostreams.go b/cmd/util/iostreams.go new file mode 100644 index 000000000..f988bae5a --- /dev/null +++ b/cmd/util/iostreams.go @@ -0,0 +1,28 @@ +package util + +import ( + "io" + "os" +) + +// IOStreams provides the standard names for iostreams. +// This is useful for embedding and for unit testing. +// Inconsistent and different names make it hard to read and review code +// This is based on https://github.com/kubernetes-sigs/kind/blob/main/pkg/cmd/iostreams.go, but just the nice type without the dependency +type IOStreams struct { + // In think, os.Stdin + In io.Reader + // Out think, os.Stdout + Out io.Writer + // ErrOut think, os.Stderr + ErrOut io.Writer +} + +// StandardIOStreams returns an IOStreams from os.Stdin, os.Stdout +func StandardIOStreams() IOStreams { + return IOStreams{ + In: os.Stdin, + Out: os.Stdout, + ErrOut: os.Stderr, + } +} diff --git a/tests/test_config_file_from_stdin.sh b/tests/test_config_file_from_stdin.sh new file mode 100755 index 000000000..394a3c5fe --- /dev/null +++ b/tests/test_config_file_from_stdin.sh @@ -0,0 +1,140 @@ +#!/bin/bash + +CURR_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +[ -d "$CURR_DIR" ] || { echo "FATAL: no current dir (maybe running in zsh?)"; exit 1; } + +# shellcheck source=./common.sh +source "$CURR_DIR/common.sh" + +### Step Setup ### +# Redirect all stdout/stderr output to logfile +LOG_FILE="$TEST_OUTPUT_DIR/$( basename "${BASH_SOURCE[0]}" ).log" +exec >${LOG_FILE} 2>&1 +export LOG_FILE + +# use a kubeconfig file specific to this test +KUBECONFIG="$KUBECONFIG_ROOT/$( basename "${BASH_SOURCE[0]}" ).yaml" +export KUBECONFIG +### Step Setup ### + + +: "${EXTRA_FLAG:=""}" +: "${EXTRA_TITLE:=""}" + +if [[ -n "$K3S_IMAGE" ]]; then + EXTRA_FLAG="--image rancher/k3s:$K3S_IMAGE" + EXTRA_TITLE="(rancher/k3s:$K3S_IMAGE)" +fi + +export CURRENT_STAGE="Test | config-file | $K3S_IMAGE" + +configfileoriginal="$CURR_DIR/assets/config_test_simple.yaml" +configfile="/tmp/config_test_simple-tmp_$(date -u +'%Y%m%dT%H%M%SZ').yaml" +clustername="configtest" + +sed -E "s/^ name:.+/ name: $clustername/g" < "$configfileoriginal" > "$configfile" # replace cluster name in config file so we can use it in this script without running into override issues +cat "$configfile" +highlight "[START] ConfigTest $EXTRA_TITLE" + +info "Creating cluster $clustername..." + +cat <