|
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