Skip to content
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

Merged
merged 1 commit into from
Dec 12, 2018

Conversation

dushyanthsc
Copy link
Contributor

@dushyanthsc dushyanthsc commented Dec 1, 2018

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 server with path specific handlers.

@knative-prow-robot knative-prow-robot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Dec 1, 2018
@knative-prow-robot knative-prow-robot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Dec 1, 2018
@knative-prow-robot
Copy link
Contributor

[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 /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@knative-prow-robot knative-prow-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Dec 1, 2018
Copy link
Contributor

@knative-prow-robot knative-prow-robot left a 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.

@dushyanthsc
Copy link
Contributor Author

/assign @evankanderson @jessiezcc

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"}
Copy link
Contributor

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?

Copy link
Contributor Author

@dushyanthsc dushyanthsc Dec 3, 2018

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.

Copy link
Member

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.

Copy link
Contributor Author

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.

}

expectedOutputs = map[string]string{
"PORT" : "8080",
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Member

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?

Copy link
Contributor Author

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.


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"
Copy link
Member

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"?

Copy link
Contributor Author

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.

}

expectedOutputs = map[string]string{
"PORT" : "8080",
Copy link
Member

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?

expectedOutputs = map[string]string{
"PORT" : "8080",
}
if err = verifyResponse(resp, "MUST", expectedOutputs); err != nil {
Copy link
Member

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed it.

return errors.Errorf("Json Un-marshalling error : %v", jsonErr)
}

if len(expectedOutputs) != len(respMap) {
Copy link
Member

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:

  1. Have the target container simply return a JSON-encoded envvars map (object).
  2. 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{...} {
 ...
}

Copy link
Contributor Author

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.


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
Copy link
Member

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.

Copy link
Contributor Author

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.

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"}
Copy link
Member

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.

@dushyanthsc dushyanthsc changed the title WIP: EnvVars e2e test modification Moving envvars_test from e2e to conformance Dec 5, 2018
@knative-prow-robot knative-prow-robot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Dec 5, 2018
@dushyanthsc
Copy link
Contributor Author

/retest

@dushyanthsc
Copy link
Contributor Author

/retest

@dushyanthsc dushyanthsc force-pushed the e2e/envvar-update branch 2 times, most recently from d50656e to 8f4925d Compare December 6, 2018 17:42
@dushyanthsc
Copy link
Contributor Author

/retest

@dushyanthsc
Copy link
Contributor Author

/retest

@dushyanthsc dushyanthsc force-pushed the e2e/envvar-update branch 2 times, most recently from 4148168 to cbe48b2 Compare December 7, 2018 19:02
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.
@dushyanthsc
Copy link
Contributor Author

/retest

1 similar comment
@dushyanthsc
Copy link
Contributor Author

/retest

func TestMustEnvVars(t *testing.T) {
logger := logging.GetContextLogger("TestMustEnvVars")
var names test.ResourceNames
resp, err := fetchEnvInfo(t, logger, test.EnvImageEnvVarsPath, &names)
Copy link
Contributor

@jessiezcc jessiezcc Dec 12, 2018

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?

Copy link
Contributor Author

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) {
Copy link
Contributor

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?

Copy link
Contributor Author

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.

@jessiezcc
Copy link
Contributor

chatted with @dushyanthsc offline on review comments.
/lgtm

@knative-prow-robot knative-prow-robot added the lgtm Indicates that a PR is ready to be merged. label Dec 12, 2018
@knative-prow-robot knative-prow-robot merged commit d525d17 into knative:master Dec 12, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. lgtm Indicates that a PR is ready to be merged. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants