Merge pull request #2246 from lavalamp/fix2

Fix unversioned output being passed to -template
This commit is contained in:
Joe Beda 2014-11-07 16:59:37 -08:00
commit 0ee7d5cc75
13 changed files with 123 additions and 60 deletions

View File

@ -92,7 +92,7 @@ function kube-up {
local count="0"
until [[ "$count" == "1" ]]; do
local minions
minions=$("${KUBE_ROOT}/cluster/kubecfg.sh" -template '{{range.Items}}{{.Name}}:{{end}}' list minions)
minions=$("${KUBE_ROOT}/cluster/kubecfg.sh" -template '{{range.items}}{{.id}}:{{end}}' list minions)
count=$(echo $minions | grep -c "${MINION_NAMES[i]}") || {
printf "."
sleep 2

View File

@ -33,7 +33,7 @@ detect-master > /dev/null
detect-minions > /dev/null
MINIONS_FILE=/tmp/minions
"${KUBE_ROOT}/cluster/kubecfg.sh" -template $'{{range.Items}}{{.Name}}\n{{end}}' list minions > ${MINIONS_FILE}
"${KUBE_ROOT}/cluster/kubecfg.sh" -template $'{{range.items}}{{.id}}\n{{end}}' list minions > ${MINIONS_FILE}
# On vSphere, use minion IPs as their names
if [[ "${KUBERNETES_PROVIDER}" == "vsphere" ]]; then

View File

@ -26,7 +26,6 @@ import (
"sort"
"strconv"
"strings"
"text/template"
"time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
@ -324,14 +323,12 @@ func getPrinter() kubecfg.ResourcePrinter {
} else {
data = []byte(*templateStr)
}
tmpl, err := template.New("output").Parse(string(data))
var err error
printer, err = kubecfg.NewTemplatePrinter(data)
if err != nil {
glog.Fatalf("Error parsing template %s, %v\n", string(data), err)
glog.Fatalf("Error '%v' parsing template:\n'%s'", err, string(data))
return nil
}
printer = &kubecfg.TemplatePrinter{
Template: tmpl,
}
default:
printer = humanReadablePrinter()
}

View File

@ -37,7 +37,7 @@ function teardown() {
trap "teardown" EXIT
pod_id_list=$($KUBECFG '-template={{range.Items}}{{.Name}} {{end}}' -l replicationController=my-hostname list pods)
pod_id_list=$($KUBECFG '-template={{range.items}}{{.id}} {{end}}' -l replicationController=my-hostname list pods)
# Pod turn up on a clean cluster can take a while for the docker image pull.
all_running=0
for i in $(seq 1 24); do
@ -45,7 +45,7 @@ for i in $(seq 1 24); do
sleep 5
all_running=1
for id in $pod_id_list; do
current_status=$($KUBECFG -template '{{.CurrentState.Status}}' get pods/$id) || true
current_status=$($KUBECFG -template '{{.currentState.status}}' get pods/$id) || true
if [[ "$current_status" != "Running" ]]; then
all_running=0
break
@ -69,7 +69,7 @@ sleep 5
# Verify that something is listening.
for id in ${pod_id_list}; do
ip=$($KUBECFG -template '{{.CurrentState.HostIP}}' get pods/$id)
ip=$($KUBECFG -template '{{.currentState.hostIP}}' get pods/$id)
echo "Trying to reach server that should be running at ${ip}:8080..."
ok=0
for i in $(seq 1 5); do

View File

@ -35,7 +35,7 @@ $KUBECFG -c "${GUESTBOOK}/redis-slave-controller.json" create /replicationContro
sleep 5
POD_LIST_1=$($KUBECFG '-template={{range.Items}}{{.Name}} {{end}}' list pods)
POD_LIST_1=$($KUBECFG '-template={{range.items}}{{.id}} {{end}}' list pods)
echo "Pods running: ${POD_LIST_1}"
$KUBECFG stop redisSlaveController
@ -45,7 +45,7 @@ $KUBECFG rm redisSlaveController
$KUBECFG delete services/redismaster
$KUBECFG delete pods/redis-master-2
POD_LIST_2=$($KUBECFG '-template={{range.Items}}{{.Name}} {{end}}' list pods)
POD_LIST_2=$($KUBECFG '-template={{range.items}}{{.id}} {{end}}' list pods)
echo "Pods running after shutdown: ${POD_LIST_2}"
exit 0

View File

@ -69,7 +69,7 @@ function query_pods() {
local i
for i in $(seq 1 10); do
pods_unsorted=($(${KUBECFG} \
'-template={{range.Items}}{{.Name}} {{end}}' \
'-template={{range.items}}{{.id}} {{end}}' \
-l name="$1" list pods))
found="${#pods_unsorted[*]}"
if [[ "${found}" == "$2" ]]; then
@ -103,7 +103,7 @@ function wait_for_pods() {
echo "Waiting for ${pods_needed} pods to become 'running'"
pods_needed="$2"
for id in ${pods_sorted}; do
status=$(${KUBECFG} -template '{{.CurrentState.Status}}' get "pods/${id}")
status=$(${KUBECFG} -template '{{.currentState.status}}' get "pods/${id}")
if [[ "${status}" == "Running" ]]; then
pods_needed=$((pods_needed-1))
fi
@ -213,9 +213,9 @@ svc1_pods=$(query_pods "${svc1_name}" "${svc1_count}")
svc2_pods=$(query_pods "${svc2_name}" "${svc2_count}")
# Get the portal IPs.
svc1_ip=$(${KUBECFG} -template '{{.PortalIP}}' get "services/${svc1_name}")
svc1_ip=$(${KUBECFG} -template '{{.portalIP}}' get "services/${svc1_name}")
test -n "${svc1_ip}" || error "Service1 IP is blank"
svc2_ip=$(${KUBECFG} -template '{{.PortalIP}}' get "services/${svc2_name}")
svc2_ip=$(${KUBECFG} -template '{{.portalIP}}' get "services/${svc2_name}")
test -n "${svc2_ip}" || error "Service2 IP is blank"
if [[ "${svc1_ip}" == "${svc2_ip}" ]]; then
error "Portal IPs conflict: ${svc1_ip}"
@ -272,7 +272,7 @@ wait_for_pods "${svc3_name}" "${svc3_count}"
svc3_pods=$(query_pods "${svc3_name}" "${svc3_count}")
# Get the portal IP.
svc3_ip=$(${KUBECFG} -template '{{.PortalIP}}' get "services/${svc3_name}")
svc3_ip=$(${KUBECFG} -template '{{.portalIP}}' get "services/${svc3_name}")
test -n "${svc3_ip}" || error "Service3 IP is blank"
if [[ "${svc3_ip}" != "${svc1_ip}" ]]; then
error "Portal IPs not resued: ${svc3_ip} != ${svc1_ip}"
@ -325,7 +325,7 @@ wait_for_pods "${svc4_name}" "${svc4_count}"
svc4_pods=$(query_pods "${svc4_name}" "${svc4_count}")
# Get the portal IP.
svc4_ip=$(${KUBECFG} -template '{{.PortalIP}}' get "services/${svc4_name}")
svc4_ip=$(${KUBECFG} -template '{{.portalIP}}' get "services/${svc4_name}")
test -n "${svc4_ip}" || error "Service4 IP is blank"
if [[ "${svc4_ip}" == "${svc2_ip}" || "${svc4_ip}" == "${svc3_ip}" ]]; then
error "Portal IPs conflict: ${svc4_ip}"

View File

@ -38,7 +38,7 @@ function validate() {
sleep 2
local pod_id_list
pod_id_list=($($KUBECFG -template='{{range.Items}}{{.Name}} {{end}}' -l name="${CONTROLLER_NAME}" list pods))
pod_id_list=($($KUBECFG -template='{{range.items}}{{.id}} {{end}}' -l name="${CONTROLLER_NAME}" list pods))
echo " ${#pod_id_list[@]} out of ${num_replicas} created"
@ -61,7 +61,7 @@ function validate() {
# currently always set to a zero time.
#
# You can read about the syntax here: http://golang.org/pkg/text/template/
template_string="{{and ((index .CurrentState.Info \"${CONTROLLER_NAME}\").State.Running) .CurrentState.Info.net.State.Running}}"
template_string="{{and ((index .currentState.info \"${CONTROLLER_NAME}\").state.running.startedAt) .currentState.info.net.state.running.startedAt}}"
current_status=$($KUBECFG -template="${template_string}" get "pods/$id") || {
if [[ $current_status =~ "pod \"${id}\" not found" ]]; then
echo " $id no longer exists"
@ -73,12 +73,12 @@ function validate() {
fi
}
if [[ "$current_status" != "{0001-01-01 00:00:00 +0000 UTC}" ]]; then
if [[ "$current_status" != "0001-01-01T00:00:00Z" ]]; then
echo " $id is created but not running"
continue
fi
template_string="{{(index .CurrentState.Info \"${CONTROLLER_NAME}\").Image}}"
template_string="{{(index .currentState.info \"${CONTROLLER_NAME}\").image}}"
current_image=$($KUBECFG -template="${template_string}" get "pods/$id")
if [[ "$current_image" != "${DOCKER_HUB_USER}/update-demo:${container_image_version}" ]]; then
echo " ${id} is created but running wrong image"
@ -86,7 +86,7 @@ function validate() {
fi
host_ip=$($KUBECFG -template='{{.CurrentState.HostIP}}' get pods/$id)
host_ip=$($KUBECFG -template='{{.currentState.hostIP}}' get pods/$id)
curl -s --max-time 5 --fail http://${host_ip}:8080/data.json \
| grep -q ${container_image_version} || {
echo " ${id} is running the right image but curl to contents failed or returned wrong info"

View File

@ -40,6 +40,9 @@ var (
tests = flag.String("tests", "", "Run only tests in hack/e2e-suite matching this glob. Ignored if -test is set.")
root = flag.String("root", absOrDie(filepath.Clean(filepath.Join(path.Base(os.Args[0]), ".."))), "Root directory of kubernetes repository.")
verbose = flag.Bool("v", false, "If true, print all command output.")
cfgCmd = flag.String("cfg", "", "If nonempty, pass this as an argument, and call kubecfg. Implies -v.")
ctlCmd = flag.String("ctl", "", "If nonempty, pass this as an argument, and call kubectl. Implies -v. (-test, -cfg, -ctl are mutually exclusive)")
)
var signals = make(chan os.Signal, 100)
@ -87,18 +90,24 @@ func main() {
}
}
failed, passed := []string{}, []string{}
if *tests != "" {
failed, passed = Test()
failure := false
switch {
case *cfgCmd != "":
failure = !runBash("'kubecfg "+*cfgCmd+"'", "$KUBECFG "+*cfgCmd)
case *ctlCmd != "":
failure = !runBash("'kubectl "+*ctlCmd+"'", "$KUBECFG "+*ctlCmd)
case *tests != "":
failed, passed := Test()
log.Printf("Passed tests: %v", passed)
log.Printf("Failed tests: %v", failed)
failure = len(failed) > 0
}
if *down {
TearDown()
}
log.Printf("Passed tests: %v", passed)
log.Printf("Failed tests: %v", failed)
if len(failed) > 0 {
if failure {
os.Exit(1)
}
}

View File

@ -100,12 +100,12 @@ kube::log::status "Testing kubectl(pods)"
"${kube_cmd[@]}" create -f examples/guestbook/redis-master.json "${kube_flags[@]}"
"${kube_cmd[@]}" get pods "${kube_flags[@]}"
"${kube_cmd[@]}" get pod redis-master-2 "${kube_flags[@]}"
[[ "$("${kube_cmd[@]}" get pod redis-master-2 -o template --output-version=v1beta1 -t '{{ .ID }}' "${kube_flags[@]}")" == "redis-master-2" ]]
[[ "$("${kube_cmd[@]}" get pod redis-master-2 -o template --output-version=v1beta1 -t '{{ .id }}' "${kube_flags[@]}")" == "redis-master-2" ]]
output_pod=$("${kube_cmd[@]}" get pod redis-master-2 -o json --output-version=v1beta1 "${kube_flags[@]}")
"${kube_cmd[@]}" delete pod redis-master-2 "${kube_flags[@]}"
[[ $("${kube_cmd[@]}" get pods -o template -t '{{ len .Items }}' "${kube_flags[@]}") -eq 0 ]]
[[ $("${kube_cmd[@]}" get pods -o template -t '{{ len .items }}' "${kube_flags[@]}") -eq 0 ]]
echo $output_pod | "${kube_cmd[@]}" create -f - "${kube_flags[@]}"
[[ $("${kube_cmd[@]}" get pods -o template -t '{{ len .Items }}' "${kube_flags[@]}") -eq 1 ]]
[[ $("${kube_cmd[@]}" get pods -o template -t '{{ len .items }}' "${kube_flags[@]}") -eq 1 ]]
"${kube_cmd[@]}" get pods -o yaml "${kube_flags[@]}" | grep -q "id: redis-master-2"
"${kube_cmd[@]}" describe pod redis-master-2 "${kube_flags[@]}" | grep -q 'Name:.*redis-master-2'
"${kube_cmd[@]}" delete -f examples/guestbook/redis-master.json "${kube_flags[@]}"

View File

@ -319,19 +319,32 @@ func (h *HumanReadablePrinter) PrintObj(obj runtime.Object, output io.Writer) er
// TemplatePrinter is an implementation of ResourcePrinter which formats data with a Go Template.
type TemplatePrinter struct {
Template *template.Template
template *template.Template
}
func NewTemplatePrinter(tmpl []byte) (*TemplatePrinter, error) {
t, err := template.New("output").Parse(string(tmpl))
if err != nil {
return nil, err
}
return &TemplatePrinter{t}, nil
}
// Print parses the data as JSON, and re-formats it with the Go Template.
func (t *TemplatePrinter) Print(data []byte, w io.Writer) error {
obj, err := latest.Codec.Decode(data)
obj := map[string]interface{}{}
err := json.Unmarshal(data, &obj)
if err != nil {
return err
}
return t.PrintObj(obj, w)
return t.template.Execute(w, obj)
}
// PrintObj formats the obj with the Go Template.
func (t *TemplatePrinter) PrintObj(obj runtime.Object, w io.Writer) error {
return t.Template.Execute(w, obj)
data, err := latest.Codec.Encode(obj)
if err != nil {
return err
}
return t.Print(data, w)
}

View File

@ -161,3 +161,19 @@ func TestUnknownTypePrinting(t *testing.T) {
t.Errorf("An error was expected from printing unknown type")
}
}
func TestTemplateEmitsVersionedObjects(t *testing.T) {
// kind is always blank in memory and set on the wire
printer, err := NewTemplatePrinter([]byte(`{{.kind}}`))
if err != nil {
t.Fatalf("tmpl fail: %v", err)
}
buffer := &bytes.Buffer{}
err = printer.PrintObj(&api.Pod{}, buffer)
if err != nil {
t.Fatalf("print fail: %v", err)
}
if e, a := "Pod", string(buffer.Bytes()); e != a {
t.Errorf("Expected %v, got %v", e, a)
}
}

View File

@ -28,6 +28,7 @@ import (
"text/template"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/golang/glog"
@ -45,35 +46,26 @@ func GetPrinter(format, templateFile string, defaultPrinter ResourcePrinter) (Re
case "yaml":
printer = &YAMLPrinter{}
case "template":
var data []byte
if len(templateFile) == 0 {
return nil, false, fmt.Errorf("template format specified but no template given")
}
tmpl, err := template.New("output").Parse(templateFile)
var err error
printer, err = NewTemplatePrinter([]byte(templateFile))
if err != nil {
return nil, false, fmt.Errorf("error parsing template %s, %v\n", string(data), err)
}
printer = &TemplatePrinter{
Template: tmpl,
return nil, false, fmt.Errorf("error parsing template %s, %v\n", templateFile, err)
}
case "templatefile":
var data []byte
if len(templateFile) > 0 {
var err error
data, err = ioutil.ReadFile(templateFile)
if err != nil {
return nil, false, fmt.Errorf("error reading template %s, %v\n", templateFile, err)
}
} else {
if len(templateFile) == 0 {
return nil, false, fmt.Errorf("templatefile format specified but no template file given")
}
tmpl, err := template.New("output").Parse(string(data))
data, err := ioutil.ReadFile(templateFile)
if err != nil {
return nil, false, fmt.Errorf("error reading template %s, %v\n", templateFile, err)
}
printer, err = NewTemplatePrinter(data)
if err != nil {
return nil, false, fmt.Errorf("error parsing template %s, %v\n", string(data), err)
}
printer = &TemplatePrinter{
Template: tmpl,
}
case "":
printer = defaultPrinter
versioned = false
@ -323,12 +315,29 @@ func (h *HumanReadablePrinter) PrintObj(obj runtime.Object, output io.Writer) er
// TemplatePrinter is an implementation of ResourcePrinter which formats data with a Go Template.
type TemplatePrinter struct {
Template *template.Template
template *template.Template
}
func NewTemplatePrinter(tmpl []byte) (*TemplatePrinter, error) {
t, err := template.New("output").Parse(string(tmpl))
if err != nil {
return nil, err
}
return &TemplatePrinter{t}, nil
}
// PrintObj formats the obj with the Go Template.
func (t *TemplatePrinter) PrintObj(obj runtime.Object, w io.Writer) error {
return t.Template.Execute(w, obj)
data, err := latest.Codec.Encode(obj)
if err != nil {
return err
}
outObj := map[string]interface{}{}
err = json.Unmarshal(data, &outObj)
if err != nil {
return err
}
return t.template.Execute(w, outObj)
}
func tabbedString(f func(*tabwriter.Writer) error) (string, error) {

View File

@ -86,14 +86,17 @@ func TestPrintYAML(t *testing.T) {
func TestPrintTemplate(t *testing.T) {
buf := bytes.NewBuffer([]byte{})
printer, versioned, err := GetPrinter("template", "{{ .Name }}", nil)
printer, versioned, err := GetPrinter("template", "{{.id}}", nil)
if err != nil {
t.Errorf("unexpected error: %#v", err)
t.Fatalf("unexpected error: %#v", err)
}
if !versioned {
t.Errorf("printer should be versioned")
}
printer.PrintObj(&api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, buf)
err = printer.PrintObj(&api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, buf)
if err != nil {
t.Fatalf("unexpected error: %#v", err)
}
if buf.String() != "foo" {
t.Errorf("unexpected output: %s", buf.String())
}
@ -204,3 +207,19 @@ func TestUnknownTypePrinting(t *testing.T) {
t.Errorf("An error was expected from printing unknown type")
}
}
func TestTemplateEmitsVersionedObjects(t *testing.T) {
// kind is always blank in memory and set on the wire
printer, err := NewTemplatePrinter([]byte(`{{.kind}}`))
if err != nil {
t.Fatalf("tmpl fail: %v", err)
}
buffer := &bytes.Buffer{}
err = printer.PrintObj(&api.Pod{}, buffer)
if err != nil {
t.Fatalf("print fail: %v", err)
}
if e, a := "Pod", string(buffer.Bytes()); e != a {
t.Errorf("Expected %v, got %v", e, a)
}
}