-
Notifications
You must be signed in to change notification settings - Fork 180
Use dedicated namespace for e2e test code #661
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,6 +30,7 @@ import ( | |
corev1 "k8s.io/api/core/v1" | ||
rbacv1 "k8s.io/api/rbac/v1" | ||
apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" | ||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" | ||
"k8s.io/apimachinery/pkg/runtime" | ||
"k8s.io/apimachinery/pkg/runtime/serializer" | ||
|
@@ -55,9 +56,8 @@ const ( | |
defaultInterval = time.Millisecond * 250 | ||
// defaultCurlInterval is the default interval to run the test curl command. | ||
defaultCurlInterval = time.Second * 5 | ||
// nsName is the name of the Namespace used for tests. | ||
// TODO [danehans]: Must be "default" until https://github.com/kubernetes-sigs/gateway-api-inference-extension/issues/227 is fixed | ||
nsName = "default" | ||
// defaultNsName is the default name of the Namespace used for tests. Can override using the E2E_NS environment variable. | ||
defaultNsName = "inf-ext-e2e" | ||
// modelServerName is the name of the model server test resources. | ||
modelServerName = "vllm-llama3-8b-instruct" | ||
// modelName is the test model name. | ||
|
@@ -77,7 +77,7 @@ const ( | |
// inferModelManifest is the manifest for the inference model CRD. | ||
inferModelManifest = "../../../config/crd/bases/inference.networking.x-k8s.io_inferencemodels.yaml" | ||
// inferExtManifest is the manifest for the inference extension test resources. | ||
inferExtManifest = "../../../config/manifests/inferencepool-resources.yaml" | ||
inferExtManifest = "../../testdata/inferencepool-e2e.yaml" | ||
// envoyManifest is the manifest for the envoy proxy test resources. | ||
envoyManifest = "../../testdata/envoy.yaml" | ||
// modelServerManifestFilepathEnvVar is the env var that holds absolute path to the manifest for the model server test resource. | ||
|
@@ -91,6 +91,7 @@ var ( | |
kubeCli *kubernetes.Clientset | ||
scheme = runtime.NewScheme() | ||
cfg = config.GetConfigOrDie() | ||
nsName string | ||
) | ||
|
||
func TestAPIs(t *testing.T) { | ||
|
@@ -101,6 +102,11 @@ func TestAPIs(t *testing.T) { | |
} | ||
|
||
var _ = ginkgo.BeforeSuite(func() { | ||
nsName = os.Getenv("E2E_NS") | ||
if nsName == "" { | ||
nsName = defaultNsName | ||
} | ||
|
||
ginkgo.By("Setting up the test suite") | ||
setupSuite() | ||
|
||
|
@@ -109,6 +115,8 @@ var _ = ginkgo.BeforeSuite(func() { | |
}) | ||
|
||
func setupInfra() { | ||
createNamespace(cli, nsName) | ||
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. can you add the namespace deletion to AfterSuite cleanup? 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. I believe it's already done here: I do observe the NS being cleaned up. |
||
|
||
modelServerManifestPath := readModelServerManifestPath() | ||
modelServerManifestArray := getYamlsFromModelServerManifest(modelServerManifestPath) | ||
if strings.Contains(modelServerManifestArray[0], "hf-token") { | ||
|
@@ -118,6 +126,7 @@ func setupInfra() { | |
"inferencepools.inference.networking.x-k8s.io": inferPoolManifest, | ||
"inferencemodels.inference.networking.x-k8s.io": inferModelManifest, | ||
} | ||
|
||
createCRDs(cli, crds) | ||
createInferExt(cli, inferExtManifest) | ||
createClient(cli, clientManifest) | ||
|
@@ -182,6 +191,17 @@ var ( | |
curlInterval = defaultCurlInterval | ||
) | ||
|
||
func createNamespace(k8sClient client.Client, ns string) { | ||
ginkgo.By("Creating e2e namespace: " + ns) | ||
obj := &corev1.Namespace{ | ||
ObjectMeta: v1.ObjectMeta{ | ||
Name: ns, | ||
}, | ||
} | ||
err := k8sClient.Create(ctx, obj) | ||
gomega.Expect(err).NotTo(gomega.HaveOccurred(), "Failed to create e2e test namespace") | ||
} | ||
|
||
// namespaceExists ensures that a specified namespace exists and is ready for use. | ||
func namespaceExists(k8sClient client.Client, ns string) { | ||
ginkgo.By("Ensuring namespace exists: " + ns) | ||
|
@@ -276,8 +296,15 @@ func createHfSecret(k8sClient client.Client, secretPath string) { | |
|
||
// createEnvoy creates the envoy proxy resources used for testing from the given filePath. | ||
func createEnvoy(k8sClient client.Client, filePath string) { | ||
inManifests := readYaml(filePath) | ||
ginkgo.By("Replacing placeholder namespace with E2E_NS environment variable") | ||
outManifests := []string{} | ||
for _, m := range inManifests { | ||
outManifests = append(outManifests, strings.ReplaceAll(m, "$E2E_NS", nsName)) | ||
} | ||
|
||
ginkgo.By("Creating envoy proxy resources from manifest: " + filePath) | ||
applyYAMLFile(k8sClient, filePath) | ||
createObjsFromYaml(k8sClient, outManifests) | ||
|
||
// Wait for the configmap to exist before proceeding with test. | ||
cfgMap := &corev1.ConfigMap{} | ||
|
@@ -302,8 +329,15 @@ func createEnvoy(k8sClient client.Client, filePath string) { | |
|
||
// createInferExt creates the inference extension resources used for testing from the given filePath. | ||
func createInferExt(k8sClient client.Client, filePath string) { | ||
inManifests := readYaml(filePath) | ||
ginkgo.By("Replacing placeholder namespace with E2E_NS environment variable") | ||
outManifests := []string{} | ||
for _, m := range inManifests { | ||
outManifests = append(outManifests, strings.ReplaceAll(m, "$E2E_NS", nsName)) | ||
} | ||
|
||
ginkgo.By("Creating inference extension resources from manifest: " + filePath) | ||
applyYAMLFile(k8sClient, filePath) | ||
createObjsFromYaml(k8sClient, outManifests) | ||
|
||
// Wait for the clusterrole to exist. | ||
testutils.EventuallyExists(ctx, func() error { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
apiVersion: inference.networking.x-k8s.io/v1alpha2 | ||
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. This looks like a duplication of the existing inferencepool-resources.yaml, excluding the namespace field. there is a big value in testing e2e our "Getting Started" files, so we are self testing the public documentation. 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. How would you suggest getting the env var parsed in the YAML file? 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. I suppose I could use a similar approach to the one you described above. However, that might complicate the getting started guide? How would the user of the guide make sure the env var was parsed in the file? 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. in the e2e a similar approach would work. in getting started guide I’m not sure we have an agreement of the other maintainers about being able to choose the namespace (I’m in favor of it). for example - this discussion is relevant only for the subject serviceaccount in the ClusterRoleBinding, as the namespace in the Service and Deployment resources can be just removed and then you can decide the ns during e2e test. 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 we tackle this in a follow-up then? If we change the getting started file in this PR its going to expand the scope considerably as we now need to update the guide with the envvar substitution command. cc @danehans 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.
+1 on not changing the getting started guide in this PR. 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.
I agree with this point. We may need to consider 2 different e2e tests, 1 for testing the quickstart and another that is more programmatic to support various inference use cases. Maybe we track this in a separate issue? 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. I prefer to move away from yaml files and just create those objects in code,,, the envoy one is complex, so I don't mind it, but other than that I think it is more manageable to have the test create those objects in code. 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. oh, well, creating the pool requires also creating all the epp and the rbac resources, so it is also complex... |
||
kind: InferencePool | ||
metadata: | ||
labels: | ||
name: vllm-llama3-8b-instruct | ||
spec: | ||
targetPortNumber: 8000 | ||
selector: | ||
app: vllm-llama3-8b-instruct | ||
extensionRef: | ||
name: vllm-llama3-8b-instruct-epp | ||
namespace: $E2E_NS | ||
--- | ||
apiVersion: v1 | ||
kind: Service | ||
metadata: | ||
name: vllm-llama3-8b-instruct-epp | ||
namespace: $E2E_NS | ||
spec: | ||
selector: | ||
app: vllm-llama3-8b-instruct-epp | ||
ports: | ||
- protocol: TCP | ||
port: 9002 | ||
targetPort: 9002 | ||
appProtocol: http2 | ||
type: ClusterIP | ||
--- | ||
apiVersion: apps/v1 | ||
kind: Deployment | ||
metadata: | ||
name: vllm-llama3-8b-instruct-epp | ||
namespace: $E2E_NS | ||
labels: | ||
app: vllm-llama3-8b-instruct-epp | ||
spec: | ||
replicas: 1 | ||
selector: | ||
matchLabels: | ||
app: vllm-llama3-8b-instruct-epp | ||
template: | ||
metadata: | ||
labels: | ||
app: vllm-llama3-8b-instruct-epp | ||
spec: | ||
# Conservatively, this timeout should mirror the longest grace period of the pods within the pool | ||
terminationGracePeriodSeconds: 130 | ||
containers: | ||
- name: epp | ||
image: us-central1-docker.pkg.dev/k8s-staging-images/gateway-api-inference-extension/epp:main | ||
imagePullPolicy: Always | ||
args: | ||
- -poolName | ||
- "vllm-llama3-8b-instruct" | ||
- -poolNamespace | ||
- "$E2E_NS" | ||
- -v | ||
- "4" | ||
- --zap-encoder | ||
- "json" | ||
- -grpcPort | ||
- "9002" | ||
- -grpcHealthPort | ||
- "9003" | ||
env: | ||
- name: USE_STREAMING | ||
value: "true" | ||
ports: | ||
- containerPort: 9002 | ||
- containerPort: 9003 | ||
- name: metrics | ||
containerPort: 9090 | ||
livenessProbe: | ||
grpc: | ||
port: 9003 | ||
service: inference-extension | ||
initialDelaySeconds: 5 | ||
periodSeconds: 10 | ||
readinessProbe: | ||
grpc: | ||
port: 9003 | ||
service: inference-extension | ||
initialDelaySeconds: 5 | ||
periodSeconds: 10 | ||
--- | ||
kind: ClusterRole | ||
apiVersion: rbac.authorization.k8s.io/v1 | ||
metadata: | ||
name: pod-read | ||
rules: | ||
- apiGroups: ["inference.networking.x-k8s.io"] | ||
resources: ["inferencemodels"] | ||
verbs: ["get", "watch", "list"] | ||
- apiGroups: [""] | ||
resources: ["pods"] | ||
verbs: ["get", "watch", "list"] | ||
- apiGroups: ["inference.networking.x-k8s.io"] | ||
resources: ["inferencepools"] | ||
verbs: ["get", "watch", "list"] | ||
- apiGroups: ["discovery.k8s.io"] | ||
resources: ["endpointslices"] | ||
verbs: ["get", "watch", "list"] | ||
- apiGroups: | ||
- authentication.k8s.io | ||
resources: | ||
- tokenreviews | ||
verbs: | ||
- create | ||
- apiGroups: | ||
- authorization.k8s.io | ||
resources: | ||
- subjectaccessreviews | ||
verbs: | ||
- create | ||
--- | ||
kind: ClusterRoleBinding | ||
apiVersion: rbac.authorization.k8s.io/v1 | ||
metadata: | ||
name: pod-read-binding | ||
subjects: | ||
- kind: ServiceAccount | ||
name: default | ||
namespace: $E2E_NS | ||
roleRef: | ||
kind: ClusterRole | ||
name: pod-read |
Uh oh!
There was an error while loading. Please reload this page.