mirror of https://github.com/linkerd/linkerd2.git
Modify inject to warn when file is un-injectable (#1603)
If an input file is un-injectable, existing inject behavior is to simply output a copy of the input. Introduce a report, printed to stderr, that communicates the end state of the inject command. Currently this includes checking for hostNetwork and unsupported resources. Malformed YAML documents will continue to cause no YAML output, and return error code 1. This change also modifies integration tests to handle stdout and stderr separately. example outputs... some pods injected, none with host networking: ``` hostNetwork: pods do not use host networking...............................[ok] supported: at least one resource injected..................................[ok] Summary: 4 of 8 YAML document(s) injected deploy/emoji deploy/voting deploy/web deploy/vote-bot ``` some pods injected, one host networking: ``` hostNetwork: pods do not use host networking...............................[warn] -- deploy/vote-bot uses "hostNetwork: true" supported: at least one resource injected..................................[ok] Summary: 3 of 8 YAML document(s) injected deploy/emoji deploy/voting deploy/web ``` no pods injected: ``` hostNetwork: pods do not use host networking...............................[warn] -- deploy/emoji, deploy/voting, deploy/web, deploy/vote-bot use "hostNetwork: true" supported: at least one resource injected..................................[warn] -- no supported objects found Summary: 0 of 8 YAML document(s) injected ``` TODO: check for UDP and other init containers Part of #1516 Signed-off-by: Andrew Seigner <siggy@buoyant.io>
This commit is contained in:
parent
828ea29321
commit
c5a719da47
|
@ -10,8 +10,6 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
lineWidth = 80
|
||||
okStatus = "[ok]"
|
||||
retryStatus = "[retry]"
|
||||
failStatus = "[FAIL]"
|
||||
)
|
||||
|
|
|
@ -32,6 +32,10 @@ const (
|
|||
ControlPlanePodName = "controller"
|
||||
// The name of the variable used to pass the pod's namespace.
|
||||
PodNamespaceEnvVarName = "LINKERD2_PROXY_POD_NAMESPACE"
|
||||
|
||||
// for inject reports
|
||||
hostNetworkDesc = "hostNetwork: pods do not use host networking"
|
||||
unsupportedDesc = "supported: at least one resource injected"
|
||||
)
|
||||
|
||||
type injectOptions struct {
|
||||
|
@ -42,6 +46,17 @@ type injectOptions struct {
|
|||
*proxyConfigOptions
|
||||
}
|
||||
|
||||
type injectReport struct {
|
||||
name string
|
||||
hostNetwork bool
|
||||
unsupportedResource bool
|
||||
}
|
||||
|
||||
// objMeta provides a generic struct to parse the names of Kubernetes objects
|
||||
type objMeta struct {
|
||||
metaV1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||
}
|
||||
|
||||
func newInjectOptions() *injectOptions {
|
||||
return &injectOptions{
|
||||
inboundPort: 4143,
|
||||
|
@ -117,14 +132,19 @@ func read(path string) ([]io.Reader, error) {
|
|||
// Returns the integer representation of os.Exit code; 0 on success and 1 on failure.
|
||||
func runInjectCmd(inputs []io.Reader, errWriter, outWriter io.Writer, options *injectOptions) int {
|
||||
postInjectBuf := &bytes.Buffer{}
|
||||
reportBuf := &bytes.Buffer{}
|
||||
|
||||
for _, input := range inputs {
|
||||
err := InjectYAML(input, postInjectBuf, options)
|
||||
err := InjectYAML(input, postInjectBuf, reportBuf, options)
|
||||
if err != nil {
|
||||
fmt.Fprintf(errWriter, "Error injecting linkerd proxy: %v\n", err)
|
||||
return 1
|
||||
}
|
||||
_, err = io.Copy(outWriter, postInjectBuf)
|
||||
|
||||
// print error report after yaml output, for better visibility
|
||||
io.Copy(errWriter, reportBuf)
|
||||
|
||||
if err != nil {
|
||||
fmt.Fprintf(errWriter, "Error printing YAML: %v\n", err)
|
||||
return 1
|
||||
|
@ -156,11 +176,12 @@ func injectObjectMeta(t *metaV1.ObjectMeta, k8sLabels map[string]string, options
|
|||
* and init-container injected. If the pod is unsuitable for having them
|
||||
* injected, return false.
|
||||
*/
|
||||
func injectPodSpec(t *v1.PodSpec, identity k8s.TLSIdentity, controlPlaneDNSNameOverride string, options *injectOptions) bool {
|
||||
func injectPodSpec(t *v1.PodSpec, identity k8s.TLSIdentity, controlPlaneDNSNameOverride string, options *injectOptions, report *injectReport) bool {
|
||||
// Pods with `hostNetwork=true` share a network namespace with the host. The
|
||||
// init-container would destroy the iptables configuration on the host, so
|
||||
// skip the injection in this case.
|
||||
if t.HostNetwork {
|
||||
report.hostNetwork = true
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -332,9 +353,11 @@ func injectPodSpec(t *v1.PodSpec, identity k8s.TLSIdentity, controlPlaneDNSNameO
|
|||
}
|
||||
|
||||
// InjectYAML takes an input stream of YAML, outputting injected YAML to out.
|
||||
func InjectYAML(in io.Reader, out io.Writer, options *injectOptions) error {
|
||||
func InjectYAML(in io.Reader, out io.Writer, report io.Writer, options *injectOptions) error {
|
||||
reader := yamlDecoder.NewYAMLReader(bufio.NewReaderSize(in, 4096))
|
||||
|
||||
injectReports := []injectReport{}
|
||||
|
||||
// Iterate over all YAML objects in the input
|
||||
for {
|
||||
// Read a single YAML object
|
||||
|
@ -346,19 +369,24 @@ func InjectYAML(in io.Reader, out io.Writer, options *injectOptions) error {
|
|||
return err
|
||||
}
|
||||
|
||||
result, err := injectResource(bytes, options)
|
||||
ir := injectReport{}
|
||||
result, err := injectResource(bytes, options, &ir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out.Write(result)
|
||||
out.Write([]byte("---\n"))
|
||||
|
||||
injectReports = append(injectReports, ir)
|
||||
}
|
||||
|
||||
generateReport(injectReports, report)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func injectList(b []byte, options *injectOptions) ([]byte, error) {
|
||||
func injectList(b []byte, options *injectOptions, report *injectReport) ([]byte, error) {
|
||||
var sourceList v1.List
|
||||
if err := yaml.Unmarshal(b, &sourceList); err != nil {
|
||||
return nil, err
|
||||
|
@ -367,7 +395,7 @@ func injectList(b []byte, options *injectOptions) ([]byte, error) {
|
|||
items := []runtime.RawExtension{}
|
||||
|
||||
for _, item := range sourceList.Items {
|
||||
result, err := injectResource(item.Raw, options)
|
||||
result, err := injectResource(item.Raw, options, report)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -387,8 +415,8 @@ func injectList(b []byte, options *injectOptions) ([]byte, error) {
|
|||
return yaml.Marshal(sourceList)
|
||||
}
|
||||
|
||||
func injectResource(bytes []byte, options *injectOptions) ([]byte, error) {
|
||||
// The Kuberentes API is versioned and each version has an API modeled
|
||||
func injectResource(bytes []byte, options *injectOptions, report *injectReport) ([]byte, error) {
|
||||
// The Kubernetes API is versioned and each version has an API modeled
|
||||
// with its own distinct Go types. If we tell `yaml.Unmarshal()` which
|
||||
// version we support then it will provide a representation of that
|
||||
// object using the given type if possible. However, it only allows us
|
||||
|
@ -405,6 +433,13 @@ func injectResource(bytes []byte, options *injectOptions) ([]byte, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// retrieve the `metadata/name` field for reporting later
|
||||
var om objMeta
|
||||
if err := yaml.Unmarshal(bytes, &om); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
report.name = fmt.Sprintf("%s/%s", strings.ToLower(meta.Kind), om.Name)
|
||||
|
||||
// obj and podTemplateSpec will reference zero or one the following
|
||||
// objects, depending on the type.
|
||||
var obj interface{}
|
||||
|
@ -510,7 +545,9 @@ func injectResource(bytes []byte, options *injectOptions) ([]byte, error) {
|
|||
// Lists are a little different than the other types. There's no immediate
|
||||
// pod template. Because of this, we do a recursive call for each element
|
||||
// in the list (instead of just marshaling the injected pod template).
|
||||
return injectList(bytes, options)
|
||||
|
||||
// TODO: generate an injectReport per list item
|
||||
return injectList(bytes, options, report)
|
||||
|
||||
}
|
||||
|
||||
|
@ -534,7 +571,7 @@ func injectResource(bytes []byte, options *injectOptions) ([]byte, error) {
|
|||
ControllerNamespace: controlPlaneNamespace,
|
||||
}
|
||||
|
||||
if injectPodSpec(podSpec, identity, DNSNameOverride, options) {
|
||||
if injectPodSpec(podSpec, identity, DNSNameOverride, options, report) {
|
||||
injectObjectMeta(objectMeta, k8sLabels, options)
|
||||
var err error
|
||||
output, err = yaml.Marshal(obj)
|
||||
|
@ -542,6 +579,8 @@ func injectResource(bytes []byte, options *injectOptions) ([]byte, error) {
|
|||
return nil, err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
report.unsupportedResource = true
|
||||
}
|
||||
|
||||
return output, nil
|
||||
|
@ -589,3 +628,57 @@ func walk(path string) ([]io.Reader, error) {
|
|||
|
||||
return in, nil
|
||||
}
|
||||
|
||||
func generateReport(injectReports []injectReport, output io.Writer) {
|
||||
|
||||
injected := []string{}
|
||||
hostNetwork := []string{}
|
||||
|
||||
for _, r := range injectReports {
|
||||
if !r.hostNetwork && !r.unsupportedResource {
|
||||
injected = append(injected, r.name)
|
||||
} else if r.hostNetwork {
|
||||
hostNetwork = append(hostNetwork, r.name)
|
||||
}
|
||||
}
|
||||
|
||||
// leading newline to separate from yaml output on stdout
|
||||
output.Write([]byte("\n"))
|
||||
|
||||
hostNetworkPrefix := fmt.Sprintf("%s%s", hostNetworkDesc, getFiller(hostNetworkDesc))
|
||||
if len(hostNetwork) == 0 {
|
||||
output.Write([]byte(fmt.Sprintf("%s%s\n", hostNetworkPrefix, okStatus)))
|
||||
} else {
|
||||
verb := "uses"
|
||||
if len(hostNetwork) > 1 {
|
||||
verb = "use"
|
||||
}
|
||||
output.Write([]byte(fmt.Sprintf("%s%s -- %s %s \"hostNetwork: true\"\n", hostNetworkPrefix, warnStatus, strings.Join(hostNetwork, ", "), verb)))
|
||||
}
|
||||
|
||||
unsupportedPrefix := fmt.Sprintf("%s%s", unsupportedDesc, getFiller(unsupportedDesc))
|
||||
if len(injected) > 0 {
|
||||
output.Write([]byte(fmt.Sprintf("%s%s\n", unsupportedPrefix, okStatus)))
|
||||
} else {
|
||||
output.Write([]byte(fmt.Sprintf("%s%s -- no supported objects found\n", unsupportedPrefix, warnStatus)))
|
||||
}
|
||||
|
||||
summary := fmt.Sprintf("Summary: %d of %d YAML document(s) injected", len(injected), len(injectReports))
|
||||
output.Write([]byte(fmt.Sprintf("\n%s\n", summary)))
|
||||
|
||||
for _, i := range injected {
|
||||
output.Write([]byte(fmt.Sprintf(" %s\n", i)))
|
||||
}
|
||||
|
||||
// trailing newline to separate from kubectl output if piping
|
||||
output.Write([]byte("\n"))
|
||||
}
|
||||
|
||||
func getFiller(text string) string {
|
||||
filler := ""
|
||||
for i := 0; i < lineWidth-len(text)-len(okStatus)-len("\n"); i++ {
|
||||
filler = filler + "."
|
||||
}
|
||||
|
||||
return filler
|
||||
}
|
||||
|
|
|
@ -45,8 +45,9 @@ func TestInjectYAML(t *testing.T) {
|
|||
read := bufio.NewReader(file)
|
||||
|
||||
output := new(bytes.Buffer)
|
||||
report := new(bytes.Buffer)
|
||||
|
||||
err = InjectYAML(read, output, tc.testInjectOptions)
|
||||
err = InjectYAML(read, output, report, tc.testInjectOptions)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error injecting YAML: %v\n", err)
|
||||
}
|
||||
|
@ -80,6 +81,7 @@ func TestRunInjectCmd(t *testing.T) {
|
|||
{
|
||||
inputFileName: "inject_gettest_deployment.good.input.yml",
|
||||
stdOutGoldenFileName: "inject_gettest_deployment.good.golden.yml",
|
||||
stdErrGoldenFileName: "inject_gettest_deployment.good.golden.stderr",
|
||||
exitCode: 0,
|
||||
},
|
||||
}
|
||||
|
@ -123,9 +125,20 @@ func TestInjectFilePath(t *testing.T) {
|
|||
resource string
|
||||
resourceFile string
|
||||
expectedFile string
|
||||
stdErrFile string
|
||||
}{
|
||||
{resource: "nginx", resourceFile: filepath.Join(resourceFolder, "nginx.yaml"), expectedFile: filepath.Join(expectedFolder, "injected_nginx.yaml")},
|
||||
{resource: "redis", resourceFile: filepath.Join(resourceFolder, "db/redis.yaml"), expectedFile: filepath.Join(expectedFolder, "injected_redis.yaml")},
|
||||
{
|
||||
resource: "nginx",
|
||||
resourceFile: filepath.Join(resourceFolder, "nginx.yaml"),
|
||||
expectedFile: filepath.Join(expectedFolder, "injected_nginx.yaml"),
|
||||
stdErrFile: filepath.Join(expectedFolder, "injected_nginx.stderr"),
|
||||
},
|
||||
{
|
||||
resource: "redis",
|
||||
resourceFile: filepath.Join(resourceFolder, "db/redis.yaml"),
|
||||
expectedFile: filepath.Join(expectedFolder, "injected_redis.yaml"),
|
||||
stdErrFile: filepath.Join(expectedFolder, "injected_redis.stderr"),
|
||||
},
|
||||
}
|
||||
|
||||
for i, testCase := range testCases {
|
||||
|
@ -135,8 +148,9 @@ func TestInjectFilePath(t *testing.T) {
|
|||
t.Fatal("Unexpected error: ", err)
|
||||
}
|
||||
|
||||
errBuf := &bytes.Buffer{}
|
||||
actual := &bytes.Buffer{}
|
||||
if exitCode := runInjectCmd(in, actual, actual, options); exitCode != 0 {
|
||||
if exitCode := runInjectCmd(in, errBuf, actual, options); exitCode != 0 {
|
||||
t.Fatal("Unexpected error. Exit code from runInjectCmd: ", exitCode)
|
||||
}
|
||||
|
||||
|
@ -144,6 +158,11 @@ func TestInjectFilePath(t *testing.T) {
|
|||
if expected != actual.String() {
|
||||
t.Errorf("Result mismatch.\nExpected: %s\nActual: %s", expected, actual.String())
|
||||
}
|
||||
|
||||
stdErr := readOptionalTestFile(t, testCase.stdErrFile)
|
||||
if stdErr != errBuf.String() {
|
||||
t.Errorf("Result mismatch.\nExpected: %s\nActual: %s", stdErr, errBuf.String())
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
@ -154,8 +173,9 @@ func TestInjectFilePath(t *testing.T) {
|
|||
t.Fatal("Unexpected error: ", err)
|
||||
}
|
||||
|
||||
errBuf := &bytes.Buffer{}
|
||||
actual := &bytes.Buffer{}
|
||||
if exitCode := runInjectCmd(in, actual, actual, options); exitCode != 0 {
|
||||
if exitCode := runInjectCmd(in, errBuf, actual, options); exitCode != 0 {
|
||||
t.Fatal("Unexpected error. Exit code from runInjectCmd: ", exitCode)
|
||||
}
|
||||
|
||||
|
@ -163,6 +183,11 @@ func TestInjectFilePath(t *testing.T) {
|
|||
if expected != actual.String() {
|
||||
t.Errorf("Result mismatch.\nExpected: %s\nActual: %s", expected, actual.String())
|
||||
}
|
||||
|
||||
stdErr := readOptionalTestFile(t, filepath.Join(expectedFolder, "injected_nginx_redis.stderr"))
|
||||
if stdErr != errBuf.String() {
|
||||
t.Errorf("Result mismatch.\nExpected: %s\nActual: %s", stdErr, errBuf.String())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"text/template"
|
||||
|
||||
|
@ -133,7 +134,7 @@ func render(config installConfig, w io.Writer, options *installOptions) error {
|
|||
// Special case for linkerd-proxy running in the Prometheus pod.
|
||||
injectOptions.proxyOutboundCapacity[config.PrometheusImage] = prometheusProxyOutboundCapacity
|
||||
|
||||
return InjectYAML(buf, w, injectOptions)
|
||||
return InjectYAML(buf, w, ioutil.Discard, injectOptions)
|
||||
}
|
||||
|
||||
func validate(options *installOptions) error {
|
||||
|
|
|
@ -14,7 +14,13 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const defaultNamespace = "linkerd"
|
||||
const (
|
||||
defaultNamespace = "linkerd"
|
||||
|
||||
lineWidth = 80
|
||||
okStatus = "[ok]"
|
||||
warnStatus = "[warn]"
|
||||
)
|
||||
|
||||
var controlPlaneNamespace string
|
||||
var apiAddr string // An empty value means "use the Kubernetes configuration"
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
hostNetwork: pods do not use host networking...............................[ok]
|
||||
supported: at least one resource injected..................................[ok]
|
||||
|
||||
Summary: 1 of 1 YAML document(s) injected
|
||||
deployment/nginx
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
hostNetwork: pods do not use host networking...............................[ok]
|
||||
supported: at least one resource injected..................................[ok]
|
||||
|
||||
Summary: 1 of 1 YAML document(s) injected
|
||||
deployment/redis
|
||||
|
||||
|
||||
hostNetwork: pods do not use host networking...............................[ok]
|
||||
supported: at least one resource injected..................................[ok]
|
||||
|
||||
Summary: 1 of 1 YAML document(s) injected
|
||||
deployment/nginx
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
hostNetwork: pods do not use host networking...............................[ok]
|
||||
supported: at least one resource injected..................................[ok]
|
||||
|
||||
Summary: 1 of 1 YAML document(s) injected
|
||||
deployment/redis
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
hostNetwork: pods do not use host networking...............................[ok]
|
||||
supported: at least one resource injected..................................[ok]
|
||||
|
||||
Summary: 2 of 2 YAML document(s) injected
|
||||
deployment/get-test-deploy-injected-1
|
||||
deployment/get-test-deploy-injected-2
|
||||
|
|
@ -39,7 +39,7 @@ func (s *server) Get(dest *destination.GetDestination, stream destination.Destin
|
|||
return err
|
||||
}
|
||||
|
||||
log.Debug("Get update: %v", update)
|
||||
log.Debugf("Get update: %v", update)
|
||||
stream.Send(update)
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ func TestMain(m *testing.M) {
|
|||
//////////////////////
|
||||
|
||||
func TestEgressHttp(t *testing.T) {
|
||||
out, err := TestHelper.LinkerdRun("inject", "testdata/proxy.yaml")
|
||||
out, _, err := TestHelper.LinkerdRun("inject", "testdata/proxy.yaml")
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ var (
|
|||
//////////////////////
|
||||
|
||||
func TestCliGet(t *testing.T) {
|
||||
out, err := TestHelper.LinkerdRun("inject", "testdata/to_be_injected_application.yaml")
|
||||
out, _, err := TestHelper.LinkerdRun("inject", "testdata/to_be_injected_application.yaml")
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ func TestCliGet(t *testing.T) {
|
|||
}
|
||||
|
||||
t.Run("get pods from --all-namespaces", func(t *testing.T) {
|
||||
out, err = TestHelper.LinkerdRun("get", "pods", "--all-namespaces")
|
||||
out, _, err = TestHelper.LinkerdRun("get", "pods", "--all-namespaces")
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v output:\n%s", err, out)
|
||||
|
@ -94,7 +94,7 @@ func TestCliGet(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("get pods from the linkerd namespace", func(t *testing.T) {
|
||||
out, err = TestHelper.LinkerdRun("get", "pods", "-n", TestHelper.GetLinkerdNamespace())
|
||||
out, _, err = TestHelper.LinkerdRun("get", "pods", "-n", TestHelper.GetLinkerdNamespace())
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v output:\n%s", err, out)
|
||||
|
|
|
@ -54,7 +54,7 @@ func TestVersionPreInstall(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestCheckPreInstall(t *testing.T) {
|
||||
out, err := TestHelper.LinkerdRun("check", "--pre", "--expected-version", TestHelper.GetVersion())
|
||||
out, _, err := TestHelper.LinkerdRun("check", "--pre", "--expected-version", TestHelper.GetVersion())
|
||||
if err != nil {
|
||||
t.Fatalf("Check command failed\n%s", out)
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ func TestInstall(t *testing.T) {
|
|||
linkerdDeployReplicas["ca"] = 1
|
||||
}
|
||||
|
||||
out, err := TestHelper.LinkerdRun(cmd...)
|
||||
out, _, err := TestHelper.LinkerdRun(cmd...)
|
||||
if err != nil {
|
||||
t.Fatalf("linkerd install command failed\n%s", out)
|
||||
}
|
||||
|
@ -131,7 +131,7 @@ func TestCheckPostInstall(t *testing.T) {
|
|||
var out string
|
||||
var err error
|
||||
overallErr := TestHelper.RetryFor(30*time.Second, func() error {
|
||||
out, err = TestHelper.LinkerdRun("check", "--expected-version", TestHelper.GetVersion())
|
||||
out, _, err = TestHelper.LinkerdRun("check", "--expected-version", TestHelper.GetVersion())
|
||||
return err
|
||||
})
|
||||
if overallErr != nil {
|
||||
|
@ -185,11 +185,16 @@ func TestInject(t *testing.T) {
|
|||
cmd = append(cmd, []string{"--tls", "optional"}...)
|
||||
}
|
||||
|
||||
out, err := TestHelper.LinkerdRun(cmd...)
|
||||
out, injectReport, err := TestHelper.LinkerdRun(cmd...)
|
||||
if err != nil {
|
||||
t.Fatalf("linkerd inject command failed\n%s", out)
|
||||
}
|
||||
|
||||
err = TestHelper.ValidateOutput(injectReport, "inject.report.golden")
|
||||
if err != nil {
|
||||
t.Fatalf("Received unexpected output\n%s", err.Error())
|
||||
}
|
||||
|
||||
prefixedNs := TestHelper.GetTestNamespace("smoke-test")
|
||||
out, err = TestHelper.KubectlApply(out, prefixedNs)
|
||||
if err != nil {
|
||||
|
@ -215,7 +220,7 @@ func TestInject(t *testing.T) {
|
|||
|
||||
func TestCheckProxy(t *testing.T) {
|
||||
prefixedNs := TestHelper.GetTestNamespace("smoke-test")
|
||||
out, err := TestHelper.LinkerdRun(
|
||||
out, _, err := TestHelper.LinkerdRun(
|
||||
"check",
|
||||
"--proxy",
|
||||
"--expected-version",
|
||||
|
|
|
@ -122,7 +122,7 @@ func TestCliStatForLinkerdNamespace(t *testing.T) {
|
|||
} {
|
||||
t.Run("linkerd "+strings.Join(tt.args, " "), func(t *testing.T) {
|
||||
err := TestHelper.RetryFor(20*time.Second, func() error {
|
||||
out, err := TestHelper.LinkerdRun(tt.args...)
|
||||
out, _, err := TestHelper.LinkerdRun(tt.args...)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected stat error: %s\n%s", err, out)
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ var (
|
|||
//////////////////////
|
||||
|
||||
func TestCliTap(t *testing.T) {
|
||||
out, err := TestHelper.LinkerdRun("inject", "testdata/tap_application.yaml")
|
||||
out, _, err := TestHelper.LinkerdRun("inject", "testdata/tap_application.yaml")
|
||||
if err != nil {
|
||||
t.Fatalf("linkerd inject command failed\n%s", out)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
hostNetwork: pods do not use host networking...............................[ok]
|
||||
supported: at least one resource injected..................................[ok]
|
||||
|
||||
Summary: 2 of 4 YAML document(s) injected
|
||||
deployment/smoke-test-terminus
|
||||
deployment/smoke-test-gateway
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package testutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
@ -73,9 +74,9 @@ func NewTestHelper() *TestHelper {
|
|||
tls: *tls,
|
||||
}
|
||||
|
||||
version, err := testHelper.LinkerdRun("version", "--client", "--short")
|
||||
version, _, err := testHelper.LinkerdRun("version", "--client", "--short")
|
||||
if err != nil {
|
||||
exit(1, "error getting linkerd version")
|
||||
exit(1, "error getting linkerd version: "+err.Error())
|
||||
}
|
||||
testHelper.version = strings.TrimSpace(version)
|
||||
|
||||
|
@ -117,19 +118,18 @@ func (h *TestHelper) TLS() bool {
|
|||
}
|
||||
|
||||
// CombinedOutput executes a shell command and returns the output.
|
||||
func (h *TestHelper) CombinedOutput(name string, arg ...string) (string, error) {
|
||||
func (h *TestHelper) CombinedOutput(name string, arg ...string) (string, string, error) {
|
||||
command := exec.Command(name, arg...)
|
||||
bytes, err := command.CombinedOutput()
|
||||
if err != nil {
|
||||
return string(bytes), err
|
||||
}
|
||||
var stderr bytes.Buffer
|
||||
command.Stderr = &stderr
|
||||
|
||||
return string(bytes), nil
|
||||
stdout, err := command.Output()
|
||||
return string(stdout), stderr.String(), err
|
||||
}
|
||||
|
||||
// LinkerdRun executes a linkerd command appended with the --linkerd-namespace
|
||||
// flag.
|
||||
func (h *TestHelper) LinkerdRun(arg ...string) (string, error) {
|
||||
func (h *TestHelper) LinkerdRun(arg ...string) (string, string, error) {
|
||||
withNamespace := append(arg, "--linkerd-namespace", h.namespace)
|
||||
return h.CombinedOutput(h.linkerd, withNamespace...)
|
||||
}
|
||||
|
@ -179,7 +179,7 @@ func (h *TestHelper) ValidateOutput(out, fixtureFile string) error {
|
|||
|
||||
// CheckVersion validates the the output of the "linkerd version" command.
|
||||
func (h *TestHelper) CheckVersion(serverVersion string) error {
|
||||
out, err := h.LinkerdRun("version")
|
||||
out, _, err := h.LinkerdRun("version")
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unexpected error: %s\n%s", err.Error(), out)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue