-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Moving envvars_test from e2e to conformance #2602
Moving envvars_test from e2e to conformance #2602
Conversation
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: dushyanthsc The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
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.
@dushyanthsc: 0 warnings.
In response to this:
Change to update the EnvVars e2e test to include all environment variables specified in run-time contract.
Proposed Changes
- Change e2e EnvVars test to include all environment variables specified in run-time contract.
- Separate "MUST" and "SHOULD" environment variables to handle them separately
- Update test/util to support serve with path specific handlers.
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.
/assign @evankanderson @jessiezcc |
test/test_images/envvars/envvars.go
Outdated
rev := os.Getenv("K_REVISION") | ||
fmt.Fprintf(w, "Here are our env vars service:%s - configuration:%s - revision:%s", svc, cfg, rev) | ||
//Environment variables that "SHOULD" be set by knative implementation | ||
var shouldSet = []string{ "K_SERVICE", "K_CONFIGURATION", "K_REVISION"} |
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.
shouldSet and mustSet are defined in both test_image and tests, can they somehow share the code?
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 did think of that, but I saw that OpenContainers use a different model where it looks like they do code-gen from spec. I was not sure if we would be moving to that model. Just as a layer of safety I have ensured that they match both in numbers and key-names, but I understand your point, will wait for Evan to comment to see whats the plan on having a single source of truth for specifying the expected keys.
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 don't think we have a plan yet for auto-generating conformance tests based on the spec. If you have a specific idea or proposal, I'd be interested, but I don't have the bandwidth to work on that in the next ~year.
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.
Got it. For this change taking into consideration your comment on a more permissive parsing model I have moved environment variables set to conformance/runtime_contact_types.go I will take a deeper look at how things are done in open-container and see if we can apply that or come up with a different approach as an action item.
test/e2e/envvars_test.go
Outdated
} | ||
|
||
expectedOutputs = map[string]string{ | ||
"PORT" : "8080", |
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.
from conformance perspective, my understanding is that as long as PORT is set, it's conformant, doesn't have to be 8080.
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.
The contract says "Ingress containerPort for ingress requests and health checks" and in the test image we create the service exposing ":8080" hence the check verifies the port number as well.
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.
Can you add a comment explaining why this MUST be 8080 (i.e. "8080 taken from ..., if you change that, this line also needs to change" or the like)?
Suggestion: maybe use a different port from 8080, to catch cases where the port has been hard-coded to 8080?
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 have moved the port value to be to a single file and referenced them in both test-image and the test. Also added comment explaining the value used for verification.
Regarding you suggestion, this issue: #2258 prohibits from using a different port. I have added a TODO in the code to change it when the above issue gets fixed.
873a18f
to
19640f8
Compare
test/e2e/envvars_test.go
Outdated
|
||
envVarsExpectedOutput := fmt.Sprintf("Here are our env vars service:%s - configuration:%s - revision:%s", names.Service, names.Config, names.Revision) | ||
domain := route.Status.Domain + "/envvars/should" |
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.
It's strange to call this "domain" -- maybe "url"?
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.
My bad, I re-used name from earlier code, I have fixed it now.
test/e2e/envvars_test.go
Outdated
} | ||
|
||
expectedOutputs = map[string]string{ | ||
"PORT" : "8080", |
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.
Can you add a comment explaining why this MUST be 8080 (i.e. "8080 taken from ..., if you change that, this line also needs to change" or the like)?
Suggestion: maybe use a different port from 8080, to catch cases where the port has been hard-coded to 8080?
test/e2e/envvars_test.go
Outdated
expectedOutputs = map[string]string{ | ||
"PORT" : "8080", | ||
} | ||
if err = verifyResponse(resp, "MUST", expectedOutputs); err != nil { |
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.
strange indent here. Run gofmt
?
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.
Fixed it.
test/e2e/envvars_test.go
Outdated
return errors.Errorf("Json Un-marshalling error : %v", jsonErr) | ||
} | ||
|
||
if len(expectedOutputs) != len(respMap) { |
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'd tend to lean towards a more permissive parsing model here. In particular, this test ends up spreading the should/must logic across both the test itself and the running container. It might be simpler to do the following:
- Have the target container simply return a JSON-encoded envvars map (object).
- Have the test decode the JSON with a "should" and a "must" struct, like so:
var should struct {
service string `json:"K_SERVICE"`
configuration string `json:"K_CONFIGURATION"`
revision string `json:"K_REVISION"`
}
var must struct {
port string `json:"PORT"`
}
if err := json.Unmarshal(payload, &should); err != nil {
...
}
if err := json.Unmarshal(payload, &must); err != nil {
...
}
if should != struct{...} {
...
}
if must != struct{...} {
...
}
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.
Makes sense, I have updated the verification to use this model.
test/test_images/envvars/README.md
Outdated
|
||
When called, the server emits a message containing the values of the environment variables for knative service, configuraiton and revision. | ||
'must' and 'should' refer to the keywords "MUST" and "SHOULD" used in the Knative [run-time contract](/docs/runtime-contract.md) and provides environment variables that "MUST" and "SHOULD" be set by a Knative implementations |
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'd prefer more generic interfaces on our test containers (e.g. one container that provides /envvars
, /grow
, /headers
, etc) rather than having a bunch of purpose-built containers, one for each test.
This would allow better re-use of the container code where we didn't need to write a new container for each new test.
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.
Makes sense, I have updated the test-image to be an environment test image that can be used to retrieve information about the environment in which the container runs. The server now exposes "/envvars" to fetch all the environment variables defined inside the container.
test/test_images/envvars/envvars.go
Outdated
rev := os.Getenv("K_REVISION") | ||
fmt.Fprintf(w, "Here are our env vars service:%s - configuration:%s - revision:%s", svc, cfg, rev) | ||
//Environment variables that "SHOULD" be set by knative implementation | ||
var shouldSet = []string{ "K_SERVICE", "K_CONFIGURATION", "K_REVISION"} |
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 don't think we have a plan yet for auto-generating conformance tests based on the spec. If you have a specific idea or proposal, I'd be interested, but I don't have the bandwidth to work on that in the next ~year.
b925d5a
to
d4691ad
Compare
/retest |
d4691ad
to
9ddaa86
Compare
/retest |
d50656e
to
8f4925d
Compare
/retest |
8f4925d
to
c6fecda
Compare
/retest |
4148168
to
cbe48b2
Compare
Change moves the envvars_test.go from e2e to conformance folder to use the test as a conformance test for the environment variables requirement specified in the run-time contract (https://github.com/knative/serving/blob/master/docs/runtime-contract.md) The test image is also changed to be more generic and provide a server that can be used to get information about the environment under which the container runs. Currently the iamge only exposes environment variables defined inside the container by exposing "/envvars" to fetch all the environment variables. The image folder name is also changed to "environment" to indicate this semantic change. Change also adds test/conformance/constants.go to define a way to have constants that can be shared between test-images and tests. Change also adds test/conformance/runtime_contract_types.go to define the runtime contract as go types.
cbe48b2
to
ef379bc
Compare
/retest |
1 similar comment
/retest |
func TestMustEnvVars(t *testing.T) { | ||
logger := logging.GetContextLogger("TestMustEnvVars") | ||
var names test.ResourceNames | ||
resp, err := fetchEnvInfo(t, logger, test.EnvImageEnvVarsPath, &names) |
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.
this value of resp is the same as what's in TestShouldEnvVars?
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.
The response from the environment test image is retrieving all the environment variables defined inside the container. And the type of object used for json.Unmarshall is determining what are environment variables of interest, in this case type MustEnvvars. The advantage of this is the next time we add/delete any environment variable from the list of SHOULD or MUST we would only have to change it in one place which is runtime_contract_types.go and everything else would just work.
) | ||
|
||
//TestShouldEnvVars verifies environment variables that are declared as "SHOULD be set" in runtime-contract | ||
func TestShouldEnvVars(t *testing.T) { |
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.
from code, I see that we validate Must and Should in a very similar way, i.e. check whether they are specified. I could be missing something. Can you call out the validation difference in comments so that it's obvious?
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.
The reason for breaking them into two tests is to adhere to the semantics in the runtime contract as they might have different policies (like SHOULD generating warnings and MUST generating failures). As this is still to be decided, the PR currently just breaks them into two tests and fails on both instances.
chatted with @dushyanthsc offline on review comments. |
Change to update the EnvVars e2e test to include all environment variables specified in run-time contract.
Proposed Changes