-
Notifications
You must be signed in to change notification settings - Fork 621
Vap for updates #4165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Vap for updates #4165
Changes from all commits
dfdbf1b
04dd99e
757b372
f706554
71fa7f1
cebd935
1dbc16b
78f0a3a
f33a044
b23375e
989e87d
ad37c0a
867b232
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,13 +17,17 @@ limitations under the License. | |
| package crd_test | ||
|
|
||
| import ( | ||
| "bytes" | ||
| "fmt" | ||
| "io" | ||
| "io/fs" | ||
| "os" | ||
| "os/exec" | ||
| "path/filepath" | ||
| "regexp" | ||
| "strings" | ||
| "testing" | ||
| "time" | ||
|
|
||
| "github.com/stretchr/testify/assert" | ||
| "github.com/stretchr/testify/require" | ||
|
|
@@ -70,40 +74,105 @@ func TestCRDValidation(t *testing.T) { | |
| crdChannel = requestedCRDChannel | ||
| } | ||
|
|
||
| t.Run("should be able to start test environment", func(_ *testing.T) { | ||
| testEnv = &envtest.Environment{ | ||
| Scheme: scheme, | ||
| ErrorIfCRDPathMissing: true, | ||
| DownloadBinaryAssets: true, | ||
| DownloadBinaryAssetsVersion: k8sVersion, | ||
| CRDInstallOptions: envtest.CRDInstallOptions{ | ||
| Paths: []string{ | ||
| filepath.Join("..", "..", "config", "crd", crdChannel), | ||
| }, | ||
| CleanUpAfterUse: true, | ||
| testEnv = &envtest.Environment{ | ||
| Scheme: scheme, | ||
| ErrorIfCRDPathMissing: true, | ||
| DownloadBinaryAssets: true, | ||
| DownloadBinaryAssetsVersion: k8sVersion, | ||
| CRDInstallOptions: envtest.CRDInstallOptions{ | ||
| Paths: []string{ | ||
| filepath.Join("..", "..", "..", "config", "crd", crdChannel), | ||
| }, | ||
| } | ||
|
|
||
| _, err = testEnv.Start() | ||
| if err != nil { | ||
| panic(fmt.Sprintf("Error initializing test environment: %v", err)) | ||
| } | ||
| }) | ||
| CleanUpAfterUse: true, | ||
| }, | ||
| } | ||
|
|
||
| _, err = testEnv.Start() | ||
| t.Cleanup(func() { | ||
| require.NoError(t, testEnv.Stop()) | ||
| }) | ||
| require.NoError(t, err, "Error initializing test environment") | ||
|
|
||
| // Setup kubectl and kubeconfig | ||
| kubectlLocation = testEnv.ControlPlane.KubectlPath | ||
| require.NotEmpty(t, kubectlLocation, "Error initializing Kubectl") | ||
|
|
||
| t.Run("should be able to set kubectl and kubeconfig and connect to the cluster", func(t *testing.T) { | ||
| kubectlLocation = testEnv.ControlPlane.KubectlPath | ||
| require.NotEmpty(t, kubectlLocation) | ||
| kubeconfigLocation = fmt.Sprintf("%s/kubeconfig", filepath.Dir(kubectlLocation)) | ||
| err = os.WriteFile(kubeconfigLocation, testEnv.KubeConfig, 0o600) | ||
| require.NoError(t, err, "Error initializing kubeconfig") | ||
|
|
||
| kubeconfigLocation = fmt.Sprintf("%s/kubeconfig", filepath.Dir(kubectlLocation)) | ||
| require.NoError(t, os.WriteFile(kubeconfigLocation, testEnv.KubeConfig, 0o600)) | ||
| apiResources, err := executeKubectlCommand(t, kubectlLocation, kubeconfigLocation, []string{"api-resources"}) | ||
| require.NoError(t, err) | ||
| require.Contains(t, apiResources, "gateway.networking.k8s.io/v1") | ||
|
|
||
| t.Run("safeupgrades VAP should validate correctly", func(t *testing.T) { | ||
| if crdChannel == "experimental" { | ||
| t.Skipf("skipping safeupgrades VAP") | ||
| } | ||
|
|
||
| apiResources, err := executeKubectlCommand(t, kubectlLocation, kubeconfigLocation, []string{"api-resources"}) | ||
| output, err := executeKubectlCommand(t, kubectlLocation, kubeconfigLocation, | ||
| []string{"apply", "--server-side", "--wait", "-f", filepath.Join("..", "..", "..", "config", "crd", "standard", "gateway.networking.k8s.io_vap_safeupgrades.yaml")}) | ||
| require.NoError(t, err) | ||
| require.Contains(t, apiResources, "gateway.networking.k8s.io/v1") | ||
|
|
||
| // Even though --wait is applied I noticed a race condition that causes tests to fail. | ||
| time.Sleep(time.Second) | ||
|
|
||
| t.Run("should be able to install standard CRDs", func(t *testing.T) { | ||
| output, err = executeKubectlCommand(t, kubectlLocation, kubeconfigLocation, | ||
| []string{"apply", "--server-side", "--wait", "-f", filepath.Join("..", "..", "..", "config", "crd", "standard")}) | ||
| require.NoError(t, err) | ||
| }) | ||
|
|
||
| t.Run("should not be able to install k8s.io experimental CRDs", func(t *testing.T) { | ||
| t.Cleanup(func() { | ||
| output, err = executeKubectlCommand(t, kubectlLocation, kubeconfigLocation, | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should you assert/require that an error does not happen here as well?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. also shouldn't this cleanup be on "crd/standard"? (or am I missing something here?)
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the feedback. I didn't assert the error here because failing to delete in cleanup should not invalidate a successful test IMO. Though it would make sense to add an assert in cleanup for the test "should be able to install x-k8s.io experimental CRDs" and I would update the name to "should be able to install and remove x-k8s.io experimental CRDs". But for the other 2 if there is no error and enter clean up there is nothing to delete anyways so throwing an error would be a false negative. Tho since I'm not using output or err I should rename to _, _. But to your point if it is failing to cleanup we probably want to see that in some form. To me it would make since to have a separate test for testing delete. I didn't put a cleanup on crd/standard because the following test is to test installing experimental on top of standard. So it makes since to not clean up the first test to have it persist for the following tests. But ultimately the VAP doesn't care so it doesn't really matter. |
||
| []string{"delete", "--wait", "-f", filepath.Join("..", "..", "..", "config", "crd", "experimental", "*.k8s.*")}) | ||
| }) | ||
|
|
||
| output, err = executeKubectlCommand(t, kubectlLocation, kubeconfigLocation, | ||
| []string{"apply", "--server-side", "--wait", "-f", filepath.Join("..", "..", "..", "config", "crd", "experimental", "*.k8s.*")}) | ||
| require.Error(t, err) | ||
| assert.Contains(t, output, "Error from server (Invalid)") | ||
| assert.Contains(t, output, "ValidatingAdmissionPolicy 'safe-upgrades.gateway.networking.k8s.io' with binding 'safe-upgrades.gateway.networking.k8s.io' denied request") | ||
|
|
||
| // Check that --api-group has no invalid crd's | ||
| output, err = executeKubectlCommand(t, kubectlLocation, kubeconfigLocation, []string{"describe", "CustomResourceDefinition"}) | ||
| require.NoError(t, err) | ||
| assert.NotContains(t, output, "gateway.networking.k8s.io/channel: experimental", "output contains 'gateway.networking.k8s.io/channel: experimental'") | ||
| }) | ||
|
|
||
| t.Run("should be able to install x-k8s.io experimental CRDs", func(t *testing.T) { | ||
| t.Cleanup(func() { | ||
| output, err = executeKubectlCommand(t, kubectlLocation, kubeconfigLocation, | ||
| []string{"delete", "--wait", "-f", filepath.Join("..", "..", "..", "config", "crd", "experimental", "*.x-k8s.*")}) | ||
| }) | ||
|
|
||
| output, err = executeKubectlCommand(t, kubectlLocation, kubeconfigLocation, | ||
| []string{"apply", "--server-side", "--wait", "-f", filepath.Join("..", "..", "..", "config", "crd", "experimental", "*.x-k8s.*")}) | ||
| require.NoError(t, err) | ||
| }) | ||
|
|
||
| t.Run("should not be able to install CRDs with an older version", func(t *testing.T) { | ||
| t.Cleanup(func() { | ||
| output, err = executeKubectlCommand(t, kubectlLocation, kubeconfigLocation, | ||
| []string{"delete", "--wait", "-f", filepath.Join("..", "..", "..", "config", "crd", "standard", "gateway.networking.k8s.io_httproutes.yaml")}) | ||
| }) | ||
|
|
||
| // Read test crd into []byte | ||
| httpCrd, err := os.ReadFile(filepath.Join("..", "..", "..", "config", "crd", "standard", "gateway.networking.k8s.io_httproutes.yaml")) | ||
| require.NoError(t, err) | ||
|
|
||
| // do replace on gateway.networking.k8s.io/bundle-version: v1.4.0 | ||
| re := regexp.MustCompile(`gateway\.networking\.k8s\.io\/bundle-version: \S*`) | ||
| sub := []byte("gateway.networking.k8s.io/bundle-version: v1.3.0") | ||
| oldCrd := re.ReplaceAll(httpCrd, sub) | ||
|
|
||
| // supply crd to stdin of cmd and kubectl apply -f - | ||
| output, err = executeKubectlCommandStdin(t, kubectlLocation, kubeconfigLocation, bytes.NewReader(oldCrd), []string{"apply", "-f", "-"}) | ||
|
|
||
| require.Error(t, err) | ||
| assert.Contains(t, output, "ValidatingAdmissionPolicy 'safe-upgrades.gateway.networking.k8s.io' with binding 'safe-upgrades.gateway.networking.k8s.io' denied request") | ||
| }) | ||
| }) | ||
|
|
||
| t.Run("should be able to install standard examples", func(t *testing.T) { | ||
|
|
@@ -155,6 +224,22 @@ func executeKubectlCommand(t *testing.T, kubectl, kubeconfig string, args []stri | |
| return string(output), err | ||
| } | ||
|
|
||
| func executeKubectlCommandStdin(t *testing.T, kubectl, kubeconfig string, stdin io.Reader, args []string) (string, error) { | ||
| t.Helper() | ||
|
|
||
| cacheDir := filepath.Dir(kubeconfig) | ||
| args = append([]string{"--cache-dir", cacheDir}, args...) | ||
|
|
||
| cmd := exec.Command(kubectl, args...) | ||
| cmd.Env = []string{ | ||
| fmt.Sprintf("KUBECONFIG=%s", kubeconfig), | ||
| } | ||
| cmd.Stdin = stdin | ||
|
|
||
| output, err := cmd.CombinedOutput() | ||
| return string(output), err | ||
| } | ||
|
|
||
| func getInvalidExamplesFiles(t *testing.T, crdChannel string) ([]string, error) { | ||
| t.Helper() | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason for removing this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I put this logic in the parent test so that you could run targeted tests without issue. for example "make test.crds-validation GO_TEST_FLAGS="-run TestCRDValidation/safeupgrades_VAP_should_validate_correctly"". would not work as well as a few other tests because it depended on logic in this test.