|
2 | 2 | // +build integ
|
3 | 3 |
|
4 | 4 | /*
|
5 |
| -End-to-End Test for kmeshctl authz Commands in Kmesh. |
6 |
| -
|
7 |
| -This test performs the following steps: |
8 |
| -1. Automatically retrieves a running Kmesh Daemon pod from the "kmesh-system" namespace. |
9 |
| -2. Waits for the pod to become ready. |
10 |
| -3. Enables authorization offloading using "kmeshctl authz enable <pod>". |
11 |
| -4. Verifies the status using "kmeshctl authz status <pod>" (expecting enabled output). |
12 |
| -5. Disables authorization using "kmeshctl authz disable <pod>". |
13 |
| -6. Verifies the status again (expecting disabled output). |
14 |
| -
|
15 |
| -This test ensures that the authz commands work correctly on a live cluster. |
16 |
| -*/ |
| 5 | + * Copyright The Kmesh Authors. |
| 6 | + * |
| 7 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
| 8 | + * you may not use this file except in compliance with the License. |
| 9 | + * You may obtain a copy of the License at: |
| 10 | + * |
| 11 | + * http://www.apache.org/licenses/LICENSE-2.0 |
| 12 | + * |
| 13 | + * Unless required by applicable law or agreed to in writing, software |
| 14 | + * distributed under the License is distributed on an "AS IS" BASIS, |
| 15 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 16 | + * See the License for the specific language governing permissions and |
| 17 | + * limitations under the License. |
| 18 | + */ |
17 | 19 |
|
18 | 20 | package kmesh
|
19 | 21 |
|
20 | 22 | import (
|
21 | 23 | "fmt"
|
| 24 | + "os/exec" |
22 | 25 | "strings"
|
23 | 26 | "testing"
|
24 | 27 | "time"
|
25 | 28 |
|
| 29 | + "istio.io/istio/pkg/test" |
26 | 30 | "istio.io/istio/pkg/test/framework"
|
27 | 31 | "istio.io/istio/pkg/test/shell"
|
28 | 32 | "istio.io/istio/pkg/test/util/retry"
|
29 | 33 | )
|
30 | 34 |
|
31 |
| -// getKmeshPod retrieves the name of a running Kmesh daemon pod in the kmesh-system namespace. |
32 |
| -// It uses kubectl with a jsonpath query to return the first pod with label "app=kmesh". |
33 |
| -func getKmeshPod() (string, error) { |
34 |
| - out, err := shell.Execute(true, "kubectl get pods -n kmesh-system -l app=kmesh -o jsonpath='{.items[0].metadata.name}'") |
| 35 | +// kmeshctlWrapper provides a minimal wrapper to invoke kmeshctl authz commands. |
| 36 | +type kmeshctlWrapper struct{} |
| 37 | + |
| 38 | +// NewKmeshctl creates and returns a new instance of kmeshctlWrapper. |
| 39 | +func NewKmeshctl() *kmeshctlWrapper { |
| 40 | + return &kmeshctlWrapper{} |
| 41 | +} |
| 42 | + |
| 43 | +// Authz executes "kmeshctl authz <subcmd>" and returns its output as a lowercase string. |
| 44 | +func (k *kmeshctlWrapper) Authz(subcmd string) (string, error) { |
| 45 | + cmd := exec.Command("kmeshctl", "authz", subcmd) |
| 46 | + output, err := cmd.CombinedOutput() |
35 | 47 | if err != nil {
|
36 |
| - return "", fmt.Errorf("failed to get kmesh pod: %v", err) |
| 48 | + return "", fmt.Errorf("command 'kmeshctl authz %s' failed: %v, output: %s", subcmd, err, string(output)) |
37 | 49 | }
|
38 |
| - podName := strings.Trim(out, "'") |
39 |
| - if podName == "" { |
40 |
| - return "", fmt.Errorf("no kmesh pod found") |
41 |
| - } |
42 |
| - return podName, nil |
| 50 | + return strings.ToLower(strings.TrimSpace(string(output))), nil |
43 | 51 | }
|
44 | 52 |
|
45 |
| -// runKmeshCtl builds and executes a kmeshctl authz command with the provided arguments. |
46 |
| -// It returns the command output (stdout) or an error. |
47 |
| -func runKmeshCtl(pod string, args ...string) (string, error) { |
48 |
| - // Construct the command string, e.g., "kmeshctl authz enable <pod>" |
49 |
| - cmd := "kmeshctl authz " + strings.Join(args, " ") + " " + pod |
50 |
| - return shell.Execute(true, cmd) |
| 53 | +// AuthzOrFatal executes the command and fails the test immediately if there is an error. |
| 54 | +func (k *kmeshctlWrapper) AuthzOrFatal(t test.Failer, subcmd string) string { |
| 55 | + out, err := k.Authz(subcmd) |
| 56 | + if err != nil { |
| 57 | + t.Fatal("failed to execute kmeshctl authz", subcmd, ":", err) |
| 58 | + } |
| 59 | + return out |
51 | 60 | }
|
52 | 61 |
|
53 |
| -func TestKmeshctlAuthz(t *testing.T) { |
| 62 | +// Global instance of kmeshctl wrapper. |
| 63 | +var kmeshctl = NewKmeshctl() |
| 64 | + |
| 65 | +// TestKmeshctlAuthzCommands performs the following operations: |
| 66 | +// - Enable authz on a Kmesh daemon pod |
| 67 | +// - Check that authz is enabled |
| 68 | +// - Disable authz |
| 69 | +// - Verify that authz is disabled |
| 70 | +func TestKmeshctlAuthzCommands(t *testing.T) { |
54 | 71 | framework.NewTest(t).Run(func(t framework.TestContext) {
|
55 |
| - var pod string |
56 |
| - var err error |
57 |
| - |
58 |
| - // --- Pod Detection and Readiness --- |
59 |
| - // Retry until we can fetch a Kmesh daemon pod from the kmesh-system namespace. |
60 |
| - err = retry.Until(func() bool { |
61 |
| - pod, err = getKmeshPod() |
62 |
| - if err != nil { |
63 |
| - t.Logf("Retrying getKmeshPod: %v", err) |
64 |
| - return false |
65 |
| - } |
66 |
| - // Additionally, use kubectl wait to ensure the pod is Ready. |
67 |
| - _, err = shell.Execute(true, "kubectl wait pod -n kmesh-system -l app=kmesh --for=condition=Ready --timeout=60s") |
68 |
| - if err != nil { |
69 |
| - t.Logf("Pod not yet ready: %v", err) |
70 |
| - return false |
71 |
| - } |
72 |
| - t.Logf("Found ready Kmesh pod: %s", pod) |
73 |
| - return true |
74 |
| - }, retry.Timeout(90*time.Second), retry.Delay(3*time.Second)) |
| 72 | + // Automatically retrieve a running Kmesh daemon pod in the kmesh-system namespace. |
| 73 | + podName, err := shell.Execute(true, "kubectl get pods -n kmesh-system -l app=kmesh -o jsonpath='{.items[0].metadata.name}'") |
75 | 74 | if err != nil {
|
76 |
| - t.Fatalf("Failed to retrieve a ready Kmesh pod: %v", err) |
| 75 | + t.Fatalf("failed to get Kmesh daemon pod: %v", err) |
| 76 | + } |
| 77 | + podName = strings.TrimSpace(podName) |
| 78 | + if podName == "" { |
| 79 | + t.Fatal("no Kmesh daemon pod found in the kmesh-system namespace") |
77 | 80 | }
|
| 81 | + t.Logf("Found Kmesh daemon pod: %s", podName) |
78 | 82 |
|
79 |
| - // --- Enable Authz --- |
80 |
| - t.Log("Enabling authz on the Kmesh pod...") |
81 |
| - enableOut, err := runKmeshCtl(pod, "enable") |
| 83 | + // Wait until the pod is ready. |
| 84 | + _, err = shell.Execute(true, "kubectl wait pod -n kmesh-system -l app=kmesh --for=condition=Ready --timeout=60s") |
82 | 85 | if err != nil {
|
83 |
| - t.Fatalf("Failed to enable authz: %v", err) |
| 86 | + t.Fatalf("Kmesh daemon pod %s did not become ready: %v", podName, err) |
84 | 87 | }
|
85 |
| - t.Logf("Authz enable output: %s", enableOut) |
86 |
| - // Expect the output to indicate authz is enabled (case-insensitive check for "true" or "enabled"). |
87 |
| - if !strings.Contains(strings.ToLower(enableOut), "true") && !strings.Contains(strings.ToLower(enableOut), "enabled") { |
88 |
| - t.Fatalf("Unexpected output from enable command: %s", enableOut) |
| 88 | + |
| 89 | + // Enable authz. |
| 90 | + t.Log("Enabling authz...") |
| 91 | + enableOut := kmeshctl.AuthzOrFatal(t, fmt.Sprintf("%s enable", podName)) |
| 92 | + t.Logf("Output from enable command: %s", enableOut) |
| 93 | + if !strings.Contains(enableOut, "enabled") && !strings.Contains(enableOut, "true") { |
| 94 | + t.Fatalf("Unexpected output when enabling authz: %s", enableOut) |
89 | 95 | }
|
90 | 96 |
|
91 |
| - // --- Verify Authz Enabled --- |
92 |
| - // Allow a brief wait for the daemon to update its status. |
| 97 | + // Wait for the state change to propagate. |
93 | 98 | time.Sleep(2 * time.Second)
|
94 |
| - t.Log("Verifying authz status (expected to be enabled)...") |
95 |
| - statusOut, err := runKmeshCtl(pod, "status") |
96 |
| - if err != nil { |
97 |
| - t.Fatalf("Failed to get authz status: %v", err) |
98 |
| - } |
99 |
| - t.Logf("Authz status output after enable: %s", statusOut) |
100 |
| - if !strings.Contains(strings.ToLower(statusOut), "true") && !strings.Contains(strings.ToLower(statusOut), "enabled") { |
101 |
| - t.Fatalf("Authz status is not enabled as expected: %s", statusOut) |
102 |
| - } |
103 | 99 |
|
104 |
| - // --- Disable Authz --- |
105 |
| - t.Log("Disabling authz on the Kmesh pod...") |
106 |
| - disableOut, err := runKmeshCtl(pod, "disable") |
107 |
| - if err != nil { |
108 |
| - t.Fatalf("Failed to disable authz: %v", err) |
| 100 | + // Check authz status: it should indicate enabled. |
| 101 | + t.Log("Verifying authz is enabled...") |
| 102 | + statusOut := kmeshctl.AuthzOrFatal(t, fmt.Sprintf("%s status", podName)) |
| 103 | + t.Logf("Status output after enabling: %s", statusOut) |
| 104 | + if !strings.Contains(statusOut, "enabled") && !strings.Contains(statusOut, "true") { |
| 105 | + t.Fatalf("Authz status does not indicate enabled: %s", statusOut) |
109 | 106 | }
|
110 |
| - t.Logf("Authz disable output: %s", disableOut) |
111 |
| - // Expect the disable output to indicate authz is disabled (look for "false" or "disabled"). |
112 |
| - if !strings.Contains(strings.ToLower(disableOut), "false") && !strings.Contains(strings.ToLower(disableOut), "disabled") { |
113 |
| - t.Fatalf("Unexpected output from disable command: %s", disableOut) |
| 107 | + |
| 108 | + // Disable authz. |
| 109 | + t.Log("Disabling authz...") |
| 110 | + disableOut := kmeshctl.AuthzOrFatal(t, fmt.Sprintf("%s disable", podName)) |
| 111 | + t.Logf("Output from disable command: %s", disableOut) |
| 112 | + if !strings.Contains(disableOut, "disabled") && !strings.Contains(disableOut, "false") { |
| 113 | + t.Fatalf("Unexpected output when disabling authz: %s", disableOut) |
114 | 114 | }
|
115 | 115 |
|
116 |
| - // --- Verify Authz Disabled --- |
117 |
| - // Wait again briefly before checking status. |
| 116 | + // Wait again for the state to propagate. |
118 | 117 | time.Sleep(2 * time.Second)
|
119 |
| - t.Log("Verifying authz status (expected to be disabled)...") |
120 |
| - statusOut, err = runKmeshCtl(pod, "status") |
121 |
| - if err != nil { |
122 |
| - t.Fatalf("Failed to get authz status after disable: %v", err) |
123 |
| - } |
124 |
| - t.Logf("Authz status output after disable: %s", statusOut) |
125 |
| - if !strings.Contains(strings.ToLower(statusOut), "false") && !strings.Contains(strings.ToLower(statusOut), "disabled") { |
126 |
| - t.Fatalf("Authz status is not disabled as expected: %s", statusOut) |
| 118 | + |
| 119 | + // Verify authz status: it should indicate disabled. |
| 120 | + t.Log("Verifying authz is disabled...") |
| 121 | + statusOut = kmeshctl.AuthzOrFatal(t, fmt.Sprintf("%s status", podName)) |
| 122 | + t.Logf("Status output after disabling: %s", statusOut) |
| 123 | + if !strings.Contains(statusOut, "disabled") && !strings.Contains(statusOut, "false") { |
| 124 | + t.Fatalf("Authz status does not indicate disabled: %s", statusOut) |
127 | 125 | }
|
128 | 126 |
|
129 |
| - t.Log("kmeshctl authz commands test passed successfully.") |
| 127 | + t.Log("kmeshctl authz commands test passed.") |
130 | 128 | })
|
131 | 129 | }
|
0 commit comments