Repository: kubernetes/ingress-nginx
Pull request #5410 (2020-04-20 21:40:08)

Add support for IngressClass and ingress.class annotation
<!--- Provide a general summary of your changes in the Title above --->
<!--- Please don't @-mention people in PR or commit messages (do so in an additional comment). --->

## What this PR does / why we need it:

Add support for new IngressClass resource, keeping support for `ingress.class` annotation.

Ingress controller deployment flag: `--ingress-class=internal`
Existing ingresses with annotation: `kubernetes.io/ingress.class: "internal"`
New IngressClass:

```
apiVersion: networking.k8s.io/v1beta1
kind: IngressClass
metadata:
  name: "internal"
  namespace: "ingress-nginx"
spec:
  controller: "k8s.io/ingress-nginx"
```

The flag will be reused for the annotation and the new IngressClass resource.
The ingress controller will check the IngressClass on startup in the same namespace where is running

## Types of changes
<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
- [x] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)

## Which issue/s this PR fixes

replaces https://github.com/kubernetes/ingress-nginx/pull/5354

## How Has This Been Tested?
<!--- Please describe in detail how you tested your changes. -->
<!--- Include details of your testing environment, and the tests you ran to -->
<!--- see how your change affects other areas of the code, etc. -->

## Checklist:
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
- [ ] My change requires a change to the documentation.
- [ ] I have updated the documentation accordingly.
- [x] I've read the [CONTRIBUTION](https://github.com/kubernetes/ingress-nginx/blob/master/CONTRIBUTING.md) guide
- [x] I have added tests to cover my changes.
- [x] All new and existing tests passed.


k8s-ci-robot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/kubernetes/ingress-nginx/pull/5410#" title="Author self-approved">aledbf</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubernetes%2Fingress-nginx).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/kubernetes/ingress-nginx/blob/master/OWNERS)~~ [aledbf]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
k8s-ci-robot: @aledbf: The following test **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-ingress-nginx-test | 28903516fd3ed0ea51cd73316687a7af7833a3b6 | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/ingress-nginx/5410/pull-ingress-nginx-test/1252351391167418370) | `/test pull-ingress-nginx-test`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes&repo=ingress-nginx&pr=5410). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3aledbf). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes/ingress-nginx/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
codecov-io: # [Codecov](https://codecov.io/gh/kubernetes/ingress-nginx/pull/5410?src=pr&el=h1) Report
> Merging [#5410](https://codecov.io/gh/kubernetes/ingress-nginx/pull/5410?src=pr&el=desc) into [master](https://codecov.io/gh/kubernetes/ingress-nginx/commit/7e637e154b221ccbf3613bcea4357b5edd5301bc&el=desc) will **decrease** coverage by `0.06%`.
> The diff coverage is `71.42%`.

[![Impacted file tree graph](https://codecov.io/gh/kubernetes/ingress-nginx/pull/5410/graphs/tree.svg?width=650&height=150&src=pr&token=hseYbbkdXH)](https://codecov.io/gh/kubernetes/ingress-nginx/pull/5410?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master    #5410      +/-   ##
==========================================
- Coverage   58.64%   58.58%   -0.07%     
==========================================
  Files          88       88              
  Lines        6913     6905       -8     
==========================================
- Hits         4054     4045       -9     
- Misses       2414     2415       +1     
  Partials      445      445              
```


| [Impacted Files](https://codecov.io/gh/kubernetes/ingress-nginx/pull/5410?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [internal/ingress/controller/store/store.go](https://codecov.io/gh/kubernetes/ingress-nginx/pull/5410/diff?src=pr&el=tree#diff-aW50ZXJuYWwvaW5ncmVzcy9jb250cm9sbGVyL3N0b3JlL3N0b3JlLmdv) | `59.78% <ø> (-0.30%)` | :arrow_down: |
| [internal/ingress/controller/template/template.go](https://codecov.io/gh/kubernetes/ingress-nginx/pull/5410/diff?src=pr&el=tree#diff-aW50ZXJuYWwvaW5ncmVzcy9jb250cm9sbGVyL3RlbXBsYXRlL3RlbXBsYXRlLmdv) | `80.10% <ø> (ø)` | |
| [internal/ingress/annotations/class/main.go](https://codecov.io/gh/kubernetes/ingress-nginx/pull/5410/diff?src=pr&el=tree#diff-aW50ZXJuYWwvaW5ncmVzcy9hbm5vdGF0aW9ucy9jbGFzcy9tYWluLmdv) | `66.66% <71.42%> (-22.23%)` | :arrow_down: |
| [internal/ingress/controller/controller.go](https://codecov.io/gh/kubernetes/ingress-nginx/pull/5410/diff?src=pr&el=tree#diff-aW50ZXJuYWwvaW5ncmVzcy9jb250cm9sbGVyL2NvbnRyb2xsZXIuZ28=) | `49.28% <0.00%> (-0.12%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/kubernetes/ingress-nginx/pull/5410?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/kubernetes/ingress-nginx/pull/5410?src=pr&el=footer). Last update [837d370...3112fff](https://codecov.io/gh/kubernetes/ingress-nginx/pull/5410?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

k8s-ci-robot: @aledbf: The following test **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-ingress-nginx-e2e-1-17 | 3112fff24b0808da32e3a1672cc1b05233e1eb3a | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/ingress-nginx/5410/pull-ingress-nginx-e2e-1-17/1252353941102923776) | `/test pull-ingress-nginx-e2e-1-17`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes&repo=ingress-nginx&pr=5410). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3aledbf). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes/ingress-nginx/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @aledbf: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-ingress-nginx-e2e-1-17 | 3112fff24b0808da32e3a1672cc1b05233e1eb3a | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/ingress-nginx/5410/pull-ingress-nginx-e2e-1-17/1252353941102923776) | `/test pull-ingress-nginx-e2e-1-17`
pull-ingress-nginx-e2e-1-15 | 3112fff24b0808da32e3a1672cc1b05233e1eb3a | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/ingress-nginx/5410/pull-ingress-nginx-e2e-1-15/1252353941090340864) | `/test pull-ingress-nginx-e2e-1-15`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes&repo=ingress-nginx&pr=5410). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3aledbf). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes/ingress-nginx/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @aledbf: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-ingress-nginx-e2e-1-17 | 3112fff24b0808da32e3a1672cc1b05233e1eb3a | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/ingress-nginx/5410/pull-ingress-nginx-e2e-1-17/1252353941102923776) | `/test pull-ingress-nginx-e2e-1-17`
pull-ingress-nginx-e2e-1-15 | 3112fff24b0808da32e3a1672cc1b05233e1eb3a | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/ingress-nginx/5410/pull-ingress-nginx-e2e-1-15/1252353941090340864) | `/test pull-ingress-nginx-e2e-1-15`
pull-ingress-nginx-e2e-1-18 | 3112fff24b0808da32e3a1672cc1b05233e1eb3a | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/ingress-nginx/5410/pull-ingress-nginx-e2e-1-18/1252353941073563648) | `/test pull-ingress-nginx-e2e-1-18`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes&repo=ingress-nginx&pr=5410). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3aledbf). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes/ingress-nginx/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @aledbf: The following test **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-ingress-nginx-e2e-1-18 | f938fdc55026591c90a7d101cda66fdb2c80060b | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/ingress-nginx/5410/pull-ingress-nginx-e2e-1-18/1252405499270270976) | `/test pull-ingress-nginx-e2e-1-18`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes&repo=ingress-nginx&pr=5410). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3aledbf). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes/ingress-nginx/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @aledbf: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-ingress-nginx-e2e-1-18 | f938fdc55026591c90a7d101cda66fdb2c80060b | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/ingress-nginx/5410/pull-ingress-nginx-e2e-1-18/1252405499270270976) | `/test pull-ingress-nginx-e2e-1-18`
pull-ingress-nginx-e2e-1-16 | f938fdc55026591c90a7d101cda66fdb2c80060b | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/ingress-nginx/5410/pull-ingress-nginx-e2e-1-16/1252405499278659584) | `/test pull-ingress-nginx-e2e-1-16`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes&repo=ingress-nginx&pr=5410). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3aledbf). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes/ingress-nginx/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
aledbf: /retest
k8s-ci-robot: @aledbf: The following test **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-ingress-nginx-e2e-1-18 | cfc90c98ef557ed7965063d7a17db59cac1707cb | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/ingress-nginx/5410/pull-ingress-nginx-e2e-1-18/1252649860566355968) | `/test pull-ingress-nginx-e2e-1-18`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes&repo=ingress-nginx&pr=5410). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3aledbf). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes/ingress-nginx/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @aledbf: The following test **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-ingress-nginx-e2e-1-18 | d714e8312315c6186e36afac81ce99f1f02d04df | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/ingress-nginx/5410/pull-ingress-nginx-e2e-1-18/1252691277502222336) | `/test pull-ingress-nginx-e2e-1-18`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes&repo=ingress-nginx&pr=5410). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3aledbf). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes/ingress-nginx/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @aledbf: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-ingress-nginx-e2e-1-18 | d714e8312315c6186e36afac81ce99f1f02d04df | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/ingress-nginx/5410/pull-ingress-nginx-e2e-1-18/1252691277502222336) | `/test pull-ingress-nginx-e2e-1-18`
pull-ingress-nginx-e2e-1-17 | d714e8312315c6186e36afac81ce99f1f02d04df | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/ingress-nginx/5410/pull-ingress-nginx-e2e-1-17/1252691277523193856) | `/test pull-ingress-nginx-e2e-1-17`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes&repo=ingress-nginx&pr=5410). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3aledbf). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes/ingress-nginx/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @aledbf: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-ingress-nginx-e2e-1-16 | 84d5df4052b5e9766c8474b9668cce156a629b90 | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/ingress-nginx/5410/pull-ingress-nginx-e2e-1-16/1252739596207263744) | `/test pull-ingress-nginx-e2e-1-16`
pull-ingress-nginx-e2e-1-15 | 84d5df4052b5e9766c8474b9668cce156a629b90 | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/ingress-nginx/5410/pull-ingress-nginx-e2e-1-15/1252739596219846656) | `/test pull-ingress-nginx-e2e-1-15`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes&repo=ingress-nginx&pr=5410). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3aledbf). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes/ingress-nginx/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
aledbf: /retest
aledbf: /assign @ElvinEfendi 
k8s-ci-robot: @aledbf: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-ingress-nginx-e2e-1-16 | 84d5df4052b5e9766c8474b9668cce156a629b90 | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/ingress-nginx/5410/pull-ingress-nginx-e2e-1-16/1252739596207263744) | `/test pull-ingress-nginx-e2e-1-16`
pull-ingress-nginx-e2e-1-15 | 84d5df4052b5e9766c8474b9668cce156a629b90 | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/ingress-nginx/5410/pull-ingress-nginx-e2e-1-15/1252768159199399936) | `/test pull-ingress-nginx-e2e-1-15`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes&repo=ingress-nginx&pr=5410). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3aledbf). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes/ingress-nginx/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @aledbf: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-ingress-nginx-e2e-1-15 | 84d5df4052b5e9766c8474b9668cce156a629b90 | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/ingress-nginx/5410/pull-ingress-nginx-e2e-1-15/1252768159199399936) | `/test pull-ingress-nginx-e2e-1-15`
pull-ingress-nginx-e2e-1-16 | 84d5df4052b5e9766c8474b9668cce156a629b90 | [link](https://prow.k8s.io/view/gcs/kubernetes-jenkins/pr-logs/pull/ingress-nginx/5410/pull-ingress-nginx-e2e-1-16/1252768159211982848) | `/test pull-ingress-nginx-e2e-1-16`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes&repo=ingress-nginx&pr=5410). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3aledbf). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes/ingress-nginx/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
aledbf: /retest
ElvinEfendi: For context:
 - https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class, 
 - https://github.com/kubernetes/ingress-nginx/pull/5307, 
 - https://github.com/kubernetes/kubernetes/blob/d911254debefb5b630498aa3552899ee2f99f22e/pkg/apis/networking/types.go#L273-L304, 

Patch:
diff --git a/charts/ingress-nginx/templates/clusterrole.yaml b/charts/ingress-nginx/templates/clusterrole.yaml
index fe7c5f511..2035f549a 100644
--- a/charts/ingress-nginx/templates/clusterrole.yaml
+++ b/charts/ingress-nginx/templates/clusterrole.yaml
@@ -65,4 +65,12 @@ rules:
       - ingresses/status
     verbs:
       - update
+  - apiGroups:
+      - "networking.k8s.io" # k8s 1.14+
+    resources:
+      - ingressclasses
+    verbs:
+      - get
+      - list
+      - watch
 {{- end }}
diff --git a/charts/ingress-nginx/templates/controller-role.yaml b/charts/ingress-nginx/templates/controller-role.yaml
index 4d313a961..f2e392744 100644
--- a/charts/ingress-nginx/templates/controller-role.yaml
+++ b/charts/ingress-nginx/templates/controller-role.yaml
@@ -49,6 +49,14 @@ rules:
       - ingresses/status
     verbs:
       - update
+  - apiGroups:
+      - "networking.k8s.io" # k8s 1.14+
+    resources:
+      - ingressclasses
+    verbs:
+      - get
+      - list
+      - watch
   - apiGroups:
       - ""
     resources:
diff --git a/cmd/nginx/main.go b/cmd/nginx/main.go
index b6811d394..d67b17232 100644
--- a/cmd/nginx/main.go
+++ b/cmd/nginx/main.go
@@ -29,7 +29,6 @@ import (
 
 	"github.com/prometheus/client_golang/prometheus"
 	"github.com/prometheus/client_golang/prometheus/promhttp"
-
 	"k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/util/wait"
@@ -42,6 +41,7 @@ import (
 	"k8s.io/klog"
 
 	"k8s.io/ingress-nginx/internal/file"
+	"k8s.io/ingress-nginx/internal/ingress/annotations/class"
 	"k8s.io/ingress-nginx/internal/ingress/controller"
 	"k8s.io/ingress-nginx/internal/ingress/metric"
 	"k8s.io/ingress-nginx/internal/k8s"
@@ -87,8 +87,10 @@ func main() {
 			if errors.IsUnauthorized(err) || errors.IsForbidden(err) {
 				klog.Fatal("✖ The cluster seems to be running with a restrictive Authorization mode and the Ingress controller does not have the required permissions to operate normally.")
 			}
+
 			klog.Fatalf("No service with name %v found: %v", conf.DefaultService, err)
 		}
+
 		klog.Infof("Validated %v as the default backend.", conf.DefaultService)
 	}
 
@@ -107,8 +109,28 @@ func main() {
 		klog.Warningf("Using deprecated \"k8s.io/api/extensions/v1beta1\" package because Kubernetes version is < v1.14.0")
 	}
 
-	if !k8s.IsIngressV1Ready {
-		klog.Infof("Enabling new Ingress features availables since v1.18.0")
+	if k8s.IsIngressV1Ready {
+		klog.Infof("Enabling new Ingress features available since Kubernetes v1.18")
+		k8s.IngressClass, err = kubeClient.NetworkingV1beta1().IngressClasses().
+			Get(context.TODO(), class.IngressClass, metav1.GetOptions{})
+		if err != nil {
+			if !errors.IsNotFound(err) {
+				if !errors.IsUnauthorized(err) && !errors.IsForbidden(err) {
+					klog.Fatalf("Error searching IngressClass: %v", err)
+				}
+
+				klog.Errorf("Unexpected error searching IngressClass: %v", err)
+			}
+
+			klog.Warningf("No IngressClass resource with name %v found. Only annotation will be used.", class.IngressClass)
+
+			// TODO: remove once this is fixed in client-go
+			k8s.IngressClass = nil
+		}
+
+		if k8s.IngressClass != nil && k8s.IngressClass.Spec.Controller != k8s.IngressNGINXController {
+			klog.Fatalf("IngressClass with name %v is not valid for ingress-nginx (invalid Spec.Controller)", class.IngressClass)
+		}
 	}
 
 	conf.Client = kubeClient
diff --git a/deploy/static/provider/aws/deploy-tls-termination.yaml b/deploy/static/provider/aws/deploy-tls-termination.yaml
index 4aed810e2..a30240596 100644
--- a/deploy/static/provider/aws/deploy-tls-termination.yaml
+++ b/deploy/static/provider/aws/deploy-tls-termination.yaml
@@ -106,6 +106,14 @@ rules:
       - ingresses/status
     verbs:
       - update
+  - apiGroups:
+      - networking.k8s.io   # k8s 1.14+
+    resources:
+      - ingressclasses
+    verbs:
+      - get
+      - list
+      - watch
 ---
 # Source: ingress-nginx/templates/clusterrolebinding.yaml
 apiVersion: rbac.authorization.k8s.io/v1
@@ -184,6 +192,14 @@ rules:
       - ingresses/status
     verbs:
       - update
+  - apiGroups:
+      - networking.k8s.io   # k8s 1.14+
+    resources:
+      - ingressclasses
+    verbs:
+      - get
+      - list
+      - watch
   - apiGroups:
       - ''
     resources:
diff --git a/deploy/static/provider/aws/deploy.yaml b/deploy/static/provider/aws/deploy.yaml
index 518457978..1dc44cb0b 100644
--- a/deploy/static/provider/aws/deploy.yaml
+++ b/deploy/static/provider/aws/deploy.yaml
@@ -99,6 +99,14 @@ rules:
       - ingresses/status
     verbs:
       - update
+  - apiGroups:
+      - networking.k8s.io   # k8s 1.14+
+    resources:
+      - ingressclasses
+    verbs:
+      - get
+      - list
+      - watch
 ---
 # Source: ingress-nginx/templates/clusterrolebinding.yaml
 apiVersion: rbac.authorization.k8s.io/v1
@@ -177,6 +185,14 @@ rules:
       - ingresses/status
     verbs:
       - update
+  - apiGroups:
+      - networking.k8s.io   # k8s 1.14+
+    resources:
+      - ingressclasses
+    verbs:
+      - get
+      - list
+      - watch
   - apiGroups:
       - ''
     resources:
diff --git a/deploy/static/provider/baremetal/deploy.yaml b/deploy/static/provider/baremetal/deploy.yaml
index ff9de1efd..406bf18be 100644
--- a/deploy/static/provider/baremetal/deploy.yaml
+++ b/deploy/static/provider/baremetal/deploy.yaml
@@ -99,6 +99,14 @@ rules:
       - ingresses/status
     verbs:
       - update
+  - apiGroups:
+      - networking.k8s.io   # k8s 1.14+
+    resources:
+      - ingressclasses
+    verbs:
+      - get
+      - list
+      - watch
 ---
 # Source: ingress-nginx/templates/clusterrolebinding.yaml
 apiVersion: rbac.authorization.k8s.io/v1
@@ -177,6 +185,14 @@ rules:
       - ingresses/status
     verbs:
       - update
+  - apiGroups:
+      - networking.k8s.io   # k8s 1.14+
+    resources:
+      - ingressclasses
+    verbs:
+      - get
+      - list
+      - watch
   - apiGroups:
       - ''
     resources:
diff --git a/deploy/static/provider/cloud/deploy.yaml b/deploy/static/provider/cloud/deploy.yaml
index 845e5d4fb..27b6ac38b 100644
--- a/deploy/static/provider/cloud/deploy.yaml
+++ b/deploy/static/provider/cloud/deploy.yaml
@@ -99,6 +99,14 @@ rules:
       - ingresses/status
     verbs:
       - update
+  - apiGroups:
+      - networking.k8s.io   # k8s 1.14+
+    resources:
+      - ingressclasses
+    verbs:
+      - get
+      - list
+      - watch
 ---
 # Source: ingress-nginx/templates/clusterrolebinding.yaml
 apiVersion: rbac.authorization.k8s.io/v1
@@ -177,6 +185,14 @@ rules:
       - ingresses/status
     verbs:
       - update
+  - apiGroups:
+      - networking.k8s.io   # k8s 1.14+
+    resources:
+      - ingressclasses
+    verbs:
+      - get
+      - list
+      - watch
   - apiGroups:
       - ''
     resources:
diff --git a/deploy/static/provider/kind/deploy.yaml b/deploy/static/provider/kind/deploy.yaml
index 2cf3661bc..29140c213 100644
--- a/deploy/static/provider/kind/deploy.yaml
+++ b/deploy/static/provider/kind/deploy.yaml
@@ -99,6 +99,14 @@ rules:
       - ingresses/status
     verbs:
       - update
+  - apiGroups:
+      - networking.k8s.io   # k8s 1.14+
+    resources:
+      - ingressclasses
+    verbs:
+      - get
+      - list
+      - watch
 ---
 # Source: ingress-nginx/templates/clusterrolebinding.yaml
 apiVersion: rbac.authorization.k8s.io/v1
@@ -177,6 +185,14 @@ rules:
       - ingresses/status
     verbs:
       - update
+  - apiGroups:
+      - networking.k8s.io   # k8s 1.14+
+    resources:
+      - ingressclasses
+    verbs:
+      - get
+      - list
+      - watch
   - apiGroups:
       - ''
     resources:
diff --git a/internal/ingress/annotations/class/main.go b/internal/ingress/annotations/class/main.go
index a20507d13..8c0684af3 100644
--- a/internal/ingress/annotations/class/main.go
+++ b/internal/ingress/annotations/class/main.go
@@ -18,6 +18,7 @@ package class
 
 import (
 	networking "k8s.io/api/networking/v1beta1"
+	"k8s.io/ingress-nginx/internal/k8s"
 )
 
 const (
@@ -37,30 +38,30 @@ var (
 	IngressClass = "nginx"
 )
 
-// IsValid returns true if the given Ingress either doesn't specify
-// the ingress.class annotation, or it's set to the configured in the
-// ingress controller.
+// IsValid returns true if the given Ingress specify the ingress.class
+// annotation or IngressClassName resource for Kubernetes >= v1.18
 func IsValid(ing *networking.Ingress) bool {
-	className := ing.Spec.IngressClassName
+	// 1. with annotation
+	ingress, ok := ing.GetAnnotations()[IngressKey]
+	if ok {
+		// empty annotation and same annotation on ingress
+		if ingress == "" && IngressClass == DefaultClass {
+			return true
+		}
 
-	// we have 2 valid combinations
-	// 1 - ingress with default class | blank annotation on ingress
-	// 2 - ingress with specific class | same annotation on ingress
-	//
-	// and 2 invalid combinations
-	// 3 - ingress with default class | fixed annotation on ingress
-	// 4 - ingress with specific class | different annotation on ingress
-	if className != nil {
-		return *className == IngressClass
+		return ingress == IngressClass
 	}
 
-	if IngressClass == DefaultClass {
-		return true
+	// 2. k8s < v1.18. Check default annotation
+	if !k8s.IsIngressV1Ready {
+		return IngressClass == DefaultClass
 	}
 
-	if IngressClass == "" {
-		return true
+	// 3. without annotation and IngressClass. Check default annotation
+	if k8s.IngressClass == nil {
+		return IngressClass == DefaultClass
 	}
 
-	return false
+	// 4. with IngressClass
+	return k8s.IngressClass.Name == *ing.Spec.IngressClassName
 }
diff --git a/internal/ingress/controller/store/store.go b/internal/ingress/controller/store/store.go
index 0a8fb117f..1cb6c4d5f 100644
--- a/internal/ingress/controller/store/store.go
+++ b/internal/ingress/controller/store/store.go
@@ -949,30 +949,18 @@ func toIngress(obj interface{}) (*networkingv1beta1.Ingress, bool) {
 			return nil, false
 		}
 
-		ing.Spec.IngressClassName = extractClassName(ing)
 		setDefaultPathTypeIfEmpty(ing)
-
 		return ing, true
 	}
 
 	if ing, ok := obj.(*networkingv1beta1.Ingress); ok {
-		ing.Spec.IngressClassName = extractClassName(ing)
 		setDefaultPathTypeIfEmpty(ing)
-
 		return ing, true
 	}
 
 	return nil, false
 }
 
-func extractClassName(ing *networkingv1beta1.Ingress) *string {
-	if c, ok := ing.Annotations[class.IngressKey]; ok {
-		return &c
-	}
-
-	return nil
-}
-
 // Default path type is Prefix to not break existing definitions
 var defaultPathType = networkingv1beta1.PathTypePrefix
 
diff --git a/internal/k8s/main.go b/internal/k8s/main.go
index a62bcf531..c1b8d9c83 100644
--- a/internal/k8s/main.go
+++ b/internal/k8s/main.go
@@ -25,6 +25,7 @@ import (
 	"k8s.io/klog"
 
 	apiv1 "k8s.io/api/core/v1"
+	networkingv1beta1 "k8s.io/api/networking/v1beta1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/util/version"
 	clientset "k8s.io/client-go/kubernetes"
@@ -121,6 +122,13 @@ var IsNetworkingIngressAvailable bool
 // IsIngressV1Ready indicates if the running Kubernetes version is at least v1.18.0
 var IsIngressV1Ready bool
 
+// IngressClass indicates the class of the Ingress to use as filter
+var IngressClass *networkingv1beta1.IngressClass
+
+// IngressNGINXController defines the valid value of IngressClass
+// Controller field for ingress-nginx
+const IngressNGINXController = "k8s.io/ingress-nginx"
+
 // NetworkingIngressAvailable checks if the package "k8s.io/api/networking/v1beta1"
 // is available or not and if Ingress V1 is supported (k8s >= v1.18.0)
 func NetworkingIngressAvailable(client clientset.Interface) (bool, bool) {


Test patch:
diff --git a/internal/ingress/annotations/class/main_test.go b/internal/ingress/annotations/class/main_test.go
index c4c95e39e..f38eeb790 100644
--- a/internal/ingress/annotations/class/main_test.go
+++ b/internal/ingress/annotations/class/main_test.go
@@ -54,10 +54,10 @@ func TestIsValidClass(t *testing.T) {
 		},
 	}
 
+	data := map[string]string{}
+	ing.SetAnnotations(data)
 	for _, test := range tests {
-		if test.ingress != "" {
-			ing.Spec.IngressClassName = &test.ingress
-		}
+		ing.Annotations[IngressKey] = test.ingress
 
 		IngressClass = test.controller
 		DefaultClass = test.defClass
diff --git a/internal/ingress/controller/controller_test.go b/internal/ingress/controller/controller_test.go
index ac5654298..356c088a2 100644
--- a/internal/ingress/controller/controller_test.go
+++ b/internal/ingress/controller/controller_test.go
@@ -190,8 +190,7 @@ func TestCheckIngress(t *testing.T) {
 	}
 
 	t.Run("When the ingress class differs from nginx", func(t *testing.T) {
-		class := "different"
-		ing.Spec.IngressClassName = &class
+		ing.ObjectMeta.Annotations["kubernetes.io/ingress.class"] = "different"
 		nginx.command = testNginxTestCommand{
 			t:   t,
 			err: fmt.Errorf("test error"),
@@ -202,8 +201,7 @@ func TestCheckIngress(t *testing.T) {
 	})
 
 	t.Run("when the class is the nginx one", func(t *testing.T) {
-		class := "nginx"
-		ing.Spec.IngressClassName = &class
+		ing.ObjectMeta.Annotations["kubernetes.io/ingress.class"] = "nginx"
 		nginx.command = testNginxTestCommand{
 			t:        t,
 			err:      nil,
diff --git a/test/e2e/framework/exec.go b/test/e2e/framework/exec.go
index 1e7bedbb1..73faf4eeb 100644
--- a/test/e2e/framework/exec.go
+++ b/test/e2e/framework/exec.go
@@ -55,7 +55,7 @@ func (f *Framework) GetLbAlgorithm(serviceName string, servicePort int) (string,
 
 // ExecIngressPod executes a command inside the first container in ingress controller running pod
 func (f *Framework) ExecIngressPod(command string) (string, error) {
-	pod, err := getIngressNGINXPod(f.Namespace, f.KubeClientSet)
+	pod, err := GetIngressNGINXPod(f.Namespace, f.KubeClientSet)
 	if err != nil {
 		return "", err
 	}
diff --git a/test/e2e/framework/framework.go b/test/e2e/framework/framework.go
index 672381536..8433e0a93 100644
--- a/test/e2e/framework/framework.go
+++ b/test/e2e/framework/framework.go
@@ -35,6 +35,7 @@ import (
 	"k8s.io/apimachinery/pkg/util/wait"
 	"k8s.io/client-go/kubernetes"
 	restclient "k8s.io/client-go/rest"
+	"k8s.io/ingress-nginx/internal/k8s"
 	"k8s.io/klog"
 )
 
@@ -56,6 +57,8 @@ var (
 type Framework struct {
 	BaseName string
 
+	IsIngressV1Ready bool
+
 	// A Kubernetes and Service Catalog client
 	KubeClientSet          kubernetes.Interface
 	KubeConfig             *restclient.Config
@@ -78,10 +81,13 @@ func NewDefaultFramework(baseName string) *Framework {
 	kubeClient, err := kubernetes.NewForConfig(kubeConfig)
 	assert.Nil(ginkgo.GinkgoT(), err, "creating Kubernetes API client")
 
+	_, isIngressV1Ready := k8s.NetworkingIngressAvailable(kubeClient)
+
 	f := &Framework{
-		BaseName:      baseName,
-		KubeConfig:    kubeConfig,
-		KubeClientSet: kubeClient,
+		BaseName:         baseName,
+		KubeConfig:       kubeConfig,
+		KubeClientSet:    kubeClient,
+		IsIngressV1Ready: isIngressV1Ready,
 	}
 
 	ginkgo.BeforeEach(f.BeforeEach)
@@ -109,7 +115,7 @@ func (f *Framework) BeforeEach() {
 // AfterEach deletes the namespace, after reading its events.
 func (f *Framework) AfterEach() {
 	if ginkgo.CurrentGinkgoTestDescription().Failed {
-		pod, err := getIngressNGINXPod(f.Namespace, f.KubeClientSet)
+		pod, err := GetIngressNGINXPod(f.Namespace, f.KubeClientSet)
 		if err != nil {
 			Logf("Unexpected error searching for ingress controller pod: %v", err)
 			return
@@ -221,7 +227,7 @@ func (f *Framework) WaitForNginxCustomConfiguration(from string, to string, matc
 }
 
 func nginxLogs(client kubernetes.Interface, namespace string) (string, error) {
-	pod, err := getIngressNGINXPod(namespace, client)
+	pod, err := GetIngressNGINXPod(namespace, client)
 	if err != nil {
 		return "", err
 	}
@@ -240,7 +246,7 @@ func (f *Framework) NginxLogs() (string, error) {
 
 func (f *Framework) matchNginxConditions(name string, matcher func(cfg string) bool) wait.ConditionFunc {
 	return func() (bool, error) {
-		pod, err := getIngressNGINXPod(f.Namespace, f.KubeClientSet)
+		pod, err := GetIngressNGINXPod(f.Namespace, f.KubeClientSet)
 		if err != nil {
 			return false, nil
 		}
@@ -272,7 +278,7 @@ func (f *Framework) matchNginxConditions(name string, matcher func(cfg string) b
 
 func (f *Framework) matchNginxCustomConditions(from string, to string, matcher func(cfg string) bool) wait.ConditionFunc {
 	return func() (bool, error) {
-		pod, err := getIngressNGINXPod(f.Namespace, f.KubeClientSet)
+		pod, err := GetIngressNGINXPod(f.Namespace, f.KubeClientSet)
 		if err != nil {
 			return false, nil
 		}
@@ -367,14 +373,14 @@ func (f *Framework) UpdateNginxConfigMapData(key string, value string) {
 // Grace period to wait for pod shutdown is in seconds.
 func (f *Framework) DeleteNGINXPod(grace int64) {
 	ns := f.Namespace
-	pod, err := getIngressNGINXPod(ns, f.KubeClientSet)
+	pod, err := GetIngressNGINXPod(ns, f.KubeClientSet)
 	assert.Nil(ginkgo.GinkgoT(), err, "expected ingress nginx pod to be running")
 
 	err = f.KubeClientSet.CoreV1().Pods(ns).Delete(context.TODO(), pod.GetName(), *metav1.NewDeleteOptions(grace))
 	assert.Nil(ginkgo.GinkgoT(), err, "deleting ingress nginx pod")
 
 	err = wait.Poll(Poll, DefaultTimeout, func() (bool, error) {
-		pod, err := getIngressNGINXPod(ns, f.KubeClientSet)
+		pod, err := GetIngressNGINXPod(ns, f.KubeClientSet)
 		if err != nil || pod == nil {
 			return false, nil
 		}
diff --git a/test/e2e/framework/k8s.go b/test/e2e/framework/k8s.go
index 818f31ff6..a75204ede 100644
--- a/test/e2e/framework/k8s.go
+++ b/test/e2e/framework/k8s.go
@@ -213,7 +213,8 @@ func podRunningReady(p *core.Pod) (bool, error) {
 	return true, nil
 }
 
-func getIngressNGINXPod(ns string, kubeClientSet kubernetes.Interface) (*core.Pod, error) {
+// GetIngressNGINXPod returns the ingress controller running pod
+func GetIngressNGINXPod(ns string, kubeClientSet kubernetes.Interface) (*core.Pod, error) {
 	l, err := kubeClientSet.CoreV1().Pods(ns).List(context.TODO(), metav1.ListOptions{
 		LabelSelector: "app.kubernetes.io/name=ingress-nginx",
 	})
diff --git a/test/e2e/settings/ingress_class.go b/test/e2e/settings/ingress_class.go
index f2b584db7..09c38f1c1 100644
--- a/test/e2e/settings/ingress_class.go
+++ b/test/e2e/settings/ingress_class.go
@@ -18,27 +18,51 @@ package settings
 
 import (
 	"context"
+	"fmt"
 	"net/http"
 	"strings"
+	"time"
 
 	"github.com/onsi/ginkgo"
 	"github.com/stretchr/testify/assert"
 	appsv1 "k8s.io/api/apps/v1"
+	networking "k8s.io/api/networking/v1beta1"
+	rbacv1 "k8s.io/api/rbac/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 
 	"k8s.io/ingress-nginx/internal/ingress/annotations/class"
+	"k8s.io/ingress-nginx/internal/k8s"
 	"k8s.io/ingress-nginx/test/e2e/framework"
 )
 
 var _ = framework.IngressNginxDescribe("[Flag] ingress-class", func() {
 	f := framework.NewDefaultFramework("ingress-class")
 
+	f.KubeClientSet.RbacV1().ClusterRoles().Create(context.TODO(), &rbacv1.ClusterRole{
+		ObjectMeta: metav1.ObjectMeta{Name: "ingress-nginx-class"},
+		Rules: []rbacv1.PolicyRule{{
+			APIGroups: []string{"networking.k8s.io"},
+			Resources: []string{"ingressclasses"},
+			Verbs:     []string{"get", "list", "watch"},
+		}},
+	}, metav1.CreateOptions{})
+
+	f.KubeClientSet.RbacV1().ClusterRoleBindings().Create(context.TODO(), &rbacv1.ClusterRoleBinding{
+		ObjectMeta: metav1.ObjectMeta{
+			Name: "ingress-nginx-class",
+		},
+		RoleRef: rbacv1.RoleRef{
+			APIGroup: "rbac.authorization.k8s.io",
+			Kind:     "ClusterRole",
+			Name:     "ingress-nginx-class",
+		},
+	}, metav1.CreateOptions{})
+
 	ginkgo.BeforeEach(func() {
 		f.NewEchoDeploymentWithReplicas(1)
 	})
 
 	ginkgo.Context("Without a specific ingress-class", func() {
-
 		ginkgo.It("should ignore Ingress with class", func() {
 			invalidHost := "foo"
 			annotations := map[string]string{
@@ -74,7 +98,15 @@ var _ = framework.IngressNginxDescribe("[Flag] ingress-class", func() {
 		ginkgo.BeforeEach(func() {
 			err := framework.UpdateDeployment(f.KubeClientSet, f.Namespace, "nginx-ingress-controller", 1,
 				func(deployment *appsv1.Deployment) error {
-					args := deployment.Spec.Template.Spec.Containers[0].Args
+					args := []string{}
+					for _, v := range deployment.Spec.Template.Spec.Containers[0].Args {
+						if strings.Contains(v, "--ingress-class") {
+							continue
+						}
+
+						args = append(args, v)
+					}
+
 					args = append(args, "--ingress-class=testclass")
 					deployment.Spec.Template.Spec.Containers[0].Args = args
 					_, err := f.KubeClientSet.AppsV1().Deployments(f.Namespace).Update(context.TODO(), deployment, metav1.UpdateOptions{})
@@ -154,4 +186,149 @@ var _ = framework.IngressNginxDescribe("[Flag] ingress-class", func() {
 				Status(http.StatusNotFound)
 		})
 	})
+
+	ginkgo.It("check scenarios for IngressClass and ingress.class annotation", func() {
+		if !f.IsIngressV1Ready {
+			ginkgo.Skip("Test requires Kubernetes v1.18 or higher")
+		}
+
+		ingressClassName := "test-new-ingress-class"
+
+		ingressClass, err := f.KubeClientSet.NetworkingV1beta1().IngressClasses().
+			Create(context.TODO(), &networking.IngressClass{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: ingressClassName,
+				},
+				Spec: networking.IngressClassSpec{
+					Controller: k8s.IngressNGINXController,
+				},
+			}, metav1.CreateOptions{})
+
+		if ingressClass == nil {
+			assert.Nil(ginkgo.GinkgoT(), err, "creating IngressClass")
+		}
+
+		pod, err := framework.GetIngressNGINXPod(f.Namespace, f.KubeClientSet)
+		assert.Nil(ginkgo.GinkgoT(), err, "searching ingress controller pod")
+		serviceAccount := pod.Spec.ServiceAccountName
+
+		crb, err := f.KubeClientSet.RbacV1().ClusterRoleBindings().Get(context.Background(), "ingress-nginx-class", metav1.GetOptions{})
+		assert.Nil(ginkgo.GinkgoT(), err, "searching cluster role binding")
+
+		// add service of current namespace
+		crb.Subjects = append(crb.Subjects, rbacv1.Subject{
+			APIGroup:  "",
+			Kind:      "ServiceAccount",
+			Name:      serviceAccount,
+			Namespace: f.Namespace,
+		})
+
+		_, err = f.KubeClientSet.RbacV1().ClusterRoleBindings().Update(context.Background(), crb, metav1.UpdateOptions{})
+		assert.Nil(ginkgo.GinkgoT(), err, "searching cluster role binding")
+
+		err = framework.UpdateDeployment(f.KubeClientSet, f.Namespace, "nginx-ingress-controller", 1,
+			func(deployment *appsv1.Deployment) error {
+				args := []string{}
+				for _, v := range deployment.Spec.Template.Spec.Containers[0].Args {
+					if strings.Contains(v, "--ingress-class") {
+						continue
+					}
+
+					args = append(args, v)
+				}
+
+				args = append(args, fmt.Sprintf("--ingress-class=%v", ingressClassName))
+				deployment.Spec.Template.Spec.Containers[0].Args = args
+				_, err := f.KubeClientSet.AppsV1().Deployments(f.Namespace).Update(context.TODO(), deployment, metav1.UpdateOptions{})
+				return err
+			})
+		assert.Nil(ginkgo.GinkgoT(), err, "updating ingress controller deployment flags")
+
+		host := "ingress.class"
+
+		ginkgo.By("only having IngressClassName")
+		ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, nil)
+		ing.Spec.IngressClassName = &ingressClassName
+		f.EnsureIngress(ing)
+
+		f.WaitForNginxServer(host, func(cfg string) bool {
+			return strings.Contains(cfg, fmt.Sprintf("server_name %v", host))
+		})
+
+		f.HTTPTestClient().
+			GET("/").
+			WithHeader("Host", host).
+			Expect().
+			Status(http.StatusOK)
+
+		ginkgo.By("only having ingress.class annotation")
+		ing, err = f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Get(context.TODO(), host, metav1.GetOptions{})
+		assert.Nil(ginkgo.GinkgoT(), err)
+
+		ing.Annotations = map[string]string{
+			class.IngressKey: ingressClassName,
+		}
+		ing.Spec.IngressClassName = nil
+
+		_, err = f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Update(context.TODO(), ing, metav1.UpdateOptions{})
+		assert.Nil(ginkgo.GinkgoT(), err)
+
+		f.WaitForNginxConfiguration(func(cfg string) bool {
+			return strings.Contains(cfg, fmt.Sprintf("server_name %v", host))
+		})
+
+		time.Sleep(2 * time.Second)
+
+		f.HTTPTestClient().
+			GET("/").
+			WithHeader("Host", host).
+			Expect().
+			Status(http.StatusOK)
+
+		ginkgo.By("having an invalid ingress.class annotation and no IngressClassName")
+		ing, err = f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Get(context.TODO(), host, metav1.GetOptions{})
+		assert.Nil(ginkgo.GinkgoT(), err)
+
+		ing.Annotations = map[string]string{
+			class.IngressKey: "invalid",
+		}
+		ing.Spec.IngressClassName = nil
+
+		_, err = f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Update(context.TODO(), ing, metav1.UpdateOptions{})
+		assert.Nil(ginkgo.GinkgoT(), err)
+
+		time.Sleep(2 * time.Second)
+
+		f.WaitForNginxConfiguration(func(cfg string) bool {
+			return !strings.Contains(cfg, fmt.Sprintf("server_name %v", host))
+		})
+
+		f.HTTPTestClient().
+			GET("/").
+			WithHeader("Host", host).
+			Expect().
+			Status(http.StatusNotFound)
+
+		ginkgo.By("not having ingress.class annotation and invalid IngressClassName")
+		ing, err = f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Get(context.TODO(), host, metav1.GetOptions{})
+		assert.Nil(ginkgo.GinkgoT(), err)
+		ing.Annotations = map[string]string{}
+		invalidClassName := "invalidclass"
+		ing.Spec.IngressClassName = &invalidClassName
+
+		_, err = f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Update(context.TODO(), ing, metav1.UpdateOptions{})
+		assert.Nil(ginkgo.GinkgoT(), err)
+
+		time.Sleep(2 * time.Second)
+
+		f.WaitForNginxConfiguration(func(cfg string) bool {
+			return !strings.Contains(cfg, fmt.Sprintf("server_name %v", host))
+		})
+
+		f.HTTPTestClient().
+			GET("/").
+			WithHeader("Host", host).
+			Expect().
+			Status(http.StatusNotFound)
+	})
 })