Example #1
0
// TODO: this test is largely cut and paste, refactor to share code
func TestRequestAttachRemoteCommand(t *testing.T) {
	testCases := []struct {
		Stdin  string
		Stdout string
		Stderr string
		Error  string
		Tty    bool
	}{
		{
			Error: "bail",
		},
		{
			Stdin:  "a",
			Stdout: "b",
			Stderr: "c",
		},
		{
			Stdin:  "a",
			Stdout: "b",
			Tty:    true,
		},
	}

	for i, testCase := range testCases {
		localOut := &bytes.Buffer{}
		localErr := &bytes.Buffer{}

		server := httptest.NewServer(fakeExecServer(t, i, testCase.Stdin, testCase.Stdout, testCase.Stderr, testCase.Error, testCase.Tty, 1))

		url, _ := url.ParseRequestURI(server.URL)
		c := restclient.NewRESTClient(url, "", restclient.ContentConfig{GroupVersion: &unversioned.GroupVersion{Group: "x"}}, -1, -1, nil)
		req := c.Post().Resource("testing")

		conf := &restclient.Config{
			Host: server.URL,
		}
		e, err := NewExecutor(conf, "POST", req.URL())
		if err != nil {
			t.Errorf("%d: unexpected error: %v", i, err)
			continue
		}
		err = e.Stream(strings.NewReader(testCase.Stdin), localOut, localErr, testCase.Tty)
		hasErr := err != nil

		if len(testCase.Error) > 0 {
			if !hasErr {
				t.Errorf("%d: expected an error", i)
			} else {
				if e, a := testCase.Error, err.Error(); !strings.Contains(a, e) {
					t.Errorf("%d: expected error stream read '%v', got '%v'", i, e, a)
				}
			}

			// TODO: Uncomment when fix #19254
			// server.Close()
			continue
		}

		if hasErr {
			t.Errorf("%d: unexpected error: %v", i, err)
			// TODO: Uncomment when fix #19254
			// server.Close()
			continue
		}

		if len(testCase.Stdout) > 0 {
			if e, a := testCase.Stdout, localOut; e != a.String() {
				t.Errorf("%d: expected stdout data '%s', got '%s'", i, e, a)
			}
		}

		if testCase.Stderr != "" {
			if e, a := testCase.Stderr, localErr; e != a.String() {
				t.Errorf("%d: expected stderr data '%s', got '%s'", i, e, a)
			}
		}

		// TODO: Uncomment when fix #19254
		// server.Close()
	}
}
Example #2
0
func TestStream(t *testing.T) {
	testCases := []struct {
		TestName        string
		Stdin           string
		Stdout          string
		Stderr          string
		Error           string
		Tty             bool
		MessageCount    int
		ClientProtocols []string
		ServerProtocols []string
	}{
		{
			TestName:        "error",
			Error:           "bail",
			Stdout:          "a",
			ClientProtocols: []string{remotecommand.StreamProtocolV2Name},
			ServerProtocols: []string{remotecommand.StreamProtocolV2Name},
		},
		{
			TestName:        "in/out/err",
			Stdin:           "a",
			Stdout:          "b",
			Stderr:          "c",
			MessageCount:    100,
			ClientProtocols: []string{remotecommand.StreamProtocolV2Name},
			ServerProtocols: []string{remotecommand.StreamProtocolV2Name},
		},
		{
			TestName:        "in/out/tty",
			Stdin:           "a",
			Stdout:          "b",
			Tty:             true,
			MessageCount:    100,
			ClientProtocols: []string{remotecommand.StreamProtocolV2Name},
			ServerProtocols: []string{remotecommand.StreamProtocolV2Name},
		},
		{
			// 1.0 kubectl, 1.0 kubelet
			TestName:        "unversioned client, unversioned server",
			Stdout:          "b",
			Stderr:          "c",
			MessageCount:    1,
			ClientProtocols: []string{},
			ServerProtocols: []string{},
		},
		{
			// 1.0 kubectl, 1.1+ kubelet
			TestName:        "unversioned client, versioned server",
			Stdout:          "b",
			Stderr:          "c",
			MessageCount:    1,
			ClientProtocols: []string{},
			ServerProtocols: []string{remotecommand.StreamProtocolV2Name, remotecommand.StreamProtocolV1Name},
		},
		{
			// 1.1+ kubectl, 1.0 kubelet
			TestName:        "versioned client, unversioned server",
			Stdout:          "b",
			Stderr:          "c",
			MessageCount:    1,
			ClientProtocols: []string{remotecommand.StreamProtocolV2Name, remotecommand.StreamProtocolV1Name},
			ServerProtocols: []string{},
		},
	}

	for _, testCase := range testCases {
		for _, exec := range []bool{true, false} {
			var name string
			if exec {
				name = testCase.TestName + " (exec)"
			} else {
				name = testCase.TestName + " (attach)"
			}
			var (
				streamIn             io.Reader
				streamOut, streamErr io.Writer
			)
			localOut := &bytes.Buffer{}
			localErr := &bytes.Buffer{}

			server := httptest.NewServer(fakeServer(t, name, exec, testCase.Stdin, testCase.Stdout, testCase.Stderr, testCase.Error, testCase.Tty, testCase.MessageCount, testCase.ServerProtocols))

			url, _ := url.ParseRequestURI(server.URL)
			config := restclient.ContentConfig{
				GroupVersion:         &schema.GroupVersion{Group: "x"},
				NegotiatedSerializer: testapi.Default.NegotiatedSerializer(),
			}
			c, err := restclient.NewRESTClient(url, "", config, -1, -1, nil, nil)
			if err != nil {
				t.Fatalf("failed to create a client: %v", err)
			}
			req := c.Post().Resource("testing")

			if exec {
				req.Param("command", "ls")
				req.Param("command", "/")
			}

			if len(testCase.Stdin) > 0 {
				req.Param(api.ExecStdinParam, "1")
				streamIn = strings.NewReader(strings.Repeat(testCase.Stdin, testCase.MessageCount))
			}

			if len(testCase.Stdout) > 0 {
				req.Param(api.ExecStdoutParam, "1")
				streamOut = localOut
			}

			if testCase.Tty {
				req.Param(api.ExecTTYParam, "1")
			} else if len(testCase.Stderr) > 0 {
				req.Param(api.ExecStderrParam, "1")
				streamErr = localErr
			}

			conf := &restclient.Config{
				Host: server.URL,
			}
			e, err := NewExecutor(conf, "POST", req.URL())
			if err != nil {
				t.Errorf("%s: unexpected error: %v", name, err)
				continue
			}
			err = e.Stream(StreamOptions{
				SupportedProtocols: testCase.ClientProtocols,
				Stdin:              streamIn,
				Stdout:             streamOut,
				Stderr:             streamErr,
				Tty:                testCase.Tty,
			})
			hasErr := err != nil

			if len(testCase.Error) > 0 {
				if !hasErr {
					t.Errorf("%s: expected an error", name)
				} else {
					if e, a := testCase.Error, err.Error(); !strings.Contains(a, e) {
						t.Errorf("%s: expected error stream read %q, got %q", name, e, a)
					}
				}

				server.Close()
				continue
			}

			if hasErr {
				t.Errorf("%s: unexpected error: %v", name, err)
				server.Close()
				continue
			}

			if len(testCase.Stdout) > 0 {
				if e, a := strings.Repeat(testCase.Stdout, testCase.MessageCount), localOut; e != a.String() {
					t.Errorf("%s: expected stdout data %q, got %q", name, e, a)
				}
			}

			if testCase.Stderr != "" {
				if e, a := strings.Repeat(testCase.Stderr, testCase.MessageCount), localErr; e != a.String() {
					t.Errorf("%s: expected stderr data %q, got %q", name, e, a)
				}
			}

			server.Close()
		}
	}
}
Example #3
0
func TestRequestExecuteRemoteCommand(t *testing.T) {
	testCases := []struct {
		Stdin        string
		Stdout       string
		Stderr       string
		Error        string
		Tty          bool
		MessageCount int
	}{
		{
			Error: "bail",
		},
		{
			Stdin:  "a",
			Stdout: "b",
			Stderr: "c",
			// TODO bump this to a larger number such as 100 once
			// https://github.com/docker/spdystream/issues/55 is fixed and the Godep
			// is bumped. Sending multiple messages over stdin/stdout/stderr results
			// in more frames being spread across multiple spdystream frame workers.
			// This makes it more likely that the spdystream bug will be encountered,
			// where streams are closed as soon as a goaway frame is received, and
			// any pending frames that haven't been processed yet may not be
			// delivered (it's a race).
			MessageCount: 1,
		},
		{
			Stdin:  "a",
			Stdout: "b",
			Tty:    true,
		},
	}

	for i, testCase := range testCases {
		localOut := &bytes.Buffer{}
		localErr := &bytes.Buffer{}

		server := httptest.NewServer(fakeExecServer(t, i, testCase.Stdin, testCase.Stdout, testCase.Stderr, testCase.Error, testCase.Tty, testCase.MessageCount))

		url, _ := url.ParseRequestURI(server.URL)
		c := restclient.NewRESTClient(url, "", restclient.ContentConfig{GroupVersion: &unversioned.GroupVersion{Group: "x"}}, -1, -1, nil)
		req := c.Post().Resource("testing")
		req.SetHeader(httpstream.HeaderProtocolVersion, StreamProtocolV2Name)
		req.Param("command", "ls")
		req.Param("command", "/")
		conf := &restclient.Config{
			Host: server.URL,
		}
		e, err := NewExecutor(conf, "POST", req.URL())
		if err != nil {
			t.Errorf("%d: unexpected error: %v", i, err)
			continue
		}
		err = e.Stream(strings.NewReader(strings.Repeat(testCase.Stdin, testCase.MessageCount)), localOut, localErr, testCase.Tty)
		hasErr := err != nil

		if len(testCase.Error) > 0 {
			if !hasErr {
				t.Errorf("%d: expected an error", i)
			} else {
				if e, a := testCase.Error, err.Error(); !strings.Contains(a, e) {
					t.Errorf("%d: expected error stream read '%v', got '%v'", i, e, a)
				}
			}

			// TODO: Uncomment when fix #19254
			// server.Close()
			continue
		}

		if hasErr {
			t.Errorf("%d: unexpected error: %v", i, err)
			// TODO: Uncomment when fix #19254
			// server.Close()
			continue
		}

		if len(testCase.Stdout) > 0 {
			if e, a := strings.Repeat(testCase.Stdout, testCase.MessageCount), localOut; e != a.String() {
				t.Errorf("%d: expected stdout data '%s', got '%s'", i, e, a)
			}
		}

		if testCase.Stderr != "" {
			if e, a := strings.Repeat(testCase.Stderr, testCase.MessageCount), localErr; e != a.String() {
				t.Errorf("%d: expected stderr data '%s', got '%s'", i, e, a)
			}
		}

		// TODO: Uncomment when fix #19254
		// server.Close()
	}
}