Repository: kubernetes-sigs/kueue
Pull request #104 (2022-03-09 12:56:16)

Add PriorityClass in Workload api
<!--  Thanks for sending a pull request!  Here are some tips for you:

1. If this is your first time, please read our contributor guidelines: https://git.k8s.io/community/contributors/guide/first-contribution.md#your-first-contribution and developer guide https://git.k8s.io/community/contributors/devel/development.md#development-guide
2. Please label this pull request according to what type of issue you are addressing, especially if this is a release targeted pull request. For reference on required PR/issue labels, read here:
https://git.k8s.io/community/contributors/devel/sig-release/release.md#issuepr-kind-label
3. Ensure you have added or ran the appropriate tests for your PR: https://git.k8s.io/community/contributors/devel/sig-testing/testing.md
4. If you want *faster* PR reviews, read how: https://git.k8s.io/community/contributors/guide/pull-requests.md#best-practices-for-faster-reviews
5. If the PR is unfinished, see how to mark it: https://git.k8s.io/community/contributors/guide/pull-requests.md#marking-unfinished-pull-requests
-->

#### What type of PR is this?

<!--
Add one of the following kinds:
/kind bug
/kind cleanup
/kind documentation
/kind feature

Optionally add one or more of the following kinds if applicable:
/kind api-change
/kind deprecation
/kind failing-test
/kind flake
/kind regression
-->
/kind feature

#### What this PR does / why we need it:

#### Which issue(s) this PR fixes:
<!--
*Automatically closes linked issue when PR is merged.
Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.
_If PR is about `failing-tests or flakes`, please post the related issues/tests in a comment and do not use `Fixes`_*
-->
The first part of #82 



denkensk: /assign @ahg-g 
k8s-ci-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/kubernetes-sigs/kueue/pull/104#" title="Author self-approved">denkensk</a>*
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please ask for approval from **ahg-g** after the PR has been reviewed.

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

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

- **[OWNERS](https://github.com/kubernetes-sigs/kueue/blob/main/OWNERS)**

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":["ahg-g"]} -->
k8s-ci-robot: @denkensk: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-kueue-test-integration-main | 673067232f6036c8fdcf7282a50481df80607e21 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_kueue/104/pull-kueue-test-integration-main/1501588334315573248) | true | `/test pull-kueue-test-integration-main`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=kueue&pr=104). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Adenkensk). 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-sigs/kueue/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 -->
denkensk: /test pull-kueue-test-integration-main
k8s-ci-robot: @denkensk: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-kueue-test-integration-main | 673067232f6036c8fdcf7282a50481df80607e21 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_kueue/104/pull-kueue-test-integration-main/1501591120491057152) | true | `/test pull-kueue-test-integration-main`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=kueue&pr=104). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Adenkensk). 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-sigs/kueue/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 -->
denkensk: /test pull-kueue-test-integration-main
k8s-ci-robot: @denkensk: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-kueue-test-integration-main | 673067232f6036c8fdcf7282a50481df80607e21 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_kueue/104/pull-kueue-test-integration-main/1501715976574472192) | true | `/test pull-kueue-test-integration-main`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=kueue&pr=104). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Adenkensk). 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-sigs/kueue/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: @denkensk: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-kueue-test-integration-main | e4ca343dc0893f0ae649f308bd0ec1227e0d6bd6 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_kueue/104/pull-kueue-test-integration-main/1503643715653079040) | true | `/test pull-kueue-test-integration-main`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=kueue&pr=104). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Adenkensk). 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-sigs/kueue/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 -->
denkensk: /test pull-kueue-test-integration-main
k8s-ci-robot: @denkensk: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-kueue-test-integration-main | 1d39c302ba6e1c3947e37cbf05bb0283cb49963d | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_kueue/104/pull-kueue-test-integration-main/1503647386868649984) | true | `/test pull-kueue-test-integration-main`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=kueue&pr=104). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Adenkensk). 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-sigs/kueue/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 -->
denkensk: /test pull-kueue-test-integration-main
k8s-ci-robot: @denkensk: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-kueue-test-integration-main | 1d39c302ba6e1c3947e37cbf05bb0283cb49963d | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_kueue/104/pull-kueue-test-integration-main/1503714818534674432) | true | `/test pull-kueue-test-integration-main`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=kueue&pr=104). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Adenkensk). 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-sigs/kueue/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: @denkensk: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-kueue-test-integration-main | 875d0bbd90908bb13ca75664849be8737ba8b0f0 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_kueue/104/pull-kueue-test-integration-main/1503766956166090752) | true | `/test pull-kueue-test-integration-main`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=kueue&pr=104). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Adenkensk). 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-sigs/kueue/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 -->
denkensk: /test pull-kueue-test-integration-main
alculquicondor: > I would continue with the simpler approach of looking up the priority at the time we add the workload to the queue and only store it in the internal struct.

It turns out to be quite invasive (we have to pass contexts, logs, a client) all within an event handler that is quite common.

I preferred the older approach of having it done in the job_controller until we have a webhook :(

But I won't block this PR on that.
k8s-ci-robot: @denkensk: PR needs rebase.

<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.
</details>
denkensk: > what is populating the PriorityClassName now?

It's populated by different controller to construct workloads. I will add this in job-controller in follow up pr. @alculquicondor 
k8s-ci-robot: @denkensk: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-kueue-verify-main | 5e2d7466045747712f205ab5f0a5ab8deca4e3d0 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_kueue/104/pull-kueue-verify-main/1504003846106517504) | true | `/test pull-kueue-verify-main`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=kueue&pr=104). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Adenkensk). 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-sigs/kueue/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: @denkensk: The following tests **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-kueue-verify-main | 5e2d7466045747712f205ab5f0a5ab8deca4e3d0 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_kueue/104/pull-kueue-verify-main/1504003846106517504) | true | `/test pull-kueue-verify-main`
pull-kueue-test-integration-main | 5e2d7466045747712f205ab5f0a5ab8deca4e3d0 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_kueue/104/pull-kueue-test-integration-main/1504003846072963072) | true | `/test pull-kueue-test-integration-main`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=kueue&pr=104). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Adenkensk). 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-sigs/kueue/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: @denkensk: The following tests **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-kueue-verify-main | 5e2d7466045747712f205ab5f0a5ab8deca4e3d0 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_kueue/104/pull-kueue-verify-main/1504003846106517504) | true | `/test pull-kueue-verify-main`
pull-kueue-test-integration-main | 5e2d7466045747712f205ab5f0a5ab8deca4e3d0 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_kueue/104/pull-kueue-test-integration-main/1504003846072963072) | true | `/test pull-kueue-test-integration-main`
pull-kueue-test-unit-main | 5e2d7466045747712f205ab5f0a5ab8deca4e3d0 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_kueue/104/pull-kueue-test-unit-main/1504003846043602944) | true | `/test pull-kueue-test-unit-main`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=kueue&pr=104). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Adenkensk). 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-sigs/kueue/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: @denkensk: The following tests **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-kueue-verify-main | 5e2d7466045747712f205ab5f0a5ab8deca4e3d0 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_kueue/104/pull-kueue-verify-main/1504003846106517504) | true | `/test pull-kueue-verify-main`
pull-kueue-test-integration-main | 5e2d7466045747712f205ab5f0a5ab8deca4e3d0 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_kueue/104/pull-kueue-test-integration-main/1504003846072963072) | true | `/test pull-kueue-test-integration-main`
pull-kueue-test-unit-main | 5e2d7466045747712f205ab5f0a5ab8deca4e3d0 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_kueue/104/pull-kueue-test-unit-main/1504003846043602944) | true | `/test pull-kueue-test-unit-main`
pull-kueue-build-image-main | 5e2d7466045747712f205ab5f0a5ab8deca4e3d0 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_kueue/104/pull-kueue-build-image-main/1504003846148460544) | true | `/test pull-kueue-build-image-main`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=kueue&pr=104). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Adenkensk). 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-sigs/kueue/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 -->
denkensk: > I thought it would be simpler because we could look it up in the create/update event handler and populate it in a workload.Info struct directly which we would pass to the Add/UpdateWorkload functions (we need to change them to receive workload.Info instead of kueue.Workload).

Yes. It would be simpler. I refactored the code as the suggestion.
denkensk: /retest
k8s-ci-robot: @denkensk: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-kueue-verify-main | 6b140687c3f00ad871124229e1a0c116ba766641 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_kueue/104/pull-kueue-verify-main/1504014534409457664) | true | `/test pull-kueue-verify-main`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=kueue&pr=104). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Adenkensk). 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-sigs/kueue/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 -->
ahg-g: I am sorry for the back and forth, this plumbing doesn't look "right". I am pretty sure there will be places where we will miss to set `info.Priority` and so it will be dangerous to continue like this unless the priority look up is done inside NewInfo, which I think isn't going to be pretty because it means `NewInfo` will need to receive client/ctx/logger, and it is used in multiple places including the cache.

I coming back to having the priority int on the QueuedWorkload and having it populated by the job-controller. Thinking more about how to prevent users from circumventing priority classes: users shouldn't be creating QueuedWorkload instances directly, and so they really can't set the QueuedWorkload priority (at least in our MVP). 

Alex, I am pretty sure this is frustrating to you, sorry about that, I am happy to make the change myself if you don't have the time.

denkensk: > I coming back to having the priority int on the QueuedWorkload and having it populated by the job-controller. Thinking more about how to prevent users from circumventing priority classes: users shouldn't be creating QueuedWorkload instances directly, and so they really can't set the QueuedWorkload priority (at least in our MVP).

Shall we only have Priority in QueuedWorkload or both PriorityClass and Priority?

> Alex, I am pretty sure this is frustrating to you, sorry about that, I am happy to make the change myself if you don't have the time.

It doesn't matter. It's worth putting in some effort before making the right decision. I will try to finish refactor the code today and tomorrow.
ahg-g: > Shall we only have Priority in QueuedWorkload or both PriorityClass and Priority?

Both, the job-controller populates it just like we do for pods. Initially I was concerned that there was no path for Admins to block usage of higher priority classes or preventing users from setting directly a high priority on the workload. But that is actually not true because admins could prevent users from creating QW directly and only allow them to create v1.Job.

I still think we want to have priority class on the Queue object but we can leave that as a followup.

> It doesn't matter. It's worth putting in some effort before making the right decision. I will try to finish refactor the code today and tomorrow.

Thank you, and I am sorry again for the back and forth, but indeed this was an informative exercise, at least for me. 


denkensk: Since this is very similar to my first version of the implementation, so I finish it quickly 😄  pls take a look again. Thanks. @ahg-g 
ahg-g: It would be nice if we can add a [scheduler integration test](https://github.com/kubernetes-sigs/kueue/blob/main/test/integration/scheduler/scheduler_test.go) in a separate `ginkgo.It`

Patch:
diff --git a/Makefile b/Makefile
index d041a41ce..89afe2e03 100644
--- a/Makefile
+++ b/Makefile
@@ -196,7 +196,7 @@ TMP_DIR=$$(mktemp -d) ;\
 cd $$TMP_DIR ;\
 $(GO_CMD) mod init tmp ;\
 echo "Downloading $(2)" ;\
-GOBIN=$(PROJECT_DIR)/bin $(GO_CMD) install $(2) ;\
+GOBIN=$(PROJECT_DIR)/bin $(GO_CMD) get $(2) ;\
 rm -rf $$TMP_DIR ;\
 }
 endef
diff --git a/api/v1alpha1/clusterqueue_types.go b/api/v1alpha1/clusterqueue_types.go
index 0bd05f591..b8f022660 100644
--- a/api/v1alpha1/clusterqueue_types.go
+++ b/api/v1alpha1/clusterqueue_types.go
@@ -222,10 +222,10 @@ type Resource struct {
 	//
 	// +listType=map
 	// +listMapKey=name
-	Flavors []Flavor `json:"flavors,omitempty"`
+	Flavors []ResourceFlavor `json:"flavors,omitempty"`
 }
 
-type Flavor struct {
+type ResourceFlavor struct {
 	// name is the type name, e.g., nvidia-tesla-k80.
 	// +kubebuilder:default=default
 	Name string `json:"name"`
diff --git a/api/v1alpha1/queuedworkload_types.go b/api/v1alpha1/queuedworkload_types.go
index 9f3008e4b..2d142ce9d 100644
--- a/api/v1alpha1/queuedworkload_types.go
+++ b/api/v1alpha1/queuedworkload_types.go
@@ -39,6 +39,20 @@ type QueuedWorkloadSpec struct {
 
 	// admission holds the parameters of the admission of the workload by a ClusterQueue.
 	Admission *Admission `json:"admission,omitempty"`
+
+	// If specified, indicates the queuedWorkload's priority.
+	// "system-node-critical" and "system-cluster-critical" are two special
+	// keywords which indicate the highest priorities with the former being
+	// the highest priority. Any other name must be defined by creating a
+	// PriorityClass object with that name. If not specified, the queuedWorkload
+	// priority will be default or zero if there is no default.
+	PriorityClassName string `json:"priorityClassName,omitempty"`
+
+	// Priority determines the order of access to the resources managed by the
+	// ClusterQueue where the workload is queued.
+	// The priority value is populated from PriorityClassName.
+	// The higher the value, the higher the priority.
+	Priority *int32 `json:"priority,omitempty"`
 }
 
 type Admission struct {
@@ -56,8 +70,8 @@ type PodSetFlavors struct {
 	// +kubebuilder:default=main
 	Name string `json:"name"`
 
-	// Flavors are the flavors assigned to the workload for each resource.
-	Flavors map[corev1.ResourceName]string `json:"flavors,omitempty"`
+	// ResourceFlavors are the flavors assigned to the workload for each resource.
+	ResourceFlavors map[corev1.ResourceName]string `json:"resourceFlavors,omitempty"`
 }
 
 type WorkloadReference struct {
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index 42a81abec..de60615a8 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -167,36 +167,6 @@ func (in *ClusterQueueStatus) DeepCopy() *ClusterQueueStatus {
 	return out
 }
 
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *Flavor) DeepCopyInto(out *Flavor) {
-	*out = *in
-	in.Quota.DeepCopyInto(&out.Quota)
-	if in.Labels != nil {
-		in, out := &in.Labels, &out.Labels
-		*out = make(map[string]string, len(*in))
-		for key, val := range *in {
-			(*out)[key] = val
-		}
-	}
-	if in.Taints != nil {
-		in, out := &in.Taints, &out.Taints
-		*out = make([]corev1.Taint, len(*in))
-		for i := range *in {
-			(*in)[i].DeepCopyInto(&(*out)[i])
-		}
-	}
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Flavor.
-func (in *Flavor) DeepCopy() *Flavor {
-	if in == nil {
-		return nil
-	}
-	out := new(Flavor)
-	in.DeepCopyInto(out)
-	return out
-}
-
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *PodSet) DeepCopyInto(out *PodSet) {
 	*out = *in
@@ -216,8 +186,8 @@ func (in *PodSet) DeepCopy() *PodSet {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *PodSetFlavors) DeepCopyInto(out *PodSetFlavors) {
 	*out = *in
-	if in.Flavors != nil {
-		in, out := &in.Flavors, &out.Flavors
+	if in.ResourceFlavors != nil {
+		in, out := &in.ResourceFlavors, &out.ResourceFlavors
 		*out = make(map[corev1.ResourceName]string, len(*in))
 		for key, val := range *in {
 			(*out)[key] = val
@@ -416,6 +386,11 @@ func (in *QueuedWorkloadSpec) DeepCopyInto(out *QueuedWorkloadSpec) {
 		*out = new(Admission)
 		(*in).DeepCopyInto(*out)
 	}
+	if in.Priority != nil {
+		in, out := &in.Priority, &out.Priority
+		*out = new(int32)
+		**out = **in
+	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new QueuedWorkloadSpec.
@@ -472,7 +447,7 @@ func (in *Resource) DeepCopyInto(out *Resource) {
 	*out = *in
 	if in.Flavors != nil {
 		in, out := &in.Flavors, &out.Flavors
-		*out = make([]Flavor, len(*in))
+		*out = make([]ResourceFlavor, len(*in))
 		for i := range *in {
 			(*in)[i].DeepCopyInto(&(*out)[i])
 		}
@@ -489,6 +464,36 @@ func (in *Resource) DeepCopy() *Resource {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ResourceFlavor) DeepCopyInto(out *ResourceFlavor) {
+	*out = *in
+	in.Quota.DeepCopyInto(&out.Quota)
+	if in.Labels != nil {
+		in, out := &in.Labels, &out.Labels
+		*out = make(map[string]string, len(*in))
+		for key, val := range *in {
+			(*out)[key] = val
+		}
+	}
+	if in.Taints != nil {
+		in, out := &in.Taints, &out.Taints
+		*out = make([]corev1.Taint, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceFlavor.
+func (in *ResourceFlavor) DeepCopy() *ResourceFlavor {
+	if in == nil {
+		return nil
+	}
+	out := new(ResourceFlavor)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *Usage) DeepCopyInto(out *Usage) {
 	*out = *in
diff --git a/config/crd/bases/kueue.x-k8s.io_queuedworkloads.yaml b/config/crd/bases/kueue.x-k8s.io_queuedworkloads.yaml
index 729c08e5b..1a2d4bd45 100644
--- a/config/crd/bases/kueue.x-k8s.io_queuedworkloads.yaml
+++ b/config/crd/bases/kueue.x-k8s.io_queuedworkloads.yaml
@@ -51,17 +51,17 @@ spec:
                       of the .spec.podSets entries.
                     items:
                       properties:
-                        flavors:
-                          additionalProperties:
-                            type: string
-                          description: Flavors are the flavors assigned to the workload
-                            for each resource.
-                          type: object
                         name:
                           default: main
                           description: Name is the name of the podSet. It should match
                             one of the names in .spec.podSets.
                           type: string
+                        resourceFlavors:
+                          additionalProperties:
+                            type: string
+                          description: ResourceFlavors are the flavors assigned to
+                            the workload for each resource.
+                          type: object
                       required:
                       - name
                       type: object
@@ -7300,6 +7300,21 @@ spec:
                 x-kubernetes-list-map-keys:
                 - name
                 x-kubernetes-list-type: map
+              priority:
+                description: Priority determines the order of access to the resources
+                  managed by the ClusterQueue where the workload is queued. The priority
+                  value is populated from PriorityClassName. The higher the value,
+                  the higher the priority.
+                format: int32
+                type: integer
+              priorityClassName:
+                description: If specified, indicates the queuedWorkload's priority.
+                  "system-node-critical" and "system-cluster-critical" are two special
+                  keywords which indicate the highest priorities with the former being
+                  the highest priority. Any other name must be defined by creating
+                  a PriorityClass object with that name. If not specified, the queuedWorkload
+                  priority will be default or zero if there is no default.
+                type: string
               queueName:
                 description: queueName is the name of the queue the QueuedWorkload
                   is associated with.
diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go
index e601c6614..9f0b48997 100644
--- a/pkg/constants/constants.go
+++ b/pkg/constants/constants.go
@@ -30,4 +30,9 @@ const (
 	// UpdatesBatchPeriod is the batch period to hold queuedworkload updates
 	// before syncing a Queue and CLusterQueue onbjects.
 	UpdatesBatchPeriod = 3 * time.Second
+
+	// DefaultPriority is used to set priority of workloads
+	// that do not specify any priority class and there is no priority class
+	// marked as default.
+	DefaultPriority = 0
 )
diff --git a/pkg/controller/workload/job/job_controller.go b/pkg/controller/workload/job/job_controller.go
index 5f3a419ac..805c422e3 100644
--- a/pkg/controller/workload/job/job_controller.go
+++ b/pkg/controller/workload/job/job_controller.go
@@ -35,6 +35,7 @@ import (
 
 	kueue "sigs.k8s.io/kueue/api/v1alpha1"
 	"sigs.k8s.io/kueue/pkg/constants"
+	utilpriority "sigs.k8s.io/kueue/pkg/util/priority"
 	"sigs.k8s.io/kueue/pkg/workload"
 )
 
@@ -257,22 +258,22 @@ func (r *JobReconciler) startJob(ctx context.Context, w *kueue.QueuedWorkload, j
 }
 
 func getNodeSelectors(cq *kueue.ClusterQueue, w *kueue.QueuedWorkload) map[string]string {
-	if len(w.Spec.Admission.PodSetFlavors[0].Flavors) == 0 {
+	if len(w.Spec.Admission.PodSetFlavors[0].ResourceFlavors) == 0 {
 		return nil
 	}
 
 	// Create a map of resources-to-flavors.
 	// May be cache this?
-	flavors := make(map[corev1.ResourceName]map[string]*kueue.Flavor, len(cq.Spec.RequestableResources))
+	flavors := make(map[corev1.ResourceName]map[string]*kueue.ResourceFlavor, len(cq.Spec.RequestableResources))
 	for _, r := range cq.Spec.RequestableResources {
-		flavors[r.Name] = make(map[string]*kueue.Flavor, len(r.Flavors))
+		flavors[r.Name] = make(map[string]*kueue.ResourceFlavor, len(r.Flavors))
 		for j := range r.Flavors {
 			flavors[r.Name][r.Flavors[j].Name] = &r.Flavors[j]
 		}
 	}
 
 	nodeSelector := map[string]string{}
-	for res, flvr := range w.Spec.Admission.PodSetFlavors[0].Flavors {
+	for res, flvr := range w.Spec.Admission.PodSetFlavors[0].ResourceFlavors {
 		if cqRes, existRes := flavors[res]; existRes {
 			if cqFlvr, existFlvr := cqRes[flvr]; existFlvr {
 				for k, v := range cqFlvr.Labels {
@@ -294,7 +295,7 @@ func (r *JobReconciler) handleJobWithNoWorkload(ctx context.Context, job *batchv
 	}
 
 	// Create the corresponding workload.
-	wl, err := ConstructWorkloadFor(job, r.scheme)
+	wl, err := ConstructWorkloadFor(ctx, r.client, job, r.scheme)
 	if err != nil {
 		return err
 	}
@@ -370,7 +371,8 @@ func (r *JobReconciler) ensureAtMostOneWorkload(ctx context.Context, job *batchv
 	return match, nil
 }
 
-func ConstructWorkloadFor(job *batchv1.Job, scheme *runtime.Scheme) (*kueue.QueuedWorkload, error) {
+func ConstructWorkloadFor(ctx context.Context, client client.Client,
+	job *batchv1.Job, scheme *runtime.Scheme) (*kueue.QueuedWorkload, error) {
 	w := &kueue.QueuedWorkload{
 		ObjectMeta: metav1.ObjectMeta{
 			Name:      job.Name,
@@ -386,6 +388,16 @@ func ConstructWorkloadFor(job *batchv1.Job, scheme *runtime.Scheme) (*kueue.Queu
 			QueueName: queueName(job),
 		},
 	}
+
+	// Populate priority from priority class.
+	priorityClassName, p, err := utilpriority.GetPriorityFromPriorityClass(
+		ctx, client, job.Spec.Template.Spec.PriorityClassName)
+	if err != nil {
+		return nil, err
+	}
+	w.Spec.Priority = &p
+	w.Spec.PriorityClassName = priorityClassName
+
 	if err := ctrl.SetControllerReference(job, w, scheme); err != nil {
 		return nil, err
 	}
diff --git a/pkg/queue/queue.go b/pkg/queue/queue.go
index 441538e08..d4214f63b 100644
--- a/pkg/queue/queue.go
+++ b/pkg/queue/queue.go
@@ -21,6 +21,7 @@ import (
 	"fmt"
 
 	kueue "sigs.k8s.io/kueue/api/v1alpha1"
+	utilpriority "sigs.k8s.io/kueue/pkg/util/priority"
 	"sigs.k8s.io/kueue/pkg/workload"
 )
 
@@ -140,6 +141,12 @@ func (cq *ClusterQueue) Pop() *workload.Info {
 }
 
 func creationFIFO(a, b workload.Info) bool {
+	p1 := utilpriority.Priority(a.Obj)
+	p2 := utilpriority.Priority(b.Obj)
+
+	if p1 != p2 {
+		return p1 > p2
+	}
 	return a.Obj.CreationTimestamp.Before(&b.Obj.CreationTimestamp)
 }
 
diff --git a/pkg/scheduler/scheduler.go b/pkg/scheduler/scheduler.go
index ff027425c..ff2b9bbd2 100644
--- a/pkg/scheduler/scheduler.go
+++ b/pkg/scheduler/scheduler.go
@@ -223,8 +223,8 @@ func (s *Scheduler) admit(ctx context.Context, e *entry) error {
 	}
 	for i := range e.TotalRequests {
 		admission.PodSetFlavors[i] = kueue.PodSetFlavors{
-			Name:    e.Obj.Spec.PodSets[i].Name,
-			Flavors: e.TotalRequests[i].Flavors,
+			Name:            e.Obj.Spec.PodSets[i].Name,
+			ResourceFlavors: e.TotalRequests[i].Flavors,
 		}
 	}
 	newWorkload.Spec.Admission = admission
diff --git a/pkg/util/priority/priority.go b/pkg/util/priority/priority.go
new file mode 100644
index 000000000..22e732c4d
--- /dev/null
+++ b/pkg/util/priority/priority.go
@@ -0,0 +1,87 @@
+/*
+Copyright 2022 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package priority
+
+import (
+	"context"
+
+	schedulingv1 "k8s.io/api/scheduling/v1"
+	"k8s.io/apimachinery/pkg/types"
+	"sigs.k8s.io/controller-runtime/pkg/client"
+
+	kueue "sigs.k8s.io/kueue/api/v1alpha1"
+	"sigs.k8s.io/kueue/pkg/constants"
+)
+
+// Priority returns priority of the given workload.
+func Priority(w *kueue.QueuedWorkload) int32 {
+	if w.Spec.Priority != nil {
+		return *w.Spec.Priority
+	}
+	// When priority of a running workload is nil, it means it was created at a time
+	// that there was no global default priority class and the priority class
+	// name of the pod was empty. So, we resolve to the static default priority.
+	return constants.DefaultPriority
+}
+
+// GetPriorityFromPriorityClass returns the priority populated from
+// priority class. If not specified, priority will be default or
+// zero if there is no default.
+func GetPriorityFromPriorityClass(ctx context.Context, client client.Client,
+	priorityClass string) (string, int32, error) {
+	if len(priorityClass) == 0 {
+		return getDefaultPriority(ctx, client)
+	}
+
+	pc := &schedulingv1.PriorityClass{}
+	if err := client.Get(ctx, types.NamespacedName{Name: priorityClass}, pc); err != nil {
+		return "", 0, err
+	}
+
+	return pc.Name, pc.Value, nil
+}
+
+func getDefaultPriority(ctx context.Context, client client.Client) (string, int32, error) {
+	dpc, err := getDefaultPriorityClass(ctx, client)
+	if err != nil {
+		return "", 0, err
+	}
+	if dpc != nil {
+		return dpc.Name, dpc.Value, nil
+	}
+	return "", int32(constants.DefaultPriority), nil
+}
+
+func getDefaultPriorityClass(ctx context.Context, client client.Client) (*schedulingv1.PriorityClass, error) {
+	pcs := schedulingv1.PriorityClassList{}
+	err := client.List(ctx, &pcs)
+	if err != nil {
+		return nil, err
+	}
+
+	// In case more than one global default priority class is added as a result of a race condition,
+	// we pick the one with the lowest priority value.
+	var defaultPC *schedulingv1.PriorityClass
+	for _, pci := range pcs.Items {
+		if pci.GlobalDefault {
+			if defaultPC == nil || defaultPC.Value > pci.Value {
+				defaultPC = &pci
+			}
+		}
+	}
+	return defaultPC, nil
+}
diff --git a/pkg/util/routine/wrapper.go b/pkg/util/routine/wrapper.go
index 356cfa42c..23b5cce28 100644
--- a/pkg/util/routine/wrapper.go
+++ b/pkg/util/routine/wrapper.go
@@ -1,3 +1,19 @@
+/*
+Copyright 2022 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
 package routine
 
 // Wrapper is used to wrap a function that will run in a goroutine.
diff --git a/pkg/workload/workload.go b/pkg/workload/workload.go
index cf6f2b4ac..e6de96f02 100644
--- a/pkg/workload/workload.go
+++ b/pkg/workload/workload.go
@@ -61,7 +61,7 @@ func totalRequests(spec *kueue.QueuedWorkloadSpec) []PodSetResources {
 	if spec.Admission != nil {
 		podSetFlavors = make(map[string]map[corev1.ResourceName]string, len(spec.Admission.PodSetFlavors))
 		for _, ps := range spec.Admission.PodSetFlavors {
-			podSetFlavors[ps.Name] = ps.Flavors
+			podSetFlavors[ps.Name] = ps.ResourceFlavors
 		}
 	}
 	for _, ps := range spec.PodSets {


Test patch:
diff --git a/pkg/cache/cache_test.go b/pkg/cache/cache_test.go
index 5ebebbe92..e620fb1d5 100644
--- a/pkg/cache/cache_test.go
+++ b/pkg/cache/cache_test.go
@@ -59,7 +59,7 @@ func TestCacheClusterQueueOperations(t *testing.T) {
 							RequestableResources: []kueue.Resource{
 								{
 									Name: corev1.ResourceCPU,
-									Flavors: []kueue.Flavor{
+									Flavors: []kueue.ResourceFlavor{
 										{
 											Name: "default",
 											Quota: kueue.Quota{
@@ -79,7 +79,7 @@ func TestCacheClusterQueueOperations(t *testing.T) {
 							RequestableResources: []kueue.Resource{
 								{
 									Name:    corev1.ResourceCPU,
-									Flavors: []kueue.Flavor{{Name: "default"}},
+									Flavors: []kueue.ResourceFlavor{{Name: "default"}},
 								}},
 							Cohort: "one",
 						},
@@ -145,7 +145,7 @@ func TestCacheClusterQueueOperations(t *testing.T) {
 							RequestableResources: []kueue.Resource{
 								{
 									Name: corev1.ResourceCPU,
-									Flavors: []kueue.Flavor{
+									Flavors: []kueue.ResourceFlavor{
 										{
 											Name: "default",
 											Quota: kueue.Quota{
@@ -275,7 +275,7 @@ func TestCacheWorkloadOperations(t *testing.T) {
 				RequestableResources: []kueue.Resource{
 					{
 						Name: "cpu",
-						Flavors: []kueue.Flavor{
+						Flavors: []kueue.ResourceFlavor{
 							{Name: "on-demand"},
 							{Name: "spot"},
 						},
@@ -289,7 +289,7 @@ func TestCacheWorkloadOperations(t *testing.T) {
 				RequestableResources: []kueue.Resource{
 					{
 						Name: "cpu",
-						Flavors: []kueue.Flavor{
+						Flavors: []kueue.ResourceFlavor{
 							{Name: "on-demand"},
 							{Name: "spot"},
 						},
@@ -319,13 +319,13 @@ func TestCacheWorkloadOperations(t *testing.T) {
 	podSetFlavors := []kueue.PodSetFlavors{
 		{
 			Name: "driver",
-			Flavors: map[corev1.ResourceName]string{
+			ResourceFlavors: map[corev1.ResourceName]string{
 				corev1.ResourceCPU: "on-demand",
 			},
 		},
 		{
 			Name: "workers",
-			Flavors: map[corev1.ResourceName]string{
+			ResourceFlavors: map[corev1.ResourceName]string{
 				corev1.ResourceCPU: "spot",
 			},
 		},
@@ -735,7 +735,7 @@ func TestClusterQueueUsage(t *testing.T) {
 			RequestableResources: []kueue.Resource{
 				{
 					Name: corev1.ResourceCPU,
-					Flavors: []kueue.Flavor{
+					Flavors: []kueue.ResourceFlavor{
 						{
 							Name: "default",
 							Quota: kueue.Quota{
@@ -747,7 +747,7 @@ func TestClusterQueueUsage(t *testing.T) {
 				},
 				{
 					Name: "example.com/gpu",
-					Flavors: []kueue.Flavor{
+					Flavors: []kueue.ResourceFlavor{
 						{
 							Name: "model_a",
 							Quota: kueue.Quota{
@@ -786,7 +786,7 @@ func TestClusterQueueUsage(t *testing.T) {
 					PodSetFlavors: []kueue.PodSetFlavors{
 						{
 							Name: "main",
-							Flavors: map[corev1.ResourceName]string{
+							ResourceFlavors: map[corev1.ResourceName]string{
 								corev1.ResourceCPU: "default",
 								"example.com/gpu":  "model_a",
 							},
@@ -813,7 +813,7 @@ func TestClusterQueueUsage(t *testing.T) {
 					PodSetFlavors: []kueue.PodSetFlavors{
 						{
 							Name: "main",
-							Flavors: map[corev1.ResourceName]string{
+							ResourceFlavors: map[corev1.ResourceName]string{
 								corev1.ResourceCPU: "default",
 								"example.com/gpu":  "model_b",
 							},
diff --git a/pkg/cache/snapshot_test.go b/pkg/cache/snapshot_test.go
index 3b3d13e86..93a38b4d6 100644
--- a/pkg/cache/snapshot_test.go
+++ b/pkg/cache/snapshot_test.go
@@ -51,7 +51,7 @@ func TestSnapshot(t *testing.T) {
 				RequestableResources: []kueue.Resource{
 					{
 						Name: corev1.ResourceCPU,
-						Flavors: []kueue.Flavor{
+						Flavors: []kueue.ResourceFlavor{
 							{
 								Name: "demand",
 								Quota: kueue.Quota{
@@ -80,7 +80,7 @@ func TestSnapshot(t *testing.T) {
 				RequestableResources: []kueue.Resource{
 					{
 						Name: corev1.ResourceCPU,
-						Flavors: []kueue.Flavor{
+						Flavors: []kueue.ResourceFlavor{
 							{
 								Name: "spot",
 								Quota: kueue.Quota{
@@ -91,7 +91,7 @@ func TestSnapshot(t *testing.T) {
 					},
 					{
 						Name: "example.com/gpu",
-						Flavors: []kueue.Flavor{
+						Flavors: []kueue.ResourceFlavor{
 							{
 								Name: "default",
 								Quota: kueue.Quota{
@@ -111,7 +111,7 @@ func TestSnapshot(t *testing.T) {
 				RequestableResources: []kueue.Resource{
 					{
 						Name: corev1.ResourceCPU,
-						Flavors: []kueue.Flavor{
+						Flavors: []kueue.ResourceFlavor{
 							{
 								Name: "default",
 								Quota: kueue.Quota{
@@ -149,7 +149,7 @@ func TestSnapshot(t *testing.T) {
 					PodSetFlavors: []kueue.PodSetFlavors{
 						{
 							Name: "main",
-							Flavors: map[corev1.ResourceName]string{
+							ResourceFlavors: map[corev1.ResourceName]string{
 								corev1.ResourceCPU: "demand",
 							},
 						},
@@ -175,7 +175,7 @@ func TestSnapshot(t *testing.T) {
 					PodSetFlavors: []kueue.PodSetFlavors{
 						{
 							Name: "main",
-							Flavors: map[corev1.ResourceName]string{
+							ResourceFlavors: map[corev1.ResourceName]string{
 								corev1.ResourceCPU: "spot",
 								"example.com/gpu":  "default",
 							},
@@ -202,7 +202,7 @@ func TestSnapshot(t *testing.T) {
 					PodSetFlavors: []kueue.PodSetFlavors{
 						{
 							Name: "main",
-							Flavors: map[corev1.ResourceName]string{
+							ResourceFlavors: map[corev1.ResourceName]string{
 								corev1.ResourceCPU: "spot",
 								"example.com/gpu":  "default",
 							},
diff --git a/pkg/queue/queue_test.go b/pkg/queue/queue_test.go
index 720ee639e..42186da7f 100644
--- a/pkg/queue/queue_test.go
+++ b/pkg/queue/queue_test.go
@@ -21,9 +21,16 @@ import (
 	"time"
 
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/utils/pointer"
+
 	kueue "sigs.k8s.io/kueue/api/v1alpha1"
 )
 
+const (
+	lowPriority  = 0
+	highPriority = 1000
+)
+
 func TestFIFOClusterQueue(t *testing.T) {
 	q := newClusterQueue(&kueue.ClusterQueue{
 		Spec: kueue.ClusterQueueSpec{
@@ -83,3 +90,98 @@ func TestFIFOClusterQueue(t *testing.T) {
 		t.Errorf("Queue is not empty, poped workload %q", got.Obj.Name)
 	}
 }
+
+func TestStrictFIFO(t *testing.T) {
+	t1 := time.Now()
+	t2 := t1.Add(time.Second)
+	for _, tt := range []struct {
+		name     string
+		w1       *kueue.QueuedWorkload
+		w2       *kueue.QueuedWorkload
+		expected string
+	}{
+		{
+			name: "w1.priority is higher than w2.priority",
+			w1: &kueue.QueuedWorkload{
+				ObjectMeta: metav1.ObjectMeta{
+					Name:              "w1",
+					CreationTimestamp: metav1.NewTime(t1),
+				},
+				Spec: kueue.QueuedWorkloadSpec{
+					PriorityClassName: "highPriority",
+					Priority:          pointer.Int32(highPriority),
+				},
+			},
+			w2: &kueue.QueuedWorkload{
+				ObjectMeta: metav1.ObjectMeta{
+					Name:              "w2",
+					CreationTimestamp: metav1.NewTime(t2),
+				},
+				Spec: kueue.QueuedWorkloadSpec{
+					PriorityClassName: "lowPriority",
+					Priority:          pointer.Int32(lowPriority),
+				},
+			},
+			expected: "w1",
+		},
+		{
+			name: "w1.priority equals w2.priority and w1.create time is earlier than w2.create time",
+			w1: &kueue.QueuedWorkload{
+				ObjectMeta: metav1.ObjectMeta{
+					Name:              "w1",
+					CreationTimestamp: metav1.NewTime(t1),
+				},
+			},
+			w2: &kueue.QueuedWorkload{
+				ObjectMeta: metav1.ObjectMeta{
+					Name:              "w2",
+					CreationTimestamp: metav1.NewTime(t2),
+				},
+			},
+			expected: "w1",
+		},
+		{
+			name: "p1.priority is lower than p2.priority and w1.create time is earlier than w2.create time",
+			w1: &kueue.QueuedWorkload{
+				ObjectMeta: metav1.ObjectMeta{
+					Name:              "w1",
+					CreationTimestamp: metav1.NewTime(t1),
+				},
+				Spec: kueue.QueuedWorkloadSpec{
+					PriorityClassName: "lowPriority",
+					Priority:          pointer.Int32(lowPriority),
+				},
+			},
+			w2: &kueue.QueuedWorkload{
+				ObjectMeta: metav1.ObjectMeta{
+					Name:              "w2",
+					CreationTimestamp: metav1.NewTime(t2),
+				},
+				Spec: kueue.QueuedWorkloadSpec{
+					PriorityClassName: "highPriority",
+					Priority:          pointer.Int32(highPriority),
+				},
+			},
+			expected: "w2",
+		},
+	} {
+		t.Run(tt.name, func(t *testing.T) {
+			q := newClusterQueue(&kueue.ClusterQueue{
+				Spec: kueue.ClusterQueueSpec{
+					QueueingStrategy: kueue.StrictFIFO,
+				},
+			})
+
+			q.PushOrUpdate(tt.w1)
+			q.PushOrUpdate(tt.w2)
+
+			got := q.Pop()
+			if got == nil {
+				t.Fatal("Queue is empty")
+			}
+			if got.Obj.Name != tt.expected {
+				t.Errorf("Poped workload %q want %q", got.Obj.Name, tt.expected)
+			}
+		})
+	}
+}
diff --git a/pkg/scheduler/scheduler_test.go b/pkg/scheduler/scheduler_test.go
index b2788205a..8808bacba 100644
--- a/pkg/scheduler/scheduler_test.go
+++ b/pkg/scheduler/scheduler_test.go
@@ -65,7 +65,7 @@ func TestSchedule(t *testing.T) {
 				RequestableResources: []kueue.Resource{
 					{
 						Name: corev1.ResourceCPU,
-						Flavors: []kueue.Flavor{
+						Flavors: []kueue.ResourceFlavor{
 							{
 								Name: "default",
 								Quota: kueue.Quota{
@@ -94,7 +94,7 @@ func TestSchedule(t *testing.T) {
 				RequestableResources: []kueue.Resource{
 					{
 						Name: corev1.ResourceCPU,
-						Flavors: []kueue.Flavor{
+						Flavors: []kueue.ResourceFlavor{
 							{
 								Name: "on-demand",
 								Quota: kueue.Quota{
@@ -130,7 +130,7 @@ func TestSchedule(t *testing.T) {
 				RequestableResources: []kueue.Resource{
 					{
 						Name: corev1.ResourceCPU,
-						Flavors: []kueue.Flavor{
+						Flavors: []kueue.ResourceFlavor{
 							{
 								Name: "on-demand",
 								Quota: kueue.Quota{
@@ -149,7 +149,7 @@ func TestSchedule(t *testing.T) {
 					},
 					{
 						Name: "example.com/gpu",
-						Flavors: []kueue.Flavor{
+						Flavors: []kueue.ResourceFlavor{
 							{
 								Name: "model-a",
 								Quota: kueue.Quota{
@@ -237,7 +237,7 @@ func TestSchedule(t *testing.T) {
 					PodSetFlavors: []kueue.PodSetFlavors{
 						{
 							Name: "one",
-							Flavors: map[corev1.ResourceName]string{
+							ResourceFlavors: map[corev1.ResourceName]string{
 								corev1.ResourceCPU: "default",
 							},
 						},
@@ -286,7 +286,7 @@ func TestSchedule(t *testing.T) {
 							PodSetFlavors: []kueue.PodSetFlavors{
 								{
 									Name: "one",
-									Flavors: map[corev1.ResourceName]string{
+									ResourceFlavors: map[corev1.ResourceName]string{
 										corev1.ResourceCPU: "default",
 									},
 								},
@@ -301,7 +301,7 @@ func TestSchedule(t *testing.T) {
 					PodSetFlavors: []kueue.PodSetFlavors{
 						{
 							Name: "one",
-							Flavors: map[corev1.ResourceName]string{
+							ResourceFlavors: map[corev1.ResourceName]string{
 								corev1.ResourceCPU: "default",
 							},
 						},
@@ -382,7 +382,7 @@ func TestSchedule(t *testing.T) {
 					PodSetFlavors: []kueue.PodSetFlavors{
 						{
 							Name: "one",
-							Flavors: map[corev1.ResourceName]string{
+							ResourceFlavors: map[corev1.ResourceName]string{
 								corev1.ResourceCPU: "default",
 							},
 						},
@@ -393,7 +393,7 @@ func TestSchedule(t *testing.T) {
 					PodSetFlavors: []kueue.PodSetFlavors{
 						{
 							Name: "one",
-							Flavors: map[corev1.ResourceName]string{
+							ResourceFlavors: map[corev1.ResourceName]string{
 								corev1.ResourceCPU: "on-demand",
 							},
 						},
@@ -447,7 +447,7 @@ func TestSchedule(t *testing.T) {
 					PodSetFlavors: []kueue.PodSetFlavors{
 						{
 							Name: "one",
-							Flavors: map[corev1.ResourceName]string{
+							ResourceFlavors: map[corev1.ResourceName]string{
 								corev1.ResourceCPU: "on-demand",
 							},
 						},
@@ -458,7 +458,7 @@ func TestSchedule(t *testing.T) {
 					PodSetFlavors: []kueue.PodSetFlavors{
 						{
 							Name: "one",
-							Flavors: map[corev1.ResourceName]string{
+							ResourceFlavors: map[corev1.ResourceName]string{
 								corev1.ResourceCPU: "on-demand",
 							},
 						},
@@ -502,14 +502,14 @@ func TestSchedule(t *testing.T) {
 					PodSetFlavors: []kueue.PodSetFlavors{
 						{
 							Name: "one",
-							Flavors: map[corev1.ResourceName]string{
+							ResourceFlavors: map[corev1.ResourceName]string{
 								corev1.ResourceCPU: "on-demand",
 								"example.com/gpu":  "model-a",
 							},
 						},
 						{
 							Name: "two",
-							Flavors: map[corev1.ResourceName]string{
+							ResourceFlavors: map[corev1.ResourceName]string{
 								corev1.ResourceCPU: "spot",
 							},
 						},
@@ -563,7 +563,7 @@ func TestSchedule(t *testing.T) {
 					PodSetFlavors: []kueue.PodSetFlavors{
 						{
 							Name: "one",
-							Flavors: map[corev1.ResourceName]string{
+							ResourceFlavors: map[corev1.ResourceName]string{
 								corev1.ResourceCPU: "on-demand",
 							},
 						},
@@ -640,7 +640,7 @@ func TestSchedule(t *testing.T) {
 							PodSetFlavors: []kueue.PodSetFlavors{
 								{
 									Name: "one",
-									Flavors: map[corev1.ResourceName]string{
+									ResourceFlavors: map[corev1.ResourceName]string{
 										corev1.ResourceCPU: "on-demand",
 									},
 								},
@@ -655,7 +655,7 @@ func TestSchedule(t *testing.T) {
 					PodSetFlavors: []kueue.PodSetFlavors{
 						{
 							Name: "one",
-							Flavors: map[corev1.ResourceName]string{
+							ResourceFlavors: map[corev1.ResourceName]string{
 								corev1.ResourceCPU: "spot",
 							},
 						},
@@ -666,7 +666,7 @@ func TestSchedule(t *testing.T) {
 					PodSetFlavors: []kueue.PodSetFlavors{
 						{
 							Name: "one",
-							Flavors: map[corev1.ResourceName]string{
+							ResourceFlavors: map[corev1.ResourceName]string{
 								corev1.ResourceCPU: "on-demand",
 							},
 						},
diff --git a/pkg/util/testing/wrappers.go b/pkg/util/testing/wrappers.go
index afd9fae9a..33c409c27 100644
--- a/pkg/util/testing/wrappers.go
+++ b/pkg/util/testing/wrappers.go
@@ -21,6 +21,7 @@ import (
 
 	batchv1 "k8s.io/api/batch/v1"
 	corev1 "k8s.io/api/core/v1"
+	schedulingv1 "k8s.io/api/scheduling/v1"
 	"k8s.io/apimachinery/pkg/api/resource"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/utils/pointer"
@@ -78,6 +79,12 @@ func (j *JobWrapper) Parallelism(p int32) *JobWrapper {
 	return j
 }
 
+// PriorityClass updates job priorityclass.
+func (j *JobWrapper) PriorityClass(pc string) *JobWrapper {
+	j.Spec.Template.Spec.PriorityClassName = pc
+	return j
+}
+
 // Queue updates the queue name of the job
 func (j *JobWrapper) Queue(queue string) *JobWrapper {
 	j.Annotations[constants.QueueAnnotation] = queue
@@ -102,6 +109,31 @@ func (j *JobWrapper) Request(r corev1.ResourceName, v string) *JobWrapper {
 	return j
 }
 
+// PriorityClassWrapper wraps a PriorityClass.
+type PriorityClassWrapper struct {
+	schedulingv1.PriorityClass
+}
+
+// MakePriorityClass creates a wrapper for a PriorityClass.
+func MakePriorityClass(name string) *PriorityClassWrapper {
+	return &PriorityClassWrapper{schedulingv1.PriorityClass{
+		ObjectMeta: metav1.ObjectMeta{
+			Name: name,
+		}},
+	}
+}
+
+// PriorityValue update value of PriorityClass。
+func (p *PriorityClassWrapper) PriorityValue(v int32) *PriorityClassWrapper {
+	p.Value = v
+	return p
+}
+
+// Obj returns the inner PriorityClass.
+func (p *PriorityClassWrapper) Obj() *schedulingv1.PriorityClass {
+	return &p.PriorityClass
+}
+
 type QueuedWorkloadWrapper struct{ kueue.QueuedWorkload }
 
 // MakeQueuedWorkload creates a wrapper for a QueuedWorkload with a single
@@ -154,6 +186,11 @@ func (w *QueuedWorkloadWrapper) Creation(t time.Time) *QueuedWorkloadWrapper {
 	return w
 }
 
+func (w *QueuedWorkloadWrapper) PriorityClass(priorityClassName string) *QueuedWorkloadWrapper {
+	w.Spec.PriorityClassName = priorityClassName
+	return w
+}
+
 // AdmissionWrapper wraps an Admission
 type AdmissionWrapper struct{ kueue.Admission }
 
@@ -162,8 +199,8 @@ func MakeAdmission(cq string) *AdmissionWrapper {
 		ClusterQueue: kueue.ClusterQueueReference(cq),
 		PodSetFlavors: []kueue.PodSetFlavors{
 			{
-				Name:    "main",
-				Flavors: make(map[corev1.ResourceName]string),
+				Name:            "main",
+				ResourceFlavors: make(map[corev1.ResourceName]string),
 			},
 		},
 	}}
@@ -174,7 +211,7 @@ func (w *AdmissionWrapper) Obj() *kueue.Admission {
 }
 
 func (w *AdmissionWrapper) Flavor(r corev1.ResourceName, f string) *AdmissionWrapper {
-	w.PodSetFlavors[0].Flavors[r] = f
+	w.PodSetFlavors[0].ResourceFlavors[r] = f
 	return w
 }
 
@@ -263,17 +300,17 @@ func (r *ResourceWrapper) Obj() *kueue.Resource {
 }
 
 // Flavor appends a flavor.
-func (r *ResourceWrapper) Flavor(f *kueue.Flavor) *ResourceWrapper {
+func (r *ResourceWrapper) Flavor(f *kueue.ResourceFlavor) *ResourceWrapper {
 	r.Flavors = append(r.Flavors, *f)
 	return r
 }
 
 // FlavorWrapper wraps a resource flavor.
-type FlavorWrapper struct{ kueue.Flavor }
+type FlavorWrapper struct{ kueue.ResourceFlavor }
 
 // MakeFlavor creates a wrapper for a resource flavor.
 func MakeFlavor(name, guaranteed string) *FlavorWrapper {
-	return &FlavorWrapper{kueue.Flavor{
+	return &FlavorWrapper{kueue.ResourceFlavor{
 		Name: name,
 		Quota: kueue.Quota{
 			Guaranteed: resource.MustParse(guaranteed),
@@ -284,8 +321,8 @@ func MakeFlavor(name, guaranteed string) *FlavorWrapper {
 }
 
 // Obj returns the inner resource flavor.
-func (f *FlavorWrapper) Obj() *kueue.Flavor {
-	return &f.Flavor
+func (f *FlavorWrapper) Obj() *kueue.ResourceFlavor {
+	return &f.ResourceFlavor
 }
 
 // Ceiling updates the flavor ceiling.
diff --git a/pkg/workload/workload_test.go b/pkg/workload/workload_test.go
index d14a15537..9d0039607 100644
--- a/pkg/workload/workload_test.go
+++ b/pkg/workload/workload_test.go
@@ -130,7 +130,7 @@ func TestNewInfo(t *testing.T) {
 				PodSetFlavors: []kueue.PodSetFlavors{
 					{
 						Name: "driver",
-						Flavors: map[corev1.ResourceName]string{
+						ResourceFlavors: map[corev1.ResourceName]string{
 							corev1.ResourceCPU: "on-demand",
 						},
 					},
diff --git a/test/integration/controller/job/job_controller_test.go b/test/integration/controller/job/job_controller_test.go
index b9e35e17e..81bd60b36 100644
--- a/test/integration/controller/job/job_controller_test.go
+++ b/test/integration/controller/job/job_controller_test.go
@@ -37,13 +37,15 @@ import (
 )
 
 const (
-	parallelism    = 4
-	jobName        = "test-job"
-	jobNamespace   = "default"
-	jobKey         = jobNamespace + "/" + jobName
-	labelKey       = "cloud.provider.com/instance"
-	flavorOnDemand = "on-demand"
-	flavorSpot     = "spot"
+	parallelism       = 4
+	jobName           = "test-job"
+	jobNamespace      = "default"
+	jobKey            = jobNamespace + "/" + jobName
+	labelKey          = "cloud.provider.com/instance"
+	flavorOnDemand    = "on-demand"
+	flavorSpot        = "spot"
+	priorityClassName = "test-priority-class"
+	priorityValue     = 10
 )
 
 // +kubebuilder:docs-gen:collapse=Imports
@@ -51,7 +53,10 @@ const (
 var _ = ginkgo.Describe("Job controller", func() {
 	ginkgo.It("Should reconcile workload and job", func() {
 		ginkgo.By("checking the job gets suspended when created unsuspended")
-		job := testing.MakeJob(jobName, jobNamespace).Obj()
+		priorityClass := testing.MakePriorityClass(priorityClassName).
+			PriorityValue(int32(priorityValue)).Obj()
+		gomega.Expect(k8sClient.Create(ctx, priorityClass)).Should(gomega.Succeed())
+		job := testing.MakeJob(jobName, jobNamespace).PriorityClass(priorityClassName).Obj()
 		gomega.Expect(k8sClient.Create(ctx, job)).Should(gomega.Succeed())
 		lookupKey := types.NamespacedName{Name: jobName, Namespace: jobNamespace}
 		createdJob := &batchv1.Job{}
@@ -70,6 +75,10 @@ var _ = ginkgo.Describe("Job controller", func() {
 		}, framework.Timeout, framework.Interval).Should(gomega.BeTrue())
 		gomega.Expect(createdWorkload.Spec.QueueName).Should(gomega.Equal(""))
 
+		ginkgo.By("checking the workload is created with priority and priorityName")
+		gomega.Expect(createdWorkload.Spec.PriorityClassName).Should(gomega.Equal(priorityClassName))
+		gomega.Expect(*createdWorkload.Spec.Priority).Should(gomega.Equal(int32(priorityValue)))
+
 		ginkgo.By("checking the workload is updated with queue name when the job does")
 		jobQueueName := "test-queue"
 		createdJob.Annotations = map[string]string{constants.QueueAnnotation: jobQueueName}
@@ -82,7 +91,7 @@ var _ = ginkgo.Describe("Job controller", func() {
 		}, framework.Timeout, framework.Interval).Should(gomega.BeTrue())
 
 		ginkgo.By("checking a second non-matching workload is deleted")
-		secondWl, _ := workloadjob.ConstructWorkloadFor(createdJob, scheme.Scheme)
+		secondWl, _ := workloadjob.ConstructWorkloadFor(ctx, k8sClient, createdJob, scheme.Scheme)
 		secondWl.Name = "second-workload"
 		secondWl.Spec.PodSets[0].Count = parallelism + 1
 		gomega.Expect(k8sClient.Create(ctx, secondWl)).Should(gomega.Succeed())
@@ -114,7 +123,7 @@ var _ = ginkgo.Describe("Job controller", func() {
 		createdWorkload.Spec.Admission = &kueue.Admission{
 			ClusterQueue: kueue.ClusterQueueReference(clusterQueue.Name),
 			PodSetFlavors: []kueue.PodSetFlavors{{
-				Flavors: map[corev1.ResourceName]string{
+				ResourceFlavors: map[corev1.ResourceName]string{
 					corev1.ResourceCPU: flavorOnDemand,
 				},
 			}},
@@ -168,7 +177,7 @@ var _ = ginkgo.Describe("Job controller", func() {
 		createdWorkload.Spec.Admission = &kueue.Admission{
 			ClusterQueue: kueue.ClusterQueueReference(clusterQueue.Name),
 			PodSetFlavors: []kueue.PodSetFlavors{{
-				Flavors: map[corev1.ResourceName]string{
+				ResourceFlavors: map[corev1.ResourceName]string{
 					corev1.ResourceCPU: flavorSpot,
 				},
 			}},
diff --git a/test/integration/scheduler/scheduler_test.go b/test/integration/scheduler/scheduler_test.go
index 50e613e9b..fa5ead8dc 100644
--- a/test/integration/scheduler/scheduler_test.go
+++ b/test/integration/scheduler/scheduler_test.go
@@ -269,4 +269,56 @@ var _ = ginkgo.Describe("Scheduler", func() {
 			return createdJob.Spec.Suspend
 		}, framework.Timeout, framework.Interval).Should(gomega.Equal(pointer.Bool(false)))
 	})
+
+	ginkgo.It("Should schedule jobs according to their priorities", func() {
+		queue := testing.MakeQueue("queue", ns.Name).ClusterQueue(prodClusterQ.Name).Obj()
+
+		highPriorityClass := testing.MakePriorityClass("high-priority-class").PriorityValue(100).Obj()
+		gomega.Expect(k8sClient.Create(ctx, highPriorityClass)).Should(gomega.Succeed())
+
+		lowPriorityClass := testing.MakePriorityClass("low-priority-class").PriorityValue(10).Obj()
+		gomega.Expect(k8sClient.Create(ctx, lowPriorityClass)).Should(gomega.Succeed())
+
+		jobLowPriority := testing.MakeJob("job-low-priority", ns.Name).Queue(queue.Name).Request(corev1.ResourceCPU, "5").PriorityClass(lowPriorityClass.Name).Obj()
+		gomega.Expect(k8sClient.Create(ctx, jobLowPriority)).Should(gomega.Succeed())
+		jobHighPriority := testing.MakeJob("job-high-priority", ns.Name).Queue(queue.Name).Request(corev1.ResourceCPU, "5").PriorityClass(highPriorityClass.Name).Obj()
+		gomega.Expect(k8sClient.Create(ctx, jobHighPriority)).Should(gomega.Succeed())
+
+		ginkgo.By("checking that workload1 is created with priority and priorityName")
+		createdLowPriorityWorkload := &kueue.QueuedWorkload{}
+		gomega.Eventually(func() bool {
+			lookupKey := types.NamespacedName{Name: jobLowPriority.Name, Namespace: jobLowPriority.Namespace}
+			err := k8sClient.Get(ctx, lookupKey, createdLowPriorityWorkload)
+			return err == nil
+		}, framework.Timeout, framework.Interval).Should(gomega.BeTrue())
+		gomega.Expect(createdLowPriorityWorkload.Spec.PriorityClassName).Should(gomega.Equal(lowPriorityClass.Name))
+		gomega.Expect(*createdLowPriorityWorkload.Spec.Priority).Should(gomega.Equal(lowPriorityClass.Value))
+
+		ginkgo.By("checking that workload2 is created with priority and priorityName")
+		createdHighPriorityWorkload := &kueue.QueuedWorkload{}
+		gomega.Eventually(func() bool {
+			lookupKey := types.NamespacedName{Name: jobHighPriority.Name, Namespace: jobHighPriority.Namespace}
+			err := k8sClient.Get(ctx, lookupKey, createdHighPriorityWorkload)
+			return err == nil
+		}, framework.Timeout, framework.Interval).Should(gomega.BeTrue())
+		gomega.Expect(createdHighPriorityWorkload.Spec.PriorityClassName).Should(gomega.Equal(highPriorityClass.Name))
+		gomega.Expect(*createdHighPriorityWorkload.Spec.Priority).Should(gomega.Equal(highPriorityClass.Value))
+
+		// delay creating the queue until after workloads are created.
+		gomega.Expect(k8sClient.Create(ctx, queue)).Should(gomega.Succeed())
+
+		ginkgo.By("checking the job with low priority continues to be suspended")
+		createdJob1 := &batchv1.Job{}
+		gomega.Consistently(func() bool {
+			return k8sClient.Get(ctx, types.NamespacedName{Name: jobLowPriority.Name, Namespace: ns.Name},
+				createdJob1) == nil && *createdJob1.Spec.Suspend
+		}, framework.ConsistentDuration, framework.Interval).Should(gomega.BeTrue())
+
+		ginkgo.By("checking the job with high priority starts")
+		createdJob2 := &batchv1.Job{}
+		gomega.Eventually(func() *bool {
+			gomega.Expect(k8sClient.Get(ctx, types.NamespacedName{Name: jobHighPriority.Name, Namespace: ns.Name}, createdJob2)).Should(gomega.Succeed())
+			return createdJob2.Spec.Suspend
+		}, framework.Timeout, framework.Interval).Should(gomega.Equal(pointer.Bool(false)))
+	})
 })