├── .dockerignore ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.yaml │ ├── config.yaml │ ├── feature_request.yaml │ └── question.yaml ├── PULL_REQUEST_TEMPLATE.md ├── dependabot.yml └── workflows │ ├── check-release.yaml │ ├── integration.yaml │ ├── release-helm-charts.yaml │ ├── release.yaml │ ├── stale.yaml │ └── trivy-image-scanning.yaml ├── .gitignore ├── .golangci.yaml ├── .pre-commit-config.yaml ├── ADOPTERS.md ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── Makefile ├── OWNERS ├── PROJECT ├── README.md ├── VERSION ├── api ├── v1alpha1 │ ├── common_types.go │ ├── defaults.go │ ├── doc.go │ ├── groupversion_info.go │ ├── register.go │ ├── sparkconnect_types.go │ └── zz_generated.deepcopy.go └── v1beta2 │ ├── defaults.go │ ├── defaults_test.go │ ├── doc.go │ ├── groupversion_info.go │ ├── pod_webhook.go │ ├── register.go │ ├── scheduledsparkapplication_types.go │ ├── sparkapplication_types.go │ ├── types.go │ └── zz_generated.deepcopy.go ├── charts └── spark-operator-chart │ ├── .helmignore │ ├── Chart.yaml │ ├── README.md │ ├── README.md.gotmpl │ ├── ci │ ├── ci-values.yaml │ └── kind-config.yaml │ ├── crds │ ├── sparkoperator.k8s.io_scheduledsparkapplications.yaml │ ├── sparkoperator.k8s.io_sparkapplications.yaml │ └── sparkoperator.k8s.io_sparkconnects.yaml │ ├── templates │ ├── _helpers.tpl │ ├── certmanager │ │ ├── _helpers.tpl │ │ ├── certificate.yaml │ │ └── issuer.yaml │ ├── controller │ │ ├── _helpers.tpl │ │ ├── deployment.yaml │ │ ├── poddisruptionbudget.yaml │ │ ├── rbac.yaml │ │ ├── service.yaml │ │ └── serviceaccount.yaml │ ├── prometheus │ │ ├── _helpers.tpl │ │ └── podmonitor.yaml │ ├── spark │ │ ├── _helpers.tpl │ │ ├── rbac.yaml │ │ └── serviceaccount.yaml │ └── webhook │ │ ├── _helpers.tpl │ │ ├── deployment.yaml │ │ ├── mutatingwebhookconfiguration.yaml │ │ ├── poddisruptionbudget.yaml │ │ ├── rbac.yaml │ │ ├── service.yaml │ │ ├── serviceaccount.yaml │ │ └── validatingwebhookconfiguration.yaml │ ├── tests │ ├── certmanager │ │ ├── certificate_test.yaml │ │ └── issuer_test.yaml │ ├── controller │ │ ├── deployment_test.yaml │ │ ├── poddisruptionbudget_test.yaml │ │ ├── rbac_test.yaml │ │ ├── service_test.yaml │ │ └── serviceaccount_test.yaml │ ├── prometheus │ │ └── podmonitor_test.yaml │ ├── spark │ │ ├── rbac_test.yaml │ │ └── serviceaccount_test.yaml │ └── webhook │ │ ├── deployment_test.yaml │ │ ├── mutatingwebhookconfiguration_test.yaml │ │ ├── poddisruptionbudget_test.yaml │ │ ├── rbac_test.yaml │ │ ├── service_test.yaml │ │ └── validatingwebhookconfiguration_test.yaml │ └── values.yaml ├── cmd └── operator │ ├── controller │ ├── root.go │ └── start.go │ ├── main.go │ ├── version │ └── root.go │ └── webhook │ ├── root.go │ └── start.go ├── config ├── certmanager │ ├── certificate.yaml │ ├── kustomization.yaml │ └── kustomizeconfig.yaml ├── crd │ ├── bases │ │ ├── sparkoperator.k8s.io_scheduledsparkapplications.yaml │ │ ├── sparkoperator.k8s.io_sparkapplications.yaml │ │ └── sparkoperator.k8s.io_sparkconnects.yaml │ ├── kustomization.yaml │ ├── kustomizeconfig.yaml │ └── patches │ │ ├── cainjection_in_sparkapplications.yaml │ │ └── webhook_in_sparkapplications.yaml ├── default │ ├── manager_webhook_patch.yaml │ └── webhookcainjection_patch.yaml ├── rbac │ ├── role.yaml │ ├── scheduledsparkapplication_editor_role.yaml │ ├── scheduledsparkapplication_viewer_role.yaml │ ├── spark-application-rbac.yaml │ ├── sparkapplication_editor_role.yaml │ └── sparkapplication_viewer_role.yaml ├── samples │ ├── kustomization.yaml │ ├── v1beta2_scheduledsparkapplication.yaml │ └── v1beta2_sparkapplication.yaml └── webhook │ ├── kustomization.yaml │ ├── kustomizeconfig.yaml │ ├── manifests.yaml │ └── service.yaml ├── docs ├── api-docs.md └── release.md ├── entrypoint.sh ├── examples ├── spark-pi-configmap.yaml ├── spark-pi-custom-resource.yaml ├── spark-pi-dynamic-allocation.yaml ├── spark-pi-kube-scheduler.yaml ├── spark-pi-pod-template.yaml ├── spark-pi-prometheus-servlet.yaml ├── spark-pi-prometheus.yaml ├── spark-pi-python.yaml ├── spark-pi-scheduled.yaml ├── spark-pi-ttl.yaml ├── spark-pi-volcano.yaml ├── spark-pi-yunikorn.yaml ├── spark-pi.yaml └── sparkconnect │ └── spark-connect.yaml ├── go.mod ├── go.sum ├── hack ├── README.md ├── api-docs │ ├── config.json │ └── template │ │ ├── members.tpl │ │ ├── pkg.tpl │ │ ├── placeholder.go │ │ └── type.tpl ├── boilerplate.go.txt ├── generate-changelog.py ├── install_packages.sh ├── update-codegen.sh └── verify-codegen.sh ├── internal ├── controller │ ├── doc.go │ ├── mutatingwebhookconfiguration │ │ ├── controller.go │ │ ├── event_filter.go │ │ └── event_handler.go │ ├── scheduledsparkapplication │ │ ├── controller.go │ │ ├── controller_test.go │ │ ├── event_filter.go │ │ ├── event_handler.go │ │ └── suite_test.go │ ├── sparkapplication │ │ ├── controller.go │ │ ├── controller_test.go │ │ ├── driveringress.go │ │ ├── driveringress_test.go │ │ ├── event_filter.go │ │ ├── event_handler.go │ │ ├── monitoring_config.go │ │ ├── monitoring_config_test.go │ │ ├── submission.go │ │ ├── submission_test.go │ │ ├── suite_test.go │ │ ├── validator.go │ │ ├── web_ui.go │ │ └── web_ui_test.go │ ├── sparkconnect │ │ ├── options.go │ │ ├── reconciler.go │ │ └── util.go │ └── validatingwebhookconfiguration │ │ ├── controller.go │ │ ├── event_filter.go │ │ └── event_handler.go ├── metrics │ ├── metrcis.go │ ├── sparkapplication_metrics.go │ └── sparkpod_metrics.go ├── scheduler │ ├── kubescheduler │ │ ├── scheduler.go │ │ └── util.go │ ├── registry.go │ ├── scheduler.go │ ├── volcano │ │ ├── scheduler.go │ │ ├── scheduler_test.go │ │ └── util.go │ └── yunikorn │ │ ├── resourceusage │ │ ├── java.go │ │ ├── java_test.go │ │ ├── memory.go │ │ ├── memory_test.go │ │ ├── resource_usage.go │ │ └── resource_usage_test.go │ │ ├── scheduler.go │ │ └── scheduler_test.go └── webhook │ ├── doc.go │ ├── resourcequota.go │ ├── resourcequota_test.go │ ├── scheduledsparkapplication_defaulter.go │ ├── scheduledsparkapplication_validator.go │ ├── sparkapplication_defaulter.go │ ├── sparkapplication_validator.go │ ├── sparkpod_defaulter.go │ ├── sparkpod_defaulter_test.go │ ├── suite_test.go │ └── webhook.go ├── pkg ├── certificate │ ├── certificate.go │ ├── certificate_test.go │ ├── doc.go │ ├── suite_test.go │ ├── util.go │ └── util_test.go ├── client │ ├── clientset │ │ └── versioned │ │ │ ├── clientset.go │ │ │ ├── fake │ │ │ ├── clientset_generated.go │ │ │ ├── doc.go │ │ │ └── register.go │ │ │ ├── scheme │ │ │ ├── doc.go │ │ │ └── register.go │ │ │ └── typed │ │ │ └── api │ │ │ └── v1beta2 │ │ │ ├── api_client.go │ │ │ ├── doc.go │ │ │ ├── fake │ │ │ ├── doc.go │ │ │ ├── fake_api_client.go │ │ │ ├── fake_scheduledsparkapplication.go │ │ │ └── fake_sparkapplication.go │ │ │ ├── generated_expansion.go │ │ │ ├── scheduledsparkapplication.go │ │ │ └── sparkapplication.go │ ├── informers │ │ └── externalversions │ │ │ ├── api │ │ │ ├── interface.go │ │ │ └── v1beta2 │ │ │ │ ├── interface.go │ │ │ │ ├── scheduledsparkapplication.go │ │ │ │ └── sparkapplication.go │ │ │ ├── factory.go │ │ │ ├── generic.go │ │ │ └── internalinterfaces │ │ │ └── factory_interfaces.go │ └── listers │ │ └── api │ │ └── v1beta2 │ │ ├── expansion_generated.go │ │ ├── scheduledsparkapplication.go │ │ └── sparkapplication.go ├── common │ ├── constants.go │ ├── doc.go │ ├── event.go │ ├── metrics.go │ ├── prometheus.go │ ├── spark.go │ └── volcano.go └── util │ ├── capabilities.go │ ├── doc.go │ ├── interrupt.go │ ├── metrics.go │ ├── predicates.go │ ├── resourcequota.go │ ├── sparkapplication.go │ ├── sparkapplication_test.go │ ├── sparkpod.go │ ├── sparkpod_test.go │ ├── suite_test.go │ ├── util.go │ ├── util_test.go │ └── workqueue.go ├── proposals └── README.md ├── spark-docker ├── Dockerfile ├── README.md └── conf │ ├── metrics.properties │ └── prometheus.yaml ├── test └── e2e │ ├── bad_examples │ ├── fail-application.yaml │ └── fail-submission.yaml │ ├── sparkapplication_test.go │ ├── sparkconnect_test.go │ └── suit_test.go └── version.go /.dockerignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vscode/ 3 | bin/ 4 | codecov.yaml 5 | cover.out 6 | .DS_Store 7 | *.iml 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yaml: -------------------------------------------------------------------------------- 1 | name: Bug Report 2 | description: Tell us about a problem you are experiencing with the Spark operator. 3 | labels: 4 | - kind/bug 5 | - lifecycle/needs-triage 6 | body: 7 | - type: markdown 8 | attributes: 9 | value: | 10 | Thanks for taking the time to fill out this Spark operator bug report! 11 | - type: textarea 12 | id: problem 13 | attributes: 14 | label: What happened? 15 | description: | 16 | Please provide a clear and concise description of the issue you are encountering, and a reproduction of your configuration. 17 | If your request is for a new feature, please use the `Feature request` template. 18 | value: | 19 | - [ ] ✋ I have searched the open/closed issues and my issue is not listed. 20 | validations: 21 | required: true 22 | - type: textarea 23 | id: reproduce 24 | attributes: 25 | label: Reproduction Code 26 | description: Steps to reproduce the behavior. 27 | - type: textarea 28 | id: expected 29 | attributes: 30 | label: Expected behavior 31 | description: A clear and concise description of what you expected to happen. 32 | - type: textarea 33 | id: actual 34 | attributes: 35 | label: Actual behavior 36 | description: A clear and concise description of what actually happened. 37 | - type: textarea 38 | id: environment 39 | attributes: 40 | label: Environment & Versions 41 | value: | 42 | - Kubernetes Version: 43 | - Spark Operator Version: 44 | - Apache Spark Version: 45 | - type: textarea 46 | id: context 47 | attributes: 48 | label: Additional context 49 | description: Add any other context about the problem here. 50 | - type: input 51 | id: votes 52 | attributes: 53 | label: Impacted by this bug? 54 | value: Give it a 👍 We prioritize the issues with most 👍 55 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yaml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | 3 | contact_links: 4 | - name: Spark Operator Documentation 5 | url: https://www.kubeflow.org/docs/components/spark-operator 6 | about: Much help can be found in the docs 7 | - name: Spark Operator Slack Channel 8 | url: https://app.slack.com/client/T08PSQ7BQ/C074588U7EG 9 | about: Ask questions about the Spark Operator 10 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yaml: -------------------------------------------------------------------------------- 1 | name: Feature Request 2 | description: Suggest an idea for the Spark operator. 3 | labels: 4 | - kind/feature 5 | - lifecycle/needs-triage 6 | body: 7 | - type: markdown 8 | attributes: 9 | value: | 10 | Thanks for taking the time to fill out this Spark operator feature request! 11 | - type: markdown 12 | attributes: 13 | value: | 14 | - Please vote on this issue by adding a 👍 [reaction](https://blog.github.com/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/) to the original issue to help the community and maintainers prioritize this request. 15 | - Please do not leave "+1" or other comments that do not add relevant new information or questions, they generate extra noise for issue followers and do not help prioritize the request. 16 | - If you are interested in working on this issue or have submitted a pull request, please leave a comment. 17 | - type: textarea 18 | id: feature 19 | attributes: 20 | label: What feature you would like to be added? 21 | description: | 22 | A clear and concise description of what you want to add to the Spark operator. 23 | Please consider to write a Spark operator enhancement proposal if it is a large feature request. 24 | validations: 25 | required: true 26 | - type: textarea 27 | id: rationale 28 | attributes: 29 | label: Why is this needed? 30 | - type: textarea 31 | id: solution 32 | attributes: 33 | label: Describe the solution you would like 34 | - type: textarea 35 | id: alternatives 36 | attributes: 37 | label: Describe alternatives you have considered 38 | - type: textarea 39 | id: context 40 | attributes: 41 | label: Additional context 42 | description: Add any other context or screenshots about the feature request here. 43 | - type: input 44 | id: votes 45 | attributes: 46 | label: Love this feature? 47 | value: Give it a 👍 We prioritize the features with most 👍 48 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.yaml: -------------------------------------------------------------------------------- 1 | name: Question 2 | description: Ask question about the Spark operator. 3 | labels: 4 | - kind/question 5 | - lifecycle/needs-triage 6 | body: 7 | - type: markdown 8 | attributes: 9 | value: | 10 | Thanks for taking the time to fill out this question! 11 | - type: textarea 12 | id: feature 13 | attributes: 14 | label: What question do you want to ask? 15 | description: | 16 | A clear and concise description of what you want to ask about the Spark operator. 17 | value: | 18 | - [ ] ✋ I have searched the open/closed issues and my issue is not listed. 19 | validations: 20 | required: true 21 | - type: textarea 22 | id: rationale 23 | attributes: 24 | label: Additional context 25 | description: Add any other context or screenshots about the question here. 26 | - type: input 27 | id: votes 28 | attributes: 29 | label: Have the same question? 30 | value: Give it a 👍 We prioritize the question with most 👍 31 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 7 | 8 | ## Purpose of this PR 9 | 10 | 11 | 12 | **Proposed changes:** 13 | 14 | - 15 | - 16 | - 17 | 18 | ## Change Category 19 | 20 | 21 | 22 | - [ ] Bugfix (non-breaking change which fixes an issue) 23 | - [ ] Feature (non-breaking change which adds functionality) 24 | - [ ] Breaking change (fix or feature that could affect existing functionality) 25 | - [ ] Documentation update 26 | 27 | ### Rationale 28 | 29 | 30 | 31 | ## Checklist 32 | 33 | 34 | 35 | - [ ] I have conducted a self-review of my own code. 36 | - [ ] I have updated documentation accordingly. 37 | - [ ] I have added tests that prove my changes are effective or that my feature works. 38 | - [ ] Existing unit tests pass locally with my changes. 39 | 40 | ### Additional Notes 41 | 42 | 43 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "gomod" 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | 8 | - package-ecosystem: "docker" 9 | directory: "/" 10 | schedule: 11 | interval: "weekly" 12 | 13 | - package-ecosystem: "github-actions" 14 | directory: "/" 15 | schedule: 16 | interval: "weekly" 17 | -------------------------------------------------------------------------------- /.github/workflows/check-release.yaml: -------------------------------------------------------------------------------- 1 | name: Check Release 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - release-* 7 | paths: 8 | - VERSION 9 | 10 | concurrency: 11 | group: ${{ github.workflow }}-${{ github.ref }} 12 | cancel-in-progress: true 13 | 14 | env: 15 | SEMVER_PATTERN: '^v([0-9]+)\.([0-9]+)\.([0-9]+)(-rc\.([0-9]+))?$' 16 | 17 | jobs: 18 | check: 19 | runs-on: ubuntu-latest 20 | 21 | steps: 22 | - name: Checkout source code 23 | uses: actions/checkout@v4 24 | with: 25 | fetch-depth: 0 26 | 27 | - name: Check whether version matches semver pattern 28 | run: | 29 | VERSION=$(cat VERSION) 30 | if [[ ${VERSION} =~ ${{ env.SEMVER_PATTERN }} ]]; then 31 | echo "Version '${VERSION}' matches semver pattern." 32 | else 33 | echo "Version '${VERSION}' does not match semver pattern." 34 | exit 1 35 | fi 36 | echo "VERSION=${VERSION}" >> $GITHUB_ENV 37 | 38 | - name: Check whether chart version and appVersion matches version 39 | run: | 40 | VERSION=${VERSION#v} 41 | CHART_VERSION=$(cat charts/spark-operator-chart/Chart.yaml | grep version | awk '{print $2}') 42 | CHART_APP_VERSION=$(cat charts/spark-operator-chart/Chart.yaml | grep appVersion | awk '{print $2}') 43 | if [[ ${CHART_VERSION} == ${VERSION} ]]; then 44 | echo "Chart version '${CHART_VERSION}' matches version '${VERSION}'." 45 | else 46 | echo "Chart version '${CHART_VERSION}' does not match version '${VERSION}'." 47 | exit 1 48 | fi 49 | if [[ ${CHART_APP_VERSION} == ${VERSION} ]]; then 50 | echo "Chart appVersion '${CHART_APP_VERSION}' matches version '${VERSION}'." 51 | else 52 | echo "Chart appVersion '${CHART_APP_VERSION}' does not match version '${VERSION}'." 53 | exit 1 54 | fi 55 | 56 | - name: Check if tag exists 57 | run: | 58 | git fetch --tags 59 | if git tag -l | grep -q "^${VERSION}$"; then 60 | echo "Tag '${VERSION}' already exists." 61 | exit 1 62 | else 63 | echo "Tag '${VERSION}' does not exist." 64 | fi 65 | -------------------------------------------------------------------------------- /.github/workflows/release-helm-charts.yaml: -------------------------------------------------------------------------------- 1 | name: Release Helm charts 2 | 3 | on: 4 | release: 5 | types: 6 | - published 7 | 8 | concurrency: 9 | group: ${{ github.workflow }}-${{ github.ref }} 10 | cancel-in-progress: true 11 | 12 | env: 13 | HELM_REGISTRY: ghcr.io 14 | HELM_REPOSITORY: ${{ github.repository_owner }}/helm-charts 15 | 16 | jobs: 17 | release_helm_charts: 18 | permissions: 19 | contents: write 20 | packages: write 21 | 22 | runs-on: ubuntu-latest 23 | 24 | steps: 25 | - name: Checkout source code 26 | uses: actions/checkout@v4 27 | 28 | - name: Configure Git 29 | run: | 30 | git config user.name "$GITHUB_ACTOR" 31 | git config user.email "$GITHUB_ACTOR@users.noreply.github.com" 32 | 33 | - name: Set up Helm 34 | uses: azure/setup-helm@v4.2.0 35 | with: 36 | version: v3.14.4 37 | 38 | - name: Login to GHCR 39 | uses: docker/login-action@v3 40 | with: 41 | registry: ${{ env.HELM_REGISTRY }} 42 | username: ${{ github.repository_owner }} 43 | password: ${{ secrets.GITHUB_TOKEN }} 44 | 45 | - name: Read version from VERSION file 46 | run: | 47 | VERSION=$(cat VERSION) 48 | echo "VERSION=${VERSION}" >> $GITHUB_ENV 49 | 50 | - name: Package Helm charts 51 | run: | 52 | for chart in $(ls charts); do 53 | helm package charts/${chart} 54 | done 55 | 56 | - name: Upload charts to GHCR 57 | run: | 58 | for pkg in $(ls *.tgz); do 59 | helm push ${pkg} oci://${{ env.HELM_REGISTRY }}/${{ env.HELM_REPOSITORY }} 60 | done 61 | 62 | - name: Save packaged charts to temp directory 63 | run: | 64 | mkdir -p /tmp/charts 65 | cp *.tgz /tmp/charts 66 | 67 | - name: Checkout to branch gh-pages 68 | uses: actions/checkout@v4 69 | with: 70 | ref: gh-pages 71 | fetch-depth: 0 72 | 73 | - name: Copy packaged charts 74 | run: | 75 | cp /tmp/charts/*.tgz . 76 | 77 | - name: Update Helm charts repo index 78 | env: 79 | CHART_URL: https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }} 80 | run: | 81 | helm repo index --merge index.yaml --url ${CHART_URL} . 82 | git add index.yaml 83 | git commit -s -m "Add index for Spark operator chart ${VERSION}" || exit 0 84 | git push 85 | -------------------------------------------------------------------------------- /.github/workflows/stale.yaml: -------------------------------------------------------------------------------- 1 | name: Mark stale issues and pull requests 2 | 3 | on: 4 | schedule: 5 | - cron: "0 */2 * * *" 6 | 7 | jobs: 8 | stale: 9 | runs-on: ubuntu-latest 10 | 11 | permissions: 12 | issues: write 13 | pull-requests: write 14 | 15 | steps: 16 | - uses: actions/stale@v9 17 | with: 18 | repo-token: ${{ secrets.GITHUB_TOKEN }} 19 | days-before-stale: 90 20 | days-before-close: 20 21 | operations-per-run: 200 22 | stale-issue-message: > 23 | This issue has been automatically marked as stale because it has not had 24 | recent activity. It will be closed if no further activity occurs. Thank you 25 | for your contributions. 26 | close-issue-message: > 27 | This issue has been automatically closed because it has not had recent 28 | activity. Please comment "/reopen" to reopen it. 29 | stale-issue-label: lifecycle/stale 30 | exempt-issue-labels: lifecycle/frozen 31 | stale-pr-message: > 32 | This pull request has been automatically marked as stale because it has not had 33 | recent activity. It will be closed if no further activity occurs. Thank you 34 | for your contributions. 35 | close-pr-message: > 36 | This pull request has been automatically closed because it has not had recent 37 | activity. Please comment "/reopen" to reopen it. 38 | stale-pr-label: lifecycle/stale 39 | exempt-pr-labels: lifecycle/frozen 40 | -------------------------------------------------------------------------------- /.github/workflows/trivy-image-scanning.yaml: -------------------------------------------------------------------------------- 1 | name: Trivy image scanning 2 | on: 3 | workflow_dispatch: 4 | schedule: 5 | - cron: '0 0 * * 1' # Every Monday at 00:00 6 | 7 | jobs: 8 | image-scanning: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout code 12 | uses: actions/checkout@v4 13 | 14 | - name: Add image to environment 15 | run: make print-IMAGE >> $GITHUB_ENV 16 | 17 | - name: trivy scan for github security tab 18 | uses: aquasecurity/trivy-action@0.32.0 19 | with: 20 | image-ref: '${{ env.IMAGE }}' 21 | format: 'sarif' 22 | ignore-unfixed: true 23 | vuln-type: 'os,library' 24 | severity: 'CRITICAL,HIGH' 25 | output: 'trivy-results.sarif' 26 | timeout: 30m0s 27 | 28 | - name: Upload Trivy scan results to GitHub Security tab 29 | uses: github/codeql-action/upload-sarif@v3 30 | if: always() 31 | with: 32 | sarif_file: 'trivy-results.sarif' 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vscode/ 3 | bin/ 4 | codecov.yaml 5 | cover.out 6 | .DS_Store 7 | *.iml 8 | -------------------------------------------------------------------------------- /.golangci.yaml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | 3 | run: 4 | # Timeout for total work, e.g. 30s, 5m, 5m30s. 5 | # If the value is lower or equal to 0, the timeout is disabled. 6 | # Default: 0 (disabled) 7 | timeout: 2m 8 | 9 | linters: 10 | # Enable specific linters. 11 | # https://golangci-lint.run/usage/linters/#enabled-by-default 12 | enable: 13 | # Detects places where loop variables are copied. 14 | - copyloopvar 15 | # Checks for duplicate words in the source code. 16 | - dupword 17 | # Tool for detection of FIXME, TODO and other comment keywords. 18 | # - godox 19 | # Enforces consistent import aliases. 20 | - importas 21 | # Find code that shadows one of Go's predeclared identifiers. 22 | - predeclared 23 | # Check that struct tags are well aligned. 24 | - tagalign 25 | # Remove unnecessary type conversions. 26 | - unconvert 27 | # Checks Go code for unused constants, variables, functions and types. 28 | - unused 29 | 30 | settings: 31 | importas: 32 | # List of aliases 33 | alias: 34 | - pkg: k8s.io/api/admissionregistration/v1 35 | alias: admissionregistrationv1 36 | - pkg: k8s.io/api/apps/v1 37 | alias: appsv1 38 | - pkg: k8s.io/api/batch/v1 39 | alias: batchv1 40 | - pkg: k8s.io/api/core/v1 41 | alias: corev1 42 | - pkg: k8s.io/api/extensions/v1beta1 43 | alias: extensionsv1beta1 44 | - pkg: k8s.io/api/networking/v1 45 | alias: networkingv1 46 | - pkg: k8s.io/apimachinery/pkg/apis/meta/v1 47 | alias: metav1 48 | - pkg: sigs.k8s.io/controller-runtime 49 | alias: ctrl 50 | 51 | issues: 52 | # Maximum issues count per one linter. 53 | # Set to 0 to disable. 54 | # Default: 50 55 | max-issues-per-linter: 50 56 | # Maximum count of issues with the same text. 57 | # Set to 0 to disable. 58 | # Default: 3 59 | max-same-issues: 3 60 | 61 | formatters: 62 | enable: 63 | # Check import statements are formatted according to the 'goimport' command. 64 | - goimports 65 | 66 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/norwoodj/helm-docs 3 | rev: "v1.13.1" 4 | hooks: 5 | - id: helm-docs 6 | args: 7 | # Make the tool search for charts only under the `charts` directory 8 | - --chart-search-root=charts 9 | - --template-files=README.md.gotmpl 10 | - --sort-values-order=file 11 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | For the code of conduct, please refer to the [Kubeflow Community Code of Conduct](https://www.kubeflow.org/docs/about/contributing/#follow-the-code-of-conduct). 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Kubeflow Spark Operator 2 | 3 | Welcome to the Kubeflow Spark Operator project. We'd love to accept your patches and contributions to this project. For detailed information about how to contribute to Kubeflow, please refer to [Contributing to Kubeflow](https://www.kubeflow.org/docs/about/contributing/). 4 | 5 | ## Developer Guide 6 | 7 | For how to develope with spark operator, please refer to [Developer Guide](https://www.kubeflow.org/docs/components/spark-operator/developer-guide/). 8 | 9 | ## Code Reviews 10 | 11 | All submissions, including submissions by project members, require review. We use GitHub pull requests for this purpose. Consult [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more information on using pull requests. 12 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | ARG SPARK_IMAGE=docker.io/library/spark:4.0.0 18 | 19 | FROM golang:1.24.1 AS builder 20 | 21 | WORKDIR /workspace 22 | 23 | RUN --mount=type=cache,target=/go/pkg/mod/ \ 24 | --mount=type=bind,source=go.mod,target=go.mod \ 25 | --mount=type=bind,source=go.sum,target=go.sum \ 26 | go mod download 27 | 28 | COPY . . 29 | 30 | ENV GOCACHE=/root/.cache/go-build 31 | 32 | ARG TARGETARCH 33 | 34 | RUN --mount=type=cache,target=/go/pkg/mod/ \ 35 | --mount=type=cache,target="/root/.cache/go-build" \ 36 | CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH} GO111MODULE=on make build-operator 37 | 38 | FROM ${SPARK_IMAGE} 39 | 40 | ARG SPARK_UID=185 41 | 42 | ARG SPARK_GID=185 43 | 44 | USER root 45 | 46 | RUN apt-get update \ 47 | && apt-get install -y tini \ 48 | && rm -rf /var/lib/apt/lists/* 49 | 50 | RUN mkdir -p /etc/k8s-webhook-server/serving-certs /home/spark && \ 51 | chmod -R g+rw /etc/k8s-webhook-server/serving-certs && \ 52 | chown -R spark /etc/k8s-webhook-server/serving-certs /home/spark 53 | 54 | USER ${SPARK_UID}:${SPARK_GID} 55 | 56 | COPY --from=builder /workspace/bin/spark-operator /usr/bin/spark-operator 57 | 58 | COPY entrypoint.sh /usr/bin/ 59 | 60 | ENTRYPOINT ["/usr/bin/entrypoint.sh"] 61 | -------------------------------------------------------------------------------- /OWNERS: -------------------------------------------------------------------------------- 1 | approvers: 2 | - andreyvelich 3 | - ChenYi015 4 | - jacobsalway 5 | - mwielgus 6 | - vara-bonthu 7 | - yuchaoran2011 8 | reviewers: 9 | - ImpSy 10 | - nabuskey 11 | -------------------------------------------------------------------------------- /PROJECT: -------------------------------------------------------------------------------- 1 | # Code generated by tool. DO NOT EDIT. 2 | # This file is used to track the info used to scaffold your project 3 | # and allow the plugins properly work. 4 | # More info: https://book.kubebuilder.io/reference/project-config.html 5 | domain: sparkoperator.k8s.io 6 | layout: 7 | - go.kubebuilder.io/v4 8 | projectName: spark-operator 9 | repo: github.com/kubeflow/spark-operator 10 | resources: 11 | - api: 12 | crdVersion: v1 13 | namespaced: true 14 | controller: true 15 | domain: sparkoperator.k8s.io 16 | kind: SparkConnect 17 | path: github.com/kubeflow/spark-operator/api/v1alpha1 18 | version: v1alpha1 19 | - api: 20 | crdVersion: v1 21 | namespaced: true 22 | controller: true 23 | domain: sparkoperator.k8s.io 24 | kind: SparkApplication 25 | path: github.com/kubeflow/spark-operator/api/v1beta2 26 | version: v1beta2 27 | webhooks: 28 | defaulting: true 29 | validation: true 30 | webhookVersion: v1 31 | - api: 32 | crdVersion: v1 33 | namespaced: true 34 | controller: true 35 | domain: sparkoperator.k8s.io 36 | kind: ScheduledSparkApplication 37 | path: github.com/kubeflow/spark-operator/api/v1beta2 38 | version: v1beta2 39 | version: "3" 40 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | v2.2.1 2 | -------------------------------------------------------------------------------- /api/v1alpha1/defaults.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2025 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1alpha1 18 | 19 | // SetSparkConnectDefaults sets default values for certain fields of a SparkConnect. 20 | func SetSparkConnectDefaults(conn *SparkConnect) { 21 | } 22 | -------------------------------------------------------------------------------- /api/v1alpha1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2025 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // +k8s:deepcopy-gen=package,register 18 | 19 | // Package v1alpha1 is the v1alpha1 version of the API. 20 | // +groupName=sparkoperator.k8s.io 21 | // +versionName=v1alpha1 22 | package v1alpha1 23 | -------------------------------------------------------------------------------- /api/v1alpha1/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2025 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package v1alpha1 contains API Schema definitions for the v1alpha1 API group 18 | // +kubebuilder:object:generate=true 19 | // +groupName=sparkoperator.k8s.io 20 | package v1alpha1 21 | 22 | import ( 23 | "k8s.io/apimachinery/pkg/runtime/schema" 24 | "sigs.k8s.io/controller-runtime/pkg/scheme" 25 | ) 26 | 27 | var ( 28 | // GroupVersion is group version used to register these objects. 29 | GroupVersion = schema.GroupVersion{Group: "sparkoperator.k8s.io", Version: "v1alpha1"} 30 | 31 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme. 32 | SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} 33 | 34 | // AddToScheme adds the types in this group-version to the given scheme. 35 | AddToScheme = SchemeBuilder.AddToScheme 36 | ) 37 | -------------------------------------------------------------------------------- /api/v1alpha1/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2025 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1alpha1 18 | 19 | import ( 20 | "k8s.io/apimachinery/pkg/runtime/schema" 21 | ) 22 | 23 | const ( 24 | Group = "sparkoperator.k8s.io" 25 | Version = "v1alpha1" 26 | ) 27 | 28 | // SchemeGroupVersion is the group version used to register these objects. 29 | var SchemeGroupVersion = schema.GroupVersion{Group: Group, Version: Version} 30 | 31 | // Resource takes an unqualified resource and returns a Group-qualified GroupResource. 32 | func Resource(resource string) schema.GroupResource { 33 | return SchemeGroupVersion.WithResource(resource).GroupResource() 34 | } 35 | -------------------------------------------------------------------------------- /api/v1beta2/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 Google LLC 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // +k8s:deepcopy-gen=package,register 18 | 19 | // Package v1beta2 is the v1beta2 version of the API. 20 | // +groupName=sparkoperator.k8s.io 21 | // +versionName=v1beta2 22 | package v1beta2 23 | -------------------------------------------------------------------------------- /api/v1beta2/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package v1beta2 contains API Schema definitions for the v1beta2 API group 18 | // +kubebuilder:object:generate=true 19 | // +groupName=sparkoperator.k8s.io 20 | package v1beta2 21 | 22 | import ( 23 | "k8s.io/apimachinery/pkg/runtime/schema" 24 | "sigs.k8s.io/controller-runtime/pkg/scheme" 25 | ) 26 | 27 | var ( 28 | // GroupVersion is group version used to register these objects. 29 | GroupVersion = schema.GroupVersion{Group: "sparkoperator.k8s.io", Version: "v1beta2"} 30 | 31 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme. 32 | SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} 33 | 34 | // AddToScheme adds the types in this group-version to the given scheme. 35 | AddToScheme = SchemeBuilder.AddToScheme 36 | ) 37 | -------------------------------------------------------------------------------- /api/v1beta2/pod_webhook.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1beta2 18 | -------------------------------------------------------------------------------- /api/v1beta2/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1beta2 18 | 19 | import ( 20 | "k8s.io/apimachinery/pkg/runtime/schema" 21 | ) 22 | 23 | const ( 24 | Group = "sparkoperator.k8s.io" 25 | Version = "v1beta2" 26 | ) 27 | 28 | // SchemeGroupVersion is the group version used to register these objects. 29 | var SchemeGroupVersion = schema.GroupVersion{Group: Group, Version: Version} 30 | 31 | // Resource takes an unqualified resource and returns a Group-qualified GroupResource. 32 | func Resource(resource string) schema.GroupResource { 33 | return SchemeGroupVersion.WithResource(resource).GroupResource() 34 | } 35 | -------------------------------------------------------------------------------- /api/v1beta2/types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2025 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | This file is needed for kubernetes/code-generator/kube_codegen.sh script used in hack/update-codegen.sh. 19 | */ 20 | 21 | package v1beta2 22 | 23 | //+genclient 24 | -------------------------------------------------------------------------------- /charts/spark-operator-chart/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | 5 | ci/ 6 | .helmignore 7 | 8 | # Common VCS dirs 9 | .git/ 10 | .gitignore 11 | .bzr/ 12 | .bzrignore 13 | .hg/ 14 | .hgignore 15 | .svn/ 16 | 17 | # Common backup files 18 | *.swp 19 | *.bak 20 | *.tmp 21 | *.orig 22 | *~ 23 | 24 | # Various IDEs 25 | *.tmproj 26 | .project 27 | .idea/ 28 | .vscode/ 29 | 30 | # MacOS 31 | .DS_Store 32 | 33 | # helm-unittest 34 | tests 35 | .debug 36 | __snapshot__ 37 | 38 | # helm-docs 39 | README.md.gotmpl 40 | -------------------------------------------------------------------------------- /charts/spark-operator-chart/Chart.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2024 The Kubeflow authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | apiVersion: v2 18 | 19 | name: spark-operator 20 | 21 | description: A Helm chart for Spark on Kubernetes operator. 22 | 23 | version: 2.2.1 24 | 25 | appVersion: 2.2.1 26 | 27 | keywords: 28 | - apache spark 29 | - big data 30 | 31 | home: https://github.com/kubeflow/spark-operator 32 | 33 | maintainers: 34 | - name: yuchaoran2011 35 | email: yuchaoran2011@gmail.com 36 | url: https://github.com/yuchaoran2011 37 | - name: ChenYi015 38 | email: github@chenyicn.net 39 | url: https://github.com/ChenYi015 40 | -------------------------------------------------------------------------------- /charts/spark-operator-chart/ci/ci-values.yaml: -------------------------------------------------------------------------------- 1 | image: 2 | tag: local 3 | -------------------------------------------------------------------------------- /charts/spark-operator-chart/ci/kind-config.yaml: -------------------------------------------------------------------------------- 1 | kind: Cluster 2 | apiVersion: kind.x-k8s.io/v1alpha4 3 | nodes: 4 | - role: control-plane 5 | - role: worker 6 | -------------------------------------------------------------------------------- /charts/spark-operator-chart/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */}} 16 | 17 | {{/* vim: set filetype=mustache: */}} 18 | {{/* 19 | Expand the name of the chart. 20 | */}} 21 | {{- define "spark-operator.name" -}} 22 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} 23 | {{- end -}} 24 | 25 | {{/* 26 | Create a default fully qualified app name. 27 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 28 | If release name contains chart name it will be used as a full name. 29 | */}} 30 | {{- define "spark-operator.fullname" -}} 31 | {{- if .Values.fullnameOverride -}} 32 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} 33 | {{- else -}} 34 | {{- $name := default .Chart.Name .Values.nameOverride -}} 35 | {{- if contains $name .Release.Name -}} 36 | {{- .Release.Name | trunc 63 | trimSuffix "-" -}} 37 | {{- else -}} 38 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} 39 | {{- end -}} 40 | {{- end -}} 41 | {{- end -}} 42 | 43 | {{/* 44 | Create chart name and version as used by the chart label. 45 | */}} 46 | {{- define "spark-operator.chart" -}} 47 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} 48 | {{- end -}} 49 | 50 | {{/* 51 | Common labels 52 | */}} 53 | {{- define "spark-operator.labels" -}} 54 | helm.sh/chart: {{ include "spark-operator.chart" . }} 55 | {{ include "spark-operator.selectorLabels" . }} 56 | {{- if .Chart.AppVersion }} 57 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 58 | {{- end }} 59 | app.kubernetes.io/managed-by: {{ .Release.Service }} 60 | {{- with .Values.commonLabels }} 61 | {{ toYaml . }} 62 | {{- end }} 63 | {{- end }} 64 | 65 | {{/* 66 | Selector labels 67 | */}} 68 | {{- define "spark-operator.selectorLabels" -}} 69 | app.kubernetes.io/name: {{ include "spark-operator.name" . }} 70 | app.kubernetes.io/instance: {{ .Release.Name }} 71 | {{- end }} 72 | 73 | {{/* 74 | Spark Operator image 75 | */}} 76 | {{- define "spark-operator.image" -}} 77 | {{ printf "%s/%s:%s" .Values.image.registry .Values.image.repository (.Values.image.tag | default .Chart.AppVersion | toString) }} 78 | {{- end -}} 79 | -------------------------------------------------------------------------------- /charts/spark-operator-chart/templates/certmanager/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{- /* 2 | Copyright 2025 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ -}} 16 | 17 | {{/* 18 | Create the name of the webhook certificate issuer. 19 | */}} 20 | {{- define "spark-operator.certManager.issuer.name" -}} 21 | {{ include "spark-operator.name" . }}-self-signed-issuer 22 | {{- end -}} 23 | 24 | {{/* 25 | Create the name of the certificate to be used by webhook. 26 | */}} 27 | {{- define "spark-operator.certManager.certificate.name" -}} 28 | {{ include "spark-operator.name" . }}-certificate 29 | {{- end -}} 30 | -------------------------------------------------------------------------------- /charts/spark-operator-chart/templates/certmanager/certificate.yaml: -------------------------------------------------------------------------------- 1 | {{- /* 2 | Copyright 2025 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ -}} 16 | 17 | {{- if .Values.webhook.enable }} 18 | {{- if .Values.certManager.enable }} 19 | {{- if not (.Capabilities.APIVersions.Has "cert-manager.io/v1/Certificate") }} 20 | {{- fail "The cluster does not support the required API version `cert-manager.io/v1` for `Certificate`." }} 21 | {{- end }} 22 | apiVersion: cert-manager.io/v1 23 | kind: Certificate 24 | metadata: 25 | name: {{ include "spark-operator.certManager.certificate.name" . }} 26 | namespace: {{ .Release.Namespace }} 27 | labels: 28 | {{- include "spark-operator.labels" . | nindent 4 }} 29 | spec: 30 | secretName: {{ include "spark-operator.webhook.secretName" . }} 31 | issuerRef: 32 | {{- if not .Values.certManager.issuerRef }} 33 | group: cert-manager.io 34 | kind: Issuer 35 | name: {{ include "spark-operator.certManager.issuer.name" . }} 36 | {{- else }} 37 | {{- toYaml .Values.certManager.issuerRef | nindent 4 }} 38 | {{- end }} 39 | commonName: {{ include "spark-operator.webhook.serviceName" . }}.{{ .Release.Namespace }}.svc 40 | dnsNames: 41 | - {{ include "spark-operator.webhook.serviceName" . }}.{{ .Release.Namespace }}.svc 42 | - {{ include "spark-operator.webhook.serviceName" . }}.{{ .Release.Namespace }}.svc.cluster.local 43 | subject: 44 | organizationalUnits: 45 | - spark-operator 46 | usages: 47 | - server auth 48 | - client auth 49 | {{- with .Values.certManager.duration }} 50 | duration: {{ . }} 51 | {{- end }} 52 | {{- with .Values.certManager.renewBefore }} 53 | renewBefore: {{ . }} 54 | {{- end }} 55 | {{- end }} 56 | {{- end }} 57 | -------------------------------------------------------------------------------- /charts/spark-operator-chart/templates/certmanager/issuer.yaml: -------------------------------------------------------------------------------- 1 | {{- /* 2 | Copyright 2025 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ -}} 16 | 17 | {{- if .Values.webhook.enable }} 18 | {{- if .Values.certManager.enable }} 19 | {{- if not .Values.certManager.issuerRef }} 20 | {{- if not (.Capabilities.APIVersions.Has "cert-manager.io/v1/Issuer") }} 21 | {{- fail "The cluster does not support the required API version `cert-manager.io/v1` for `Issuer`." }} 22 | {{- end }} 23 | apiVersion: cert-manager.io/v1 24 | kind: Issuer 25 | metadata: 26 | name: {{ include "spark-operator.certManager.issuer.name" . }} 27 | namespace: {{ .Release.Namespace }} 28 | labels: 29 | {{- include "spark-operator.labels" . | nindent 4 }} 30 | spec: 31 | selfSigned: {} 32 | {{- end }} 33 | {{- end }} 34 | {{- end }} 35 | -------------------------------------------------------------------------------- /charts/spark-operator-chart/templates/controller/poddisruptionbudget.yaml: -------------------------------------------------------------------------------- 1 | {{/* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */}} 16 | 17 | {{- if .Values.controller.podDisruptionBudget.enable }} 18 | {{- if le (int .Values.controller.replicas) 1 }} 19 | {{- fail "controller.replicas must be greater than 1 to enable pod disruption budget for controller" }} 20 | {{- end -}} 21 | apiVersion: policy/v1 22 | kind: PodDisruptionBudget 23 | metadata: 24 | name: {{ include "spark-operator.controller.podDisruptionBudgetName" . }} 25 | labels: 26 | {{- include "spark-operator.controller.labels" . | nindent 4 }} 27 | spec: 28 | selector: 29 | matchLabels: 30 | {{- include "spark-operator.controller.selectorLabels" . | nindent 6 }} 31 | {{- with .Values.controller.podDisruptionBudget.minAvailable }} 32 | minAvailable: {{ . }} 33 | {{- end }} 34 | {{- end }} 35 | -------------------------------------------------------------------------------- /charts/spark-operator-chart/templates/controller/service.yaml: -------------------------------------------------------------------------------- 1 | {{/* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */}} 16 | 17 | {{- if .Values.controller.pprof.enable }} 18 | apiVersion: v1 19 | kind: Service 20 | metadata: 21 | name: {{ include "spark-operator.controller.serviceName" . }} 22 | labels: 23 | {{- include "spark-operator.controller.labels" . | nindent 4 }} 24 | spec: 25 | selector: 26 | {{- include "spark-operator.controller.selectorLabels" . | nindent 4 }} 27 | ports: 28 | - port: {{ .Values.controller.pprof.port }} 29 | targetPort: {{ .Values.controller.pprof.portName | quote }} 30 | name: {{ .Values.controller.pprof.portName }} 31 | {{- end }} 32 | -------------------------------------------------------------------------------- /charts/spark-operator-chart/templates/controller/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{/* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */}} 16 | 17 | {{- if .Values.controller.serviceAccount.create }} 18 | apiVersion: v1 19 | kind: ServiceAccount 20 | automountServiceAccountToken: {{ .Values.controller.serviceAccount.automountServiceAccountToken }} 21 | metadata: 22 | name: {{ include "spark-operator.controller.serviceAccountName" . }} 23 | namespace: {{ .Release.Namespace }} 24 | labels: 25 | {{- include "spark-operator.controller.labels" . | nindent 4 }} 26 | {{- with .Values.controller.serviceAccount.annotations }} 27 | annotations: 28 | {{- toYaml . | nindent 4 }} 29 | {{- end }} 30 | {{- end }} 31 | -------------------------------------------------------------------------------- /charts/spark-operator-chart/templates/prometheus/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */}} 16 | 17 | {{/* 18 | Create the name of pod monitor 19 | */}} 20 | {{- define "spark-operator.prometheus.podMonitorName" -}} 21 | {{- include "spark-operator.fullname" . }}-podmonitor 22 | {{- end -}} 23 | -------------------------------------------------------------------------------- /charts/spark-operator-chart/templates/prometheus/podmonitor.yaml: -------------------------------------------------------------------------------- 1 | {{/* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */}} 16 | 17 | {{- if .Values.prometheus.podMonitor.create -}} 18 | {{- if not .Values.prometheus.metrics.enable }} 19 | {{- fail "`metrics.enable` must be set to true when `podMonitor.create` is true." }} 20 | {{- end }} 21 | {{- if not (.Capabilities.APIVersions.Has "monitoring.coreos.com/v1/PodMonitor") }} 22 | {{- fail "The cluster does not support the required API version `monitoring.coreos.com/v1` for `PodMonitor`." }} 23 | {{- end }} 24 | apiVersion: monitoring.coreos.com/v1 25 | kind: PodMonitor 26 | metadata: 27 | name: {{ include "spark-operator.prometheus.podMonitorName" . }} 28 | {{- with .Values.prometheus.podMonitor.labels }} 29 | labels: 30 | {{- toYaml . | nindent 4 }} 31 | {{- end }} 32 | spec: 33 | podMetricsEndpoints: 34 | - interval: {{ .Values.prometheus.podMonitor.podMetricsEndpoint.interval }} 35 | port: {{ .Values.prometheus.metrics.portName | quote }} 36 | scheme: {{ .Values.prometheus.podMonitor.podMetricsEndpoint.scheme }} 37 | jobLabel: {{ .Values.prometheus.podMonitor.jobLabel }} 38 | namespaceSelector: 39 | matchNames: 40 | - {{ .Release.Namespace }} 41 | selector: 42 | matchLabels: 43 | {{- include "spark-operator.selectorLabels" . | nindent 6 }} 44 | {{- end }} 45 | -------------------------------------------------------------------------------- /charts/spark-operator-chart/templates/spark/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */}} 16 | 17 | {{/* 18 | Create the name of spark component 19 | */}} 20 | {{- define "spark-operator.spark.name" -}} 21 | {{- include "spark-operator.fullname" . }}-spark 22 | {{- end -}} 23 | 24 | {{/* 25 | Create the name of the service account to be used by spark applications 26 | */}} 27 | {{- define "spark-operator.spark.serviceAccountName" -}} 28 | {{- if .Values.spark.serviceAccount.create -}} 29 | {{- .Values.spark.serviceAccount.name | default (include "spark-operator.spark.name" .) -}} 30 | {{- else -}} 31 | {{- .Values.spark.serviceAccount.name | default "default" -}} 32 | {{- end -}} 33 | {{- end -}} 34 | 35 | {{/* 36 | Create the name of the role to be used by spark service account 37 | */}} 38 | {{- define "spark-operator.spark.roleName" -}} 39 | {{- include "spark-operator.spark.serviceAccountName" . }} 40 | {{- end -}} 41 | 42 | {{/* 43 | Create the name of the role binding to be used by spark service account 44 | */}} 45 | {{- define "spark-operator.spark.roleBindingName" -}} 46 | {{- include "spark-operator.spark.serviceAccountName" . }} 47 | {{- end -}} 48 | -------------------------------------------------------------------------------- /charts/spark-operator-chart/templates/spark/rbac.yaml: -------------------------------------------------------------------------------- 1 | {{/* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */}} 16 | 17 | {{- if .Values.spark.rbac.create -}} 18 | {{- range $jobNamespace := .Values.spark.jobNamespaces | default list }} 19 | {{- if ne $jobNamespace "" }} 20 | 21 | --- 22 | apiVersion: rbac.authorization.k8s.io/v1 23 | kind: Role 24 | metadata: 25 | name: {{ include "spark-operator.spark.roleName" $ }} 26 | namespace: {{ $jobNamespace }} 27 | labels: 28 | {{- include "spark-operator.labels" $ | nindent 4 }} 29 | {{- with $.Values.spark.rbac.annotations }} 30 | annotations: 31 | {{- toYaml . | nindent 4 }} 32 | {{- end }} 33 | rules: 34 | - apiGroups: 35 | - "" 36 | resources: 37 | - pods 38 | - configmaps 39 | - persistentvolumeclaims 40 | - services 41 | verbs: 42 | - get 43 | - list 44 | - watch 45 | - create 46 | - update 47 | - patch 48 | - delete 49 | - deletecollection 50 | 51 | --- 52 | apiVersion: rbac.authorization.k8s.io/v1 53 | kind: RoleBinding 54 | metadata: 55 | name: {{ include "spark-operator.spark.roleBindingName" $ }} 56 | namespace: {{ $jobNamespace }} 57 | labels: 58 | {{- include "spark-operator.labels" $ | nindent 4 }} 59 | {{- with $.Values.spark.rbac.annotations }} 60 | annotations: 61 | {{- toYaml . | nindent 4 }} 62 | {{- end }} 63 | subjects: 64 | - kind: ServiceAccount 65 | name: {{ include "spark-operator.spark.serviceAccountName" $ }} 66 | namespace: {{ $jobNamespace }} 67 | roleRef: 68 | apiGroup: rbac.authorization.k8s.io 69 | kind: Role 70 | name: {{ include "spark-operator.spark.roleName" $ }} 71 | {{- end }} 72 | {{- end }} 73 | {{- end }} 74 | -------------------------------------------------------------------------------- /charts/spark-operator-chart/templates/spark/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{/* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */}} 16 | 17 | {{- if .Values.spark.serviceAccount.create }} 18 | {{- range $jobNamespace := .Values.spark.jobNamespaces | default list }} 19 | {{- if ne $jobNamespace "" }} 20 | 21 | --- 22 | apiVersion: v1 23 | kind: ServiceAccount 24 | automountServiceAccountToken: {{ $.Values.spark.serviceAccount.automountServiceAccountToken }} 25 | metadata: 26 | name: {{ include "spark-operator.spark.serviceAccountName" $ }} 27 | namespace: {{ $jobNamespace }} 28 | labels: {{ include "spark-operator.labels" $ | nindent 4 }} 29 | {{- with $.Values.spark.serviceAccount.annotations }} 30 | annotations: {{ toYaml . | nindent 4 }} 31 | {{- end }} 32 | {{- end }} 33 | {{- end }} 34 | {{- end }} 35 | -------------------------------------------------------------------------------- /charts/spark-operator-chart/templates/webhook/poddisruptionbudget.yaml: -------------------------------------------------------------------------------- 1 | {{/* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */}} 16 | 17 | {{- if .Values.webhook.enable }} 18 | {{- if .Values.webhook.podDisruptionBudget.enable }} 19 | {{- if le (int .Values.webhook.replicas) 1 }} 20 | {{- fail "webhook.replicas must be greater than 1 to enable pod disruption budget for webhook" }} 21 | {{- end -}} 22 | apiVersion: policy/v1 23 | kind: PodDisruptionBudget 24 | metadata: 25 | name: {{ include "spark-operator.webhook.podDisruptionBudgetName" . }} 26 | labels: 27 | {{- include "spark-operator.webhook.labels" . | nindent 4 }} 28 | spec: 29 | selector: 30 | matchLabels: 31 | {{- include "spark-operator.webhook.selectorLabels" . | nindent 6 }} 32 | {{- with .Values.webhook.podDisruptionBudget.minAvailable }} 33 | minAvailable: {{ . }} 34 | {{- end }} 35 | {{- end }} 36 | {{- end }} 37 | -------------------------------------------------------------------------------- /charts/spark-operator-chart/templates/webhook/service.yaml: -------------------------------------------------------------------------------- 1 | {{/* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */}} 16 | 17 | {{- if .Values.webhook.enable }} 18 | apiVersion: v1 19 | kind: Service 20 | metadata: 21 | name: {{ include "spark-operator.webhook.serviceName" . }} 22 | labels: 23 | {{- include "spark-operator.webhook.labels" . | nindent 4 }} 24 | spec: 25 | selector: 26 | {{- include "spark-operator.webhook.selectorLabels" . | nindent 4 }} 27 | ports: 28 | - port: {{ .Values.webhook.port }} 29 | targetPort: {{ .Values.webhook.portName | quote }} 30 | name: {{ .Values.webhook.portName }} 31 | {{- end }} 32 | -------------------------------------------------------------------------------- /charts/spark-operator-chart/templates/webhook/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{/* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */}} 16 | 17 | {{- if .Values.webhook.enable }} 18 | {{- if .Values.webhook.serviceAccount.create -}} 19 | apiVersion: v1 20 | kind: ServiceAccount 21 | automountServiceAccountToken: {{ .Values.webhook.serviceAccount.automountServiceAccountToken }} 22 | metadata: 23 | name: {{ include "spark-operator.webhook.serviceAccountName" . }} 24 | namespace: {{ .Release.Namespace }} 25 | labels: 26 | {{- include "spark-operator.webhook.labels" . | nindent 4 }} 27 | {{- with .Values.webhook.serviceAccount.annotations }} 28 | annotations: 29 | {{- toYaml . | nindent 4 }} 30 | {{- end }} 31 | {{- end }} 32 | {{- end }} 33 | -------------------------------------------------------------------------------- /charts/spark-operator-chart/tests/controller/poddisruptionbudget_test.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2024 The Kubeflow authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | suite: Test controller pod disruption budget 18 | 19 | templates: 20 | - controller/poddisruptionbudget.yaml 21 | 22 | release: 23 | name: spark-operator 24 | namespace: spark-operator 25 | 26 | tests: 27 | - it: Should not render podDisruptionBudget if `controller.podDisruptionBudget.enable` is false 28 | set: 29 | controller: 30 | podDisruptionBudget: 31 | enable: false 32 | asserts: 33 | - hasDocuments: 34 | count: 0 35 | 36 | - it: Should fail if `controller.replicas` is less than 2 when `controller.podDisruptionBudget.enable` is true 37 | set: 38 | controller: 39 | replicas: 1 40 | podDisruptionBudget: 41 | enable: true 42 | asserts: 43 | - failedTemplate: 44 | errorMessage: "controller.replicas must be greater than 1 to enable pod disruption budget for controller" 45 | 46 | - it: Should render spark operator podDisruptionBudget if `controller.podDisruptionBudget.enable` is true 47 | set: 48 | controller: 49 | replicas: 2 50 | podDisruptionBudget: 51 | enable: true 52 | asserts: 53 | - containsDocument: 54 | apiVersion: policy/v1 55 | kind: PodDisruptionBudget 56 | name: spark-operator-controller-pdb 57 | 58 | - it: Should set minAvailable if `controller.podDisruptionBudget.minAvailable` is specified 59 | set: 60 | controller: 61 | replicas: 2 62 | podDisruptionBudget: 63 | enable: true 64 | minAvailable: 3 65 | asserts: 66 | - equal: 67 | path: spec.minAvailable 68 | value: 3 69 | -------------------------------------------------------------------------------- /charts/spark-operator-chart/tests/controller/service_test.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2024 The Kubeflow authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | suite: Test controller deployment 18 | 19 | templates: 20 | - controller/service.yaml 21 | 22 | release: 23 | name: spark-operator 24 | namespace: spark-operator 25 | 26 | tests: 27 | - it: Should create the pprof service correctly 28 | set: 29 | controller: 30 | pprof: 31 | enable: true 32 | port: 12345 33 | portName: pprof-test 34 | asserts: 35 | - containsDocument: 36 | apiVersion: v1 37 | kind: Service 38 | name: spark-operator-controller-svc 39 | - equal: 40 | path: spec.ports[0] 41 | value: 42 | port: 12345 43 | targetPort: pprof-test 44 | name: pprof-test -------------------------------------------------------------------------------- /charts/spark-operator-chart/tests/controller/serviceaccount_test.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2024 The Kubeflow authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | suite: Test controller service account 18 | 19 | templates: 20 | - controller/serviceaccount.yaml 21 | 22 | release: 23 | name: spark-operator 24 | namespace: spark-operator 25 | 26 | tests: 27 | - it: Should not create controller service account if `controller.serviceAccount.create` is false 28 | set: 29 | controller: 30 | serviceAccount: 31 | create: false 32 | asserts: 33 | - hasDocuments: 34 | count: 0 35 | 36 | - it: Should create controller service account by default 37 | asserts: 38 | - containsDocument: 39 | apiVersion: v1 40 | kind: ServiceAccount 41 | name: spark-operator-controller 42 | 43 | - it: Should use the specified service account name if `controller.serviceAccount.name` is set 44 | set: 45 | controller: 46 | serviceAccount: 47 | name: custom-service-account 48 | asserts: 49 | - containsDocument: 50 | apiVersion: v1 51 | kind: ServiceAccount 52 | name: custom-service-account 53 | 54 | - it: Should add extra annotations if `controller.serviceAccount.annotations` is set 55 | set: 56 | controller: 57 | serviceAccount: 58 | annotations: 59 | key1: value1 60 | key2: value2 61 | asserts: 62 | - equal: 63 | path: metadata.annotations.key1 64 | value: value1 65 | - equal: 66 | path: metadata.annotations.key2 67 | value: value2 68 | -------------------------------------------------------------------------------- /charts/spark-operator-chart/tests/webhook/poddisruptionbudget_test.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2024 The Kubeflow authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | suite: Test webhook pod disruption budget 18 | 19 | templates: 20 | - webhook/poddisruptionbudget.yaml 21 | 22 | release: 23 | name: spark-operator 24 | namespace: spark-operator 25 | 26 | tests: 27 | - it: Should not render podDisruptionBudget if `webhook.enable` is `false` 28 | set: 29 | webhook: 30 | enable: false 31 | asserts: 32 | - hasDocuments: 33 | count: 0 34 | 35 | - it: Should not render podDisruptionBudget if `webhook.podDisruptionBudget.enable` is false 36 | set: 37 | webhook: 38 | podDisruptionBudget: 39 | enable: false 40 | asserts: 41 | - hasDocuments: 42 | count: 0 43 | 44 | - it: Should fail if `webhook.replicas` is less than 2 when `webhook.podDisruptionBudget.enable` is true 45 | set: 46 | webhook: 47 | replicas: 1 48 | podDisruptionBudget: 49 | enable: true 50 | asserts: 51 | - failedTemplate: 52 | errorMessage: "webhook.replicas must be greater than 1 to enable pod disruption budget for webhook" 53 | 54 | - it: Should render spark operator podDisruptionBudget if `webhook.podDisruptionBudget.enable` is true 55 | set: 56 | webhook: 57 | replicas: 2 58 | podDisruptionBudget: 59 | enable: true 60 | asserts: 61 | - containsDocument: 62 | apiVersion: policy/v1 63 | kind: PodDisruptionBudget 64 | name: spark-operator-webhook-pdb 65 | 66 | - it: Should set minAvailable if `webhook.podDisruptionBudget.minAvailable` is specified 67 | set: 68 | webhook: 69 | replicas: 2 70 | podDisruptionBudget: 71 | enable: true 72 | minAvailable: 3 73 | asserts: 74 | - equal: 75 | path: spec.minAvailable 76 | value: 3 77 | -------------------------------------------------------------------------------- /charts/spark-operator-chart/tests/webhook/service_test.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2024 The Kubeflow authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | suite: Test webhook service 18 | 19 | templates: 20 | - webhook/service.yaml 21 | 22 | release: 23 | name: spark-operator 24 | namespace: spark-operator 25 | 26 | tests: 27 | - it: Should not create webhook service if `webhook.enable` is `false` 28 | set: 29 | webhook: 30 | enable: false 31 | asserts: 32 | - hasDocuments: 33 | count: 0 34 | 35 | - it: Should create the webhook service correctly 36 | set: 37 | webhook: 38 | portName: webhook 39 | asserts: 40 | - containsDocument: 41 | apiVersion: v1 42 | kind: Service 43 | name: spark-operator-webhook-svc 44 | - equal: 45 | path: spec.ports[0] 46 | value: 47 | port: 9443 48 | targetPort: webhook 49 | name: webhook 50 | -------------------------------------------------------------------------------- /cmd/operator/controller/root.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controller 18 | 19 | import ( 20 | "github.com/spf13/cobra" 21 | ) 22 | 23 | func NewCommand() *cobra.Command { 24 | command := &cobra.Command{ 25 | Use: "controller", 26 | Short: "Spark operator controller", 27 | RunE: func(cmd *cobra.Command, _ []string) error { 28 | return cmd.Help() 29 | }, 30 | } 31 | command.AddCommand(NewStartCommand()) 32 | return command 33 | } 34 | -------------------------------------------------------------------------------- /cmd/operator/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "fmt" 21 | "os" 22 | 23 | "github.com/spf13/cobra" 24 | 25 | "github.com/kubeflow/spark-operator/v2/cmd/operator/controller" 26 | "github.com/kubeflow/spark-operator/v2/cmd/operator/version" 27 | "github.com/kubeflow/spark-operator/v2/cmd/operator/webhook" 28 | ) 29 | 30 | func NewCommand() *cobra.Command { 31 | command := &cobra.Command{ 32 | Use: "spark-operator", 33 | Short: "Spark operator", 34 | RunE: func(cmd *cobra.Command, _ []string) error { 35 | return cmd.Help() 36 | }, 37 | } 38 | command.AddCommand(controller.NewCommand()) 39 | command.AddCommand(webhook.NewCommand()) 40 | command.AddCommand(version.NewCommand()) 41 | return command 42 | } 43 | 44 | func main() { 45 | if err := NewCommand().Execute(); err != nil { 46 | fmt.Fprintf(os.Stderr, "%v\n", err) 47 | os.Exit(1) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /cmd/operator/version/root.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package version 18 | 19 | import ( 20 | "github.com/spf13/cobra" 21 | 22 | sparkoperator "github.com/kubeflow/spark-operator/v2" 23 | ) 24 | 25 | var ( 26 | short bool 27 | ) 28 | 29 | func NewCommand() *cobra.Command { 30 | command := &cobra.Command{ 31 | Use: "version", 32 | Short: "Print version information", 33 | RunE: func(cmd *cobra.Command, args []string) error { 34 | sparkoperator.PrintVersion(short) 35 | return nil 36 | }, 37 | } 38 | command.Flags().BoolVar(&short, "short", false, "Print just the version string.") 39 | return command 40 | } 41 | -------------------------------------------------------------------------------- /cmd/operator/webhook/root.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package webhook 18 | 19 | import ( 20 | "github.com/spf13/cobra" 21 | ) 22 | 23 | func NewCommand() *cobra.Command { 24 | command := &cobra.Command{ 25 | Use: "webhook", 26 | Short: "Spark operator webhook", 27 | RunE: func(cmd *cobra.Command, _ []string) error { 28 | return cmd.Help() 29 | }, 30 | } 31 | command.AddCommand(NewStartCommand()) 32 | return command 33 | } 34 | -------------------------------------------------------------------------------- /config/certmanager/certificate.yaml: -------------------------------------------------------------------------------- 1 | # The following manifests contain a self-signed issuer CR and a certificate CR. 2 | # More document can be found at https://docs.cert-manager.io 3 | # WARNING: Targets CertManager v1.0. Check https://cert-manager.io/docs/installation/upgrading/ for breaking changes. 4 | apiVersion: cert-manager.io/v1 5 | kind: Issuer 6 | metadata: 7 | labels: 8 | app.kubernetes.io/name: spark-operator 9 | app.kubernetes.io/managed-by: kustomize 10 | name: selfsigned-issuer 11 | namespace: system 12 | spec: 13 | selfSigned: {} 14 | --- 15 | apiVersion: cert-manager.io/v1 16 | kind: Certificate 17 | metadata: 18 | labels: 19 | app.kubernetes.io/name: certificate 20 | app.kubernetes.io/instance: serving-cert 21 | app.kubernetes.io/component: certificate 22 | app.kubernetes.io/created-by: spark-operator 23 | app.kubernetes.io/part-of: spark-operator 24 | app.kubernetes.io/managed-by: kustomize 25 | name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml 26 | namespace: system 27 | spec: 28 | # SERVICE_NAME and SERVICE_NAMESPACE will be substituted by kustomize 29 | dnsNames: 30 | - SERVICE_NAME.SERVICE_NAMESPACE.svc 31 | - SERVICE_NAME.SERVICE_NAMESPACE.svc.cluster.local 32 | issuerRef: 33 | kind: Issuer 34 | name: selfsigned-issuer 35 | secretName: webhook-server-cert # this secret will not be prefixed, since it's not managed by kustomize 36 | -------------------------------------------------------------------------------- /config/certmanager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - certificate.yaml 3 | 4 | configurations: 5 | - kustomizeconfig.yaml 6 | -------------------------------------------------------------------------------- /config/certmanager/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This configuration is for teaching kustomize how to update name ref substitution 2 | nameReference: 3 | - kind: Issuer 4 | group: cert-manager.io 5 | fieldSpecs: 6 | - kind: Certificate 7 | group: cert-manager.io 8 | path: spec/issuerRef/name 9 | -------------------------------------------------------------------------------- /config/crd/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # This kustomization.yaml is not intended to be run by itself, 2 | # since it depends on service name and namespace that are out of this kustomize package. 3 | # It should be run by config/default 4 | resources: 5 | - bases/sparkoperator.k8s.io_scheduledsparkapplications.yaml 6 | - bases/sparkoperator.k8s.io_sparkapplications.yaml 7 | # +kubebuilder:scaffold:crdkustomizeresource 8 | 9 | patches: 10 | # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. 11 | # patches here are for enabling the conversion webhook for each CRD 12 | - path: patches/webhook_in_sparkapplications.yaml 13 | - path: patches/webhook_in_sparkapplications.yaml 14 | # +kubebuilder:scaffold:crdkustomizewebhookpatch 15 | 16 | # [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix. 17 | # patches here are for enabling the CA injection for each CRD 18 | #- path: patches/cainjection_in_scheduledsparkapplications.yaml 19 | #- path: patches/cainjection_in_sparkapplications.yaml 20 | # +kubebuilder:scaffold:crdkustomizecainjectionpatch 21 | 22 | # [WEBHOOK] To enable webhook, uncomment the following section 23 | # the following config is for teaching kustomize how to do kustomization for CRDs. 24 | 25 | configurations: 26 | - kustomizeconfig.yaml 27 | -------------------------------------------------------------------------------- /config/crd/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This file is for teaching kustomize how to substitute name and namespace reference in CRD 2 | nameReference: 3 | - kind: Service 4 | version: v1 5 | fieldSpecs: 6 | - kind: CustomResourceDefinition 7 | version: v1 8 | group: apiextensions.k8s.io 9 | path: spec/conversion/webhook/clientConfig/service/name 10 | 11 | namespace: 12 | - kind: CustomResourceDefinition 13 | version: v1 14 | group: apiextensions.k8s.io 15 | path: spec/conversion/webhook/clientConfig/service/namespace 16 | create: false 17 | 18 | varReference: 19 | - path: metadata/annotations 20 | -------------------------------------------------------------------------------- /config/crd/patches/cainjection_in_sparkapplications.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME 7 | name: sparkapplications.sparkoperator.k8s.io 8 | -------------------------------------------------------------------------------- /config/crd/patches/webhook_in_sparkapplications.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables a conversion webhook for the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: sparkapplications.sparkoperator.k8s.io 6 | spec: 7 | conversion: 8 | strategy: Webhook 9 | webhook: 10 | clientConfig: 11 | service: 12 | namespace: system 13 | name: webhook-service 14 | path: /convert 15 | conversionReviewVersions: 16 | - v1 17 | -------------------------------------------------------------------------------- /config/default/manager_webhook_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: manager 11 | ports: 12 | - containerPort: 9443 13 | name: webhook-server 14 | protocol: TCP 15 | volumeMounts: 16 | - mountPath: /tmp/k8s-webhook-server/serving-certs 17 | name: cert 18 | readOnly: true 19 | volumes: 20 | - name: cert 21 | secret: 22 | defaultMode: 420 23 | secretName: webhook-server-cert 24 | -------------------------------------------------------------------------------- /config/default/webhookcainjection_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch add annotation to admission webhook config and 2 | # CERTIFICATE_NAMESPACE and CERTIFICATE_NAME will be substituted by kustomize 3 | apiVersion: admissionregistration.k8s.io/v1 4 | kind: MutatingWebhookConfiguration 5 | metadata: 6 | labels: 7 | app.kubernetes.io/name: spark-operator 8 | app.kubernetes.io/managed-by: kustomize 9 | name: mutating-webhook-configuration 10 | annotations: 11 | cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME 12 | --- 13 | apiVersion: admissionregistration.k8s.io/v1 14 | kind: ValidatingWebhookConfiguration 15 | metadata: 16 | labels: 17 | app.kubernetes.io/name: validatingwebhookconfiguration 18 | app.kubernetes.io/instance: validating-webhook-configuration 19 | app.kubernetes.io/component: webhook 20 | app.kubernetes.io/created-by: spark-operator 21 | app.kubernetes.io/part-of: spark-operator 22 | app.kubernetes.io/managed-by: kustomize 23 | name: validating-webhook-configuration 24 | annotations: 25 | cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME 26 | -------------------------------------------------------------------------------- /config/rbac/role.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: spark-operator-controller 6 | rules: 7 | - resources: 8 | - configmaps 9 | verbs: 10 | - create 11 | - delete 12 | - get 13 | - list 14 | - patch 15 | - update 16 | - resources: 17 | - events 18 | verbs: 19 | - create 20 | - patch 21 | - update 22 | - resources: 23 | - nodes 24 | verbs: 25 | - get 26 | - resources: 27 | - pods 28 | verbs: 29 | - create 30 | - delete 31 | - deletecollection 32 | - get 33 | - list 34 | - patch 35 | - update 36 | - watch 37 | - resources: 38 | - resourcequotas 39 | verbs: 40 | - get 41 | - list 42 | - watch 43 | - resources: 44 | - services 45 | verbs: 46 | - create 47 | - delete 48 | - get 49 | - list 50 | - update 51 | - watch 52 | - apiGroups: 53 | - apiextensions.k8s.io 54 | resources: 55 | - customresourcedefinitions 56 | verbs: 57 | - get 58 | - apiGroups: 59 | - extensions 60 | - networking.k8s.io 61 | resources: 62 | - ingresses 63 | verbs: 64 | - create 65 | - delete 66 | - get 67 | - list 68 | - update 69 | - watch 70 | - apiGroups: 71 | - sparkoperator.k8s.io 72 | resources: 73 | - scheduledsparkapplications 74 | - sparkapplications 75 | - sparkconnects 76 | verbs: 77 | - create 78 | - delete 79 | - get 80 | - list 81 | - patch 82 | - update 83 | - watch 84 | - apiGroups: 85 | - sparkoperator.k8s.io 86 | resources: 87 | - scheduledsparkapplications/finalizers 88 | - sparkapplications/finalizers 89 | verbs: 90 | - update 91 | - apiGroups: 92 | - sparkoperator.k8s.io 93 | resources: 94 | - scheduledsparkapplications/status 95 | - sparkapplications/status 96 | - sparkconnects/status 97 | verbs: 98 | - get 99 | - patch 100 | - update 101 | -------------------------------------------------------------------------------- /config/rbac/scheduledsparkapplication_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit scheduledsparkapplications. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: spark-operator 7 | app.kubernetes.io/managed-by: kustomize 8 | name: scheduledsparkapplication-editor-role 9 | rules: 10 | - apiGroups: 11 | - sparkoperator.k8s.io 12 | resources: 13 | - scheduledsparkapplications 14 | verbs: 15 | - create 16 | - delete 17 | - get 18 | - list 19 | - patch 20 | - update 21 | - watch 22 | - apiGroups: 23 | - sparkoperator.k8s.io 24 | resources: 25 | - scheduledsparkapplications/status 26 | verbs: 27 | - get 28 | -------------------------------------------------------------------------------- /config/rbac/scheduledsparkapplication_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view scheduledsparkapplications. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: spark-operator 7 | app.kubernetes.io/managed-by: kustomize 8 | name: scheduledsparkapplication-viewer-role 9 | rules: 10 | - apiGroups: 11 | - sparkoperator.k8s.io 12 | resources: 13 | - scheduledsparkapplications 14 | verbs: 15 | - get 16 | - list 17 | - watch 18 | - apiGroups: 19 | - sparkoperator.k8s.io 20 | resources: 21 | - scheduledsparkapplications/status 22 | verbs: 23 | - get 24 | -------------------------------------------------------------------------------- /config/rbac/spark-application-rbac.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2024 The Kubeflow authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | apiVersion: v1 17 | kind: ServiceAccount 18 | metadata: 19 | name: spark-operator-spark 20 | namespace: default 21 | --- 22 | apiVersion: rbac.authorization.k8s.io/v1 23 | kind: Role 24 | metadata: 25 | namespace: default 26 | name: spark-role 27 | rules: 28 | - apiGroups: 29 | - "" 30 | resources: 31 | - pods 32 | - configmaps 33 | - persistentvolumeclaims 34 | - services 35 | verbs: 36 | - get 37 | - list 38 | - watch 39 | - create 40 | - update 41 | - patch 42 | - delete 43 | - deletecollection 44 | --- 45 | apiVersion: rbac.authorization.k8s.io/v1 46 | kind: RoleBinding 47 | metadata: 48 | name: spark-role-binding 49 | namespace: default 50 | subjects: 51 | - kind: ServiceAccount 52 | name: spark-operator-spark 53 | namespace: default 54 | roleRef: 55 | kind: Role 56 | name: spark-role 57 | apiGroup: rbac.authorization.k8s.io 58 | -------------------------------------------------------------------------------- /config/rbac/sparkapplication_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit sparkapplications. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: spark-operator 7 | app.kubernetes.io/managed-by: kustomize 8 | name: sparkapplication-editor-role 9 | rules: 10 | - apiGroups: 11 | - sparkoperator.k8s.io 12 | resources: 13 | - sparkapplications 14 | verbs: 15 | - create 16 | - delete 17 | - get 18 | - list 19 | - patch 20 | - update 21 | - watch 22 | - apiGroups: 23 | - sparkoperator.k8s.io 24 | resources: 25 | - sparkapplications/status 26 | verbs: 27 | - get 28 | -------------------------------------------------------------------------------- /config/rbac/sparkapplication_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view sparkapplications. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: spark-operator 7 | app.kubernetes.io/managed-by: kustomize 8 | name: sparkapplication-viewer-role 9 | rules: 10 | - apiGroups: 11 | - sparkoperator.k8s.io 12 | resources: 13 | - sparkapplications 14 | verbs: 15 | - get 16 | - list 17 | - watch 18 | - apiGroups: 19 | - sparkoperator.k8s.io 20 | resources: 21 | - sparkapplications/status 22 | verbs: 23 | - get 24 | -------------------------------------------------------------------------------- /config/samples/kustomization.yaml: -------------------------------------------------------------------------------- 1 | ## Append samples of your project ## 2 | resources: 3 | - v1beta2_sparkapplication.yaml 4 | - v1beta2_scheduledsparkapplication.yaml 5 | # +kubebuilder:scaffold:manifestskustomizesamples 6 | -------------------------------------------------------------------------------- /config/samples/v1beta2_scheduledsparkapplication.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: sparkoperator.k8s.io/v1beta2 2 | kind: ScheduledSparkApplication 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: spark-operator 6 | app.kubernetes.io/managed-by: kustomize 7 | name: scheduledsparkapplication-sample 8 | spec: 9 | schedule: "@every 3m" 10 | concurrencyPolicy: Allow 11 | template: 12 | type: Scala 13 | mode: cluster 14 | image: docker.io/library/spark:4.0.0 15 | imagePullPolicy: IfNotPresent 16 | mainClass: org.apache.spark.examples.SparkPi 17 | mainApplicationFile: local:///opt/spark/examples/jars/spark-examples.jar 18 | sparkVersion: 4.0.0 19 | restartPolicy: 20 | type: Never 21 | driver: 22 | labels: 23 | version: 4.0.0 24 | cores: 1 25 | coreLimit: 1200m 26 | memory: 512m 27 | serviceAccount: spark-operator-spark 28 | executor: 29 | labels: 30 | version: 4.0.0 31 | instances: 1 32 | cores: 1 33 | coreLimit: 1200m 34 | memory: 512m 35 | -------------------------------------------------------------------------------- /config/samples/v1beta2_sparkapplication.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: sparkoperator.k8s.io/v1beta2 2 | kind: SparkApplication 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: spark-operator 6 | app.kubernetes.io/managed-by: kustomize 7 | name: sparkapplication-sample 8 | spec: 9 | type: Scala 10 | mode: cluster 11 | image: docker.io/library/spark:4.0.0 12 | imagePullPolicy: IfNotPresent 13 | mainClass: org.apache.spark.examples.SparkPi 14 | mainApplicationFile: local:///opt/spark/examples/jars/spark-examples.jar 15 | sparkVersion: 4.0.0 16 | driver: 17 | labels: 18 | version: 4.0.0 19 | serviceAccount: spark-operator-spark 20 | executor: 21 | labels: 22 | version: 4.0.0 23 | instances: 1 24 | -------------------------------------------------------------------------------- /config/webhook/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manifests.yaml 3 | - service.yaml 4 | 5 | configurations: 6 | - kustomizeconfig.yaml 7 | -------------------------------------------------------------------------------- /config/webhook/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # the following config is for teaching kustomize where to look at when substituting nameReference. 2 | # It requires kustomize v2.1.0 or newer to work properly. 3 | nameReference: 4 | - kind: Service 5 | version: v1 6 | fieldSpecs: 7 | - kind: MutatingWebhookConfiguration 8 | group: admissionregistration.k8s.io 9 | path: webhooks/clientConfig/service/name 10 | - kind: ValidatingWebhookConfiguration 11 | group: admissionregistration.k8s.io 12 | path: webhooks/clientConfig/service/name 13 | 14 | namespace: 15 | - kind: MutatingWebhookConfiguration 16 | group: admissionregistration.k8s.io 17 | path: webhooks/clientConfig/service/namespace 18 | create: true 19 | - kind: ValidatingWebhookConfiguration 20 | group: admissionregistration.k8s.io 21 | path: webhooks/clientConfig/service/namespace 22 | create: true 23 | -------------------------------------------------------------------------------- /config/webhook/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: spark-operator 6 | app.kubernetes.io/managed-by: kustomize 7 | name: webhook-service 8 | namespace: system 9 | spec: 10 | ports: 11 | - port: 443 12 | protocol: TCP 13 | targetPort: 9443 14 | selector: 15 | control-plane: controller-manager 16 | -------------------------------------------------------------------------------- /entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # echo commands to the terminal output 4 | set -ex 5 | 6 | # Check whether there is a passwd entry for the container UID 7 | myuid="$(id -u)" 8 | # If there is no passwd entry for the container UID, attempt to fake one 9 | # You can also refer to the https://github.com/docker-library/official-images/pull/13089#issuecomment-1534706523 10 | # It's to resolve OpenShift random UID case. 11 | # See also: https://github.com/docker-library/postgres/pull/448 12 | if ! getent passwd "$myuid" &> /dev/null; then 13 | for wrapper in {/usr,}/lib{/*,}/libnss_wrapper.so; do 14 | if [ -s "$wrapper" ]; then 15 | NSS_WRAPPER_PASSWD="$(mktemp)" 16 | NSS_WRAPPER_GROUP="$(mktemp)" 17 | export LD_PRELOAD="$wrapper" NSS_WRAPPER_PASSWD NSS_WRAPPER_GROUP 18 | mygid="$(id -g)" 19 | printf 'spark:x:%s:%s:${SPARK_USER_NAME:-anonymous uid}:%s:/bin/false\n' "$myuid" "$mygid" "$SPARK_HOME" > "$NSS_WRAPPER_PASSWD" 20 | printf 'spark:x:%s:\n' "$mygid" > "$NSS_WRAPPER_GROUP" 21 | break 22 | fi 23 | done 24 | fi 25 | 26 | exec /usr/bin/tini -s -- /usr/bin/spark-operator "$@" 27 | -------------------------------------------------------------------------------- /examples/spark-pi-configmap.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | apiVersion: sparkoperator.k8s.io/v1beta2 17 | kind: SparkApplication 18 | metadata: 19 | name: spark-pi-configmap 20 | namespace: default 21 | spec: 22 | type: Scala 23 | mode: cluster 24 | image: docker.io/library/spark:4.0.0 25 | imagePullPolicy: IfNotPresent 26 | mainClass: org.apache.spark.examples.SparkPi 27 | mainApplicationFile: local:///opt/spark/examples/jars/spark-examples.jar 28 | sparkVersion: 4.0.0 29 | restartPolicy: 30 | type: Never 31 | volumes: 32 | - name: config-vol 33 | configMap: 34 | name: test-configmap 35 | driver: 36 | cores: 1 37 | memory: 512m 38 | volumeMounts: 39 | - name: config-vol 40 | mountPath: /opt/spark/config 41 | serviceAccount: spark-operator-spark 42 | securityContext: 43 | capabilities: 44 | drop: 45 | - ALL 46 | runAsGroup: 185 47 | runAsUser: 185 48 | runAsNonRoot: true 49 | allowPrivilegeEscalation: false 50 | seccompProfile: 51 | type: RuntimeDefault 52 | executor: 53 | instances: 1 54 | cores: 1 55 | memory: 512m 56 | volumeMounts: 57 | - name: config-vol 58 | mountPath: /opt/spark/config 59 | securityContext: 60 | capabilities: 61 | drop: 62 | - ALL 63 | runAsGroup: 185 64 | runAsUser: 185 65 | runAsNonRoot: true 66 | allowPrivilegeEscalation: false 67 | seccompProfile: 68 | type: RuntimeDefault 69 | -------------------------------------------------------------------------------- /examples/spark-pi-custom-resource.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | apiVersion: sparkoperator.k8s.io/v1beta2 17 | kind: SparkApplication 18 | metadata: 19 | name: spark-pi-custom-resource 20 | namespace: default 21 | spec: 22 | type: Scala 23 | mode: cluster 24 | image: docker.io/library/spark:4.0.0 25 | imagePullPolicy: IfNotPresent 26 | mainClass: org.apache.spark.examples.SparkPi 27 | mainApplicationFile: local:///opt/spark/examples/jars/spark-examples.jar 28 | sparkVersion: 4.0.0 29 | restartPolicy: 30 | type: Never 31 | driver: 32 | coreRequest: "0.5" 33 | coreLimit: 800m 34 | memory: 512m 35 | serviceAccount: spark-operator-spark 36 | securityContext: 37 | capabilities: 38 | drop: 39 | - ALL 40 | runAsGroup: 185 41 | runAsUser: 185 42 | runAsNonRoot: true 43 | allowPrivilegeEscalation: false 44 | seccompProfile: 45 | type: RuntimeDefault 46 | executor: 47 | instances: 1 48 | coreRequest: "1200m" 49 | coreLimit: 1500m 50 | memory: 512m 51 | securityContext: 52 | capabilities: 53 | drop: 54 | - ALL 55 | runAsGroup: 185 56 | runAsUser: 185 57 | runAsNonRoot: true 58 | allowPrivilegeEscalation: false 59 | seccompProfile: 60 | type: RuntimeDefault 61 | -------------------------------------------------------------------------------- /examples/spark-pi-dynamic-allocation.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2024 The Kubeflow authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | apiVersion: sparkoperator.k8s.io/v1beta2 17 | kind: SparkApplication 18 | metadata: 19 | name: spark-pi-dynamic-allocation 20 | namespace: default 21 | spec: 22 | type: Scala 23 | mode: cluster 24 | image: docker.io/library/spark:4.0.0 25 | imagePullPolicy: IfNotPresent 26 | mainClass: org.apache.spark.examples.SparkPi 27 | mainApplicationFile: local:///opt/spark/examples/jars/spark-examples.jar 28 | sparkVersion: 4.0.0 29 | driver: 30 | cores: 1 31 | memory: 512m 32 | serviceAccount: spark-operator-spark 33 | securityContext: 34 | capabilities: 35 | drop: 36 | - ALL 37 | runAsGroup: 185 38 | runAsUser: 185 39 | runAsNonRoot: true 40 | allowPrivilegeEscalation: false 41 | seccompProfile: 42 | type: RuntimeDefault 43 | executor: 44 | instances: 1 45 | cores: 1 46 | memory: 512m 47 | securityContext: 48 | capabilities: 49 | drop: 50 | - ALL 51 | runAsGroup: 185 52 | runAsUser: 185 53 | runAsNonRoot: true 54 | allowPrivilegeEscalation: false 55 | seccompProfile: 56 | type: RuntimeDefault 57 | dynamicAllocation: 58 | enabled: true 59 | initialExecutors: 2 60 | maxExecutors: 5 61 | minExecutors: 1 62 | -------------------------------------------------------------------------------- /examples/spark-pi-kube-scheduler.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2024 The Kubeflow authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | apiVersion: sparkoperator.k8s.io/v1beta2 17 | kind: SparkApplication 18 | metadata: 19 | name: spark-pi-kube-scheduler 20 | namespace: default 21 | spec: 22 | type: Scala 23 | mode: cluster 24 | image: docker.io/library/spark:4.0.0 25 | imagePullPolicy: IfNotPresent 26 | mainClass: org.apache.spark.examples.SparkPi 27 | mainApplicationFile: local:///opt/spark/examples/jars/spark-examples.jar 28 | sparkVersion: 4.0.0 29 | driver: 30 | cores: 1 31 | memory: 512m 32 | serviceAccount: spark-operator-spark 33 | securityContext: 34 | capabilities: 35 | drop: 36 | - ALL 37 | runAsGroup: 185 38 | runAsUser: 185 39 | runAsNonRoot: true 40 | allowPrivilegeEscalation: false 41 | seccompProfile: 42 | type: RuntimeDefault 43 | executor: 44 | instances: 2 45 | cores: 1 46 | memory: 512m 47 | securityContext: 48 | capabilities: 49 | drop: 50 | - ALL 51 | runAsGroup: 185 52 | runAsUser: 185 53 | runAsNonRoot: true 54 | allowPrivilegeEscalation: false 55 | seccompProfile: 56 | type: RuntimeDefault 57 | batchScheduler: kube-scheduler 58 | -------------------------------------------------------------------------------- /examples/spark-pi-prometheus-servlet.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2024 The Kubeflow authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | apiVersion: sparkoperator.k8s.io/v1beta2 17 | kind: SparkApplication 18 | metadata: 19 | name: spark-pi-python 20 | spec: 21 | type: Python 22 | pythonVersion: "3" 23 | mode: cluster 24 | image: docker.io/library/spark:4.0.0 25 | imagePullPolicy: IfNotPresent 26 | mainApplicationFile: local:///opt/spark/examples/src/main/python/pi.py 27 | sparkVersion: 4.0.0 28 | sparkConf: 29 | # Expose Spark metrics for Prometheus 30 | "spark.kubernetes.driver.annotation.prometheus.io/scrape": "true" 31 | "spark.kubernetes.driver.annotation.prometheus.io/path": "/metrics/executors/prometheus/" 32 | "spark.kubernetes.driver.annotation.prometheus.io/port": "4040" 33 | "spark.kubernetes.driver.service.annotation.prometheus.io/scrape": "true" 34 | "spark.kubernetes.driver.service.annotation.prometheus.io/path": "/metrics/driver/prometheus/" 35 | "spark.kubernetes.driver.service.annotation.prometheus.io/port": "4040" 36 | "spark.ui.prometheus.enabled": "true" 37 | "spark.executor.processTreeMetrics.enabled": "true" 38 | "spark.metrics.conf.*.sink.prometheusServlet.class": "org.apache.spark.metrics.sink.PrometheusServlet" 39 | "spark.metrics.conf.driver.sink.prometheusServlet.path": "/metrics/driver/prometheus/" 40 | "spark.metrics.conf.executor.sink.prometheusServlet.path": "/metrics/executors/prometheus/" 41 | driver: 42 | cores: 1 43 | memory: 512m 44 | serviceAccount: spark-operator-spark 45 | securityContext: 46 | capabilities: 47 | drop: 48 | - ALL 49 | runAsGroup: 185 50 | runAsUser: 185 51 | runAsNonRoot: true 52 | allowPrivilegeEscalation: false 53 | seccompProfile: 54 | type: RuntimeDefault 55 | executor: 56 | instances: 1 57 | cores: 1 58 | memory: 512m 59 | securityContext: 60 | capabilities: 61 | drop: 62 | - ALL 63 | runAsGroup: 185 64 | runAsUser: 185 65 | runAsNonRoot: true 66 | allowPrivilegeEscalation: false 67 | seccompProfile: 68 | type: RuntimeDefault 69 | -------------------------------------------------------------------------------- /examples/spark-pi-prometheus.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2018 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | apiVersion: sparkoperator.k8s.io/v1beta2 18 | kind: SparkApplication 19 | metadata: 20 | name: spark-pi 21 | namespace: default 22 | spec: 23 | type: Scala 24 | mode: cluster 25 | image: {IMAGE_REGISTRY}/{IMAGE_REPOSITORY}/docker.io/library/spark:4.0.0-gcs-prometheus 26 | imagePullPolicy: Always 27 | mainClass: org.apache.spark.examples.SparkPi 28 | mainApplicationFile: local:///opt/spark/examples/jars/spark-examples.jar 29 | arguments: 30 | - "100000" 31 | sparkVersion: 4.0.0 32 | restartPolicy: 33 | type: Never 34 | driver: 35 | cores: 1 36 | memory: 512m 37 | labels: 38 | version: 4.0.0 39 | serviceAccount: spark-operator-spark 40 | securityContext: 41 | capabilities: 42 | drop: 43 | - ALL 44 | runAsGroup: 185 45 | runAsUser: 185 46 | runAsNonRoot: true 47 | allowPrivilegeEscalation: false 48 | seccompProfile: 49 | type: RuntimeDefault 50 | executor: 51 | cores: 1 52 | instances: 1 53 | memory: 512m 54 | securityContext: 55 | capabilities: 56 | drop: 57 | - ALL 58 | runAsGroup: 185 59 | runAsUser: 185 60 | runAsNonRoot: true 61 | allowPrivilegeEscalation: false 62 | seccompProfile: 63 | type: RuntimeDefault 64 | labels: 65 | version: 4.0.0 66 | monitoring: 67 | exposeDriverMetrics: true 68 | exposeExecutorMetrics: true 69 | prometheus: 70 | jmxExporterJar: /prometheus/jmx_prometheus_javaagent-0.11.0.jar 71 | port: 8090 72 | -------------------------------------------------------------------------------- /examples/spark-pi-python.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2018 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | apiVersion: sparkoperator.k8s.io/v1beta2 17 | kind: SparkApplication 18 | metadata: 19 | name: spark-pi-python 20 | namespace: default 21 | spec: 22 | type: Python 23 | pythonVersion: "3" 24 | mode: cluster 25 | image: docker.io/library/spark:4.0.0 26 | imagePullPolicy: IfNotPresent 27 | mainApplicationFile: local:///opt/spark/examples/src/main/python/pi.py 28 | sparkVersion: 4.0.0 29 | driver: 30 | cores: 1 31 | memory: 512m 32 | serviceAccount: spark-operator-spark 33 | securityContext: 34 | capabilities: 35 | drop: 36 | - ALL 37 | runAsGroup: 185 38 | runAsUser: 185 39 | runAsNonRoot: true 40 | allowPrivilegeEscalation: false 41 | seccompProfile: 42 | type: RuntimeDefault 43 | executor: 44 | instances: 1 45 | cores: 1 46 | memory: 512m 47 | securityContext: 48 | capabilities: 49 | drop: 50 | - ALL 51 | runAsGroup: 185 52 | runAsUser: 185 53 | runAsNonRoot: true 54 | allowPrivilegeEscalation: false 55 | seccompProfile: 56 | type: RuntimeDefault 57 | -------------------------------------------------------------------------------- /examples/spark-pi-scheduled.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2018 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | apiVersion: sparkoperator.k8s.io/v1beta2 18 | kind: ScheduledSparkApplication 19 | metadata: 20 | name: spark-pi-scheduled 21 | namespace: default 22 | spec: 23 | schedule: "@every 3m" 24 | concurrencyPolicy: Allow 25 | template: 26 | type: Scala 27 | mode: cluster 28 | image: docker.io/library/spark:4.0.0 29 | imagePullPolicy: IfNotPresent 30 | mainClass: org.apache.spark.examples.SparkPi 31 | mainApplicationFile: local:///opt/spark/examples/jars/spark-examples.jar 32 | sparkVersion: 4.0.0 33 | restartPolicy: 34 | type: Never 35 | driver: 36 | cores: 1 37 | memory: 512m 38 | serviceAccount: spark-operator-spark 39 | securityContext: 40 | capabilities: 41 | drop: 42 | - ALL 43 | runAsGroup: 185 44 | runAsUser: 185 45 | runAsNonRoot: true 46 | allowPrivilegeEscalation: false 47 | seccompProfile: 48 | type: RuntimeDefault 49 | executor: 50 | instances: 1 51 | cores: 1 52 | memory: 512m 53 | securityContext: 54 | capabilities: 55 | drop: 56 | - ALL 57 | runAsGroup: 185 58 | runAsUser: 185 59 | runAsNonRoot: true 60 | allowPrivilegeEscalation: false 61 | seccompProfile: 62 | type: RuntimeDefault 63 | -------------------------------------------------------------------------------- /examples/spark-pi-ttl.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2024 The Kubeflow authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | apiVersion: sparkoperator.k8s.io/v1beta2 17 | kind: SparkApplication 18 | metadata: 19 | name: spark-pi-ttl 20 | namespace: default 21 | spec: 22 | type: Scala 23 | mode: cluster 24 | image: docker.io/library/spark:4.0.0 25 | imagePullPolicy: IfNotPresent 26 | mainClass: org.apache.spark.examples.SparkPi 27 | mainApplicationFile: local:///opt/spark/examples/jars/spark-examples.jar 28 | sparkVersion: 4.0.0 29 | timeToLiveSeconds: 30 30 | driver: 31 | cores: 1 32 | memory: 512m 33 | serviceAccount: spark-operator-spark 34 | securityContext: 35 | capabilities: 36 | drop: 37 | - ALL 38 | runAsGroup: 185 39 | runAsUser: 185 40 | runAsNonRoot: true 41 | allowPrivilegeEscalation: false 42 | seccompProfile: 43 | type: RuntimeDefault 44 | executor: 45 | instances: 1 46 | cores: 1 47 | memory: 512m 48 | securityContext: 49 | capabilities: 50 | drop: 51 | - ALL 52 | runAsGroup: 185 53 | runAsUser: 185 54 | runAsNonRoot: true 55 | allowPrivilegeEscalation: false 56 | seccompProfile: 57 | type: RuntimeDefault 58 | -------------------------------------------------------------------------------- /examples/spark-pi-volcano.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2024 The Kubeflow authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | apiVersion: sparkoperator.k8s.io/v1beta2 17 | kind: SparkApplication 18 | metadata: 19 | name: spark-pi-volcano 20 | namespace: default 21 | spec: 22 | type: Scala 23 | mode: cluster 24 | image: docker.io/library/spark:4.0.0 25 | imagePullPolicy: IfNotPresent 26 | mainClass: org.apache.spark.examples.SparkPi 27 | mainApplicationFile: local:///opt/spark/examples/jars/spark-examples.jar 28 | sparkVersion: 4.0.0 29 | driver: 30 | cores: 1 31 | memory: 512m 32 | serviceAccount: spark-operator-spark 33 | securityContext: 34 | capabilities: 35 | drop: 36 | - ALL 37 | runAsGroup: 185 38 | runAsUser: 185 39 | runAsNonRoot: true 40 | allowPrivilegeEscalation: false 41 | seccompProfile: 42 | type: RuntimeDefault 43 | executor: 44 | instances: 2 45 | cores: 1 46 | memory: 512m 47 | securityContext: 48 | capabilities: 49 | drop: 50 | - ALL 51 | runAsGroup: 185 52 | runAsUser: 185 53 | runAsNonRoot: true 54 | allowPrivilegeEscalation: false 55 | seccompProfile: 56 | type: RuntimeDefault 57 | batchScheduler: volcano 58 | -------------------------------------------------------------------------------- /examples/spark-pi-yunikorn.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2024 The Kubeflow authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | apiVersion: sparkoperator.k8s.io/v1beta2 17 | kind: SparkApplication 18 | metadata: 19 | name: spark-pi-yunikorn 20 | namespace: default 21 | spec: 22 | type: Scala 23 | mode: cluster 24 | image: docker.io/library/spark:4.0.0 25 | imagePullPolicy: IfNotPresent 26 | mainClass: org.apache.spark.examples.SparkPi 27 | mainApplicationFile: local:///opt/spark/examples/jars/spark-examples.jar 28 | sparkVersion: 4.0.0 29 | driver: 30 | cores: 1 31 | memory: 512m 32 | serviceAccount: spark-operator-spark 33 | securityContext: 34 | capabilities: 35 | drop: 36 | - ALL 37 | runAsGroup: 185 38 | runAsUser: 185 39 | runAsNonRoot: true 40 | allowPrivilegeEscalation: false 41 | seccompProfile: 42 | type: RuntimeDefault 43 | executor: 44 | instances: 2 45 | cores: 1 46 | memory: 512m 47 | securityContext: 48 | capabilities: 49 | drop: 50 | - ALL 51 | runAsGroup: 185 52 | runAsUser: 185 53 | runAsNonRoot: true 54 | allowPrivilegeEscalation: false 55 | seccompProfile: 56 | type: RuntimeDefault 57 | batchScheduler: yunikorn 58 | batchSchedulerOptions: 59 | queue: root.default 60 | -------------------------------------------------------------------------------- /examples/spark-pi.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | apiVersion: sparkoperator.k8s.io/v1beta2 17 | kind: SparkApplication 18 | metadata: 19 | name: spark-pi 20 | namespace: default 21 | spec: 22 | type: Scala 23 | mode: cluster 24 | image: docker.io/library/spark:4.0.0 25 | imagePullPolicy: IfNotPresent 26 | mainClass: org.apache.spark.examples.SparkPi 27 | mainApplicationFile: local:///opt/spark/examples/jars/spark-examples.jar 28 | arguments: 29 | - "5000" 30 | sparkVersion: 4.0.0 31 | driver: 32 | labels: 33 | version: 4.0.0 34 | cores: 1 35 | memory: 512m 36 | serviceAccount: spark-operator-spark 37 | securityContext: 38 | capabilities: 39 | drop: 40 | - ALL 41 | runAsGroup: 185 42 | runAsUser: 185 43 | runAsNonRoot: true 44 | allowPrivilegeEscalation: false 45 | seccompProfile: 46 | type: RuntimeDefault 47 | executor: 48 | labels: 49 | version: 4.0.0 50 | instances: 1 51 | cores: 1 52 | memory: 512m 53 | securityContext: 54 | capabilities: 55 | drop: 56 | - ALL 57 | runAsGroup: 185 58 | runAsUser: 185 59 | runAsNonRoot: true 60 | allowPrivilegeEscalation: false 61 | seccompProfile: 62 | type: RuntimeDefault 63 | -------------------------------------------------------------------------------- /examples/sparkconnect/spark-connect.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2025 The Kubeflow authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | apiVersion: sparkoperator.k8s.io/v1alpha1 17 | kind: SparkConnect 18 | metadata: 19 | name: spark-connect 20 | namespace: default 21 | spec: 22 | sparkVersion: 4.0.0 23 | server: 24 | template: 25 | metadata: 26 | labels: 27 | key1: value1 28 | key2: value2 29 | annotations: 30 | key3: value3 31 | key4: value4 32 | spec: 33 | containers: 34 | - name: spark-kubernetes-driver 35 | image: spark:4.0.0 36 | imagePullPolicy: Always 37 | resources: 38 | requests: 39 | cpu: 1 40 | memory: 1Gi 41 | limits: 42 | cpu: 1 43 | memory: 1Gi 44 | serviceAccount: spark-operator-spark 45 | securityContext: 46 | capabilities: 47 | drop: 48 | - ALL 49 | runAsGroup: 185 50 | runAsUser: 185 51 | runAsNonRoot: true 52 | allowPrivilegeEscalation: false 53 | seccompProfile: 54 | type: RuntimeDefault 55 | executor: 56 | instances: 2 57 | cores: 1 58 | memory: 512m 59 | template: 60 | metadata: 61 | labels: 62 | key1: value1 63 | key2: value2 64 | annotations: 65 | key3: value3 66 | key4: value4 67 | spec: 68 | containers: 69 | - name: spark-kubernetes-executor 70 | image: spark:4.0.0 71 | imagePullPolicy: Always 72 | securityContext: 73 | capabilities: 74 | drop: 75 | - ALL 76 | runAsGroup: 185 77 | runAsUser: 185 78 | runAsNonRoot: true 79 | allowPrivilegeEscalation: false 80 | seccompProfile: 81 | type: RuntimeDefault 82 | -------------------------------------------------------------------------------- /hack/README.md: -------------------------------------------------------------------------------- 1 | ## Updating [client-go](../client-go) directory 2 | [client-go](../client-go) directory contains clientset, informers, and listers generated by [kubernetes/code-generator](https://github.com/kubernetes/code-generator). 3 | 4 | ### Update files in [client-go](../client-go) directory 5 | ```bash 6 | ./hack/update-codegen.sh 7 | ``` 8 | 9 | ### Verify changes to files in [client-go](../client-go) directory 10 | ```bash 11 | ./hack/verify-codegen.sh 12 | ``` 13 | -------------------------------------------------------------------------------- /hack/api-docs/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "hideMemberFields": [ 3 | "TypeMeta" 4 | ], 5 | "hideTypePatterns": [ 6 | "ParseError$", 7 | "List$" 8 | ], 9 | "externalPackages": [ 10 | { 11 | "typeMatchPrefix": "^k8s\\.io/apimachinery/pkg/apis/meta/v1\\.Duration$", 12 | "docsURLTemplate": "https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1#Duration" 13 | }, 14 | { 15 | "typeMatchPrefix": "^k8s\\.io/(api|apimachinery/pkg/apis)/", 16 | "docsURLTemplate": "https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#{{lower .TypeIdentifier}}-{{arrIndex .PackageSegments -1}}-{{arrIndex .PackageSegments -2}}" 17 | }, 18 | { 19 | "typeMatchPrefix": "^github\\.com/knative/pkg/apis/duck/", 20 | "docsURLTemplate": "https://pkg.go.dev/github.com/knative/pkg/apis/duck/{{arrIndex .PackageSegments -1}}#{{.TypeIdentifier}}" 21 | } 22 | ], 23 | "typeDisplayNamePrefixOverrides": { 24 | "k8s.io/api/": "Kubernetes ", 25 | "k8s.io/apimachinery/pkg/apis/": "Kubernetes " 26 | }, 27 | "markdownDisabled": false 28 | } -------------------------------------------------------------------------------- /hack/api-docs/template/members.tpl: -------------------------------------------------------------------------------- 1 | {{ define "members" }} 2 | 3 | {{ range .Members }} 4 | {{ if not (hiddenMember .)}} 5 | 6 | 7 | {{ fieldName . }}
8 | 9 | {{ if linkForType .Type }} 10 | 11 | {{ typeDisplayName .Type }} 12 | 13 | {{ else }} 14 | {{ typeDisplayName .Type }} 15 | {{ end }} 16 | 17 | 18 | 19 | {{ if fieldEmbedded . }} 20 |

21 | (Members of {{ fieldName . }} are embedded into this type.) 22 |

23 | {{ end}} 24 | 25 | {{ if isOptionalMember .}} 26 | (Optional) 27 | {{ end }} 28 | 29 | {{ safe (renderComments .CommentLines) }} 30 | 31 | {{ if and (eq (.Type.Name.Name) "ObjectMeta") }} 32 | Refer to the Kubernetes API documentation for the fields of the 33 | metadata field. 34 | {{ end }} 35 | 36 | {{ if or (eq (fieldName .) "spec") }} 37 |
38 |
39 | 40 | {{ template "members" .Type }} 41 |
42 | {{ end }} 43 | 44 | 45 | {{ end }} 46 | {{ end }} 47 | 48 | {{ end }} -------------------------------------------------------------------------------- /hack/api-docs/template/pkg.tpl: -------------------------------------------------------------------------------- 1 | {{ define "packages" }} 2 | 3 | {{ with .packages}} 4 |

Packages:

5 | 12 | {{ end}} 13 | 14 | {{ range .packages }} 15 |

16 | {{- packageDisplayName . -}} 17 |

18 | 19 | {{ with (index .GoPackages 0 )}} 20 | {{ with .DocComments }} 21 |
22 | {{ safe (renderComments .) }} 23 |
24 | {{ end }} 25 | {{ end }} 26 | 27 | Resource Types: 28 |
    29 | {{- range (visibleTypes (sortedTypes .Types)) -}} 30 | {{ if isExportedType . -}} 31 |
  • 32 | {{ typeDisplayName . }} 33 |
  • 34 | {{- end }} 35 | {{- end -}} 36 |
37 | 38 | {{ range (visibleTypes (sortedTypes .Types))}} 39 | {{ template "type" . }} 40 | {{ end }} 41 |
42 | {{ end }} 43 | 44 |

45 | Generated with gen-crd-api-reference-docs. 46 |

47 | 48 | {{ end }} -------------------------------------------------------------------------------- /hack/api-docs/template/placeholder.go: -------------------------------------------------------------------------------- 1 | // Placeholder file to make Go vendor this directory properly. 2 | package template 3 | -------------------------------------------------------------------------------- /hack/api-docs/template/type.tpl: -------------------------------------------------------------------------------- 1 | {{ define "type" }} 2 | 3 |

4 | {{- .Name.Name }} 5 | {{ if eq .Kind "Alias" }}({{.Underlying}} alias){{ end -}} 6 |

7 | {{ with (typeReferences .) }} 8 |

9 | (Appears on: 10 | {{- $prev := "" -}} 11 | {{- range . -}} 12 | {{- if $prev -}}, {{ end -}} 13 | {{- $prev = . -}} 14 | {{ typeDisplayName . }} 15 | {{- end -}} 16 | ) 17 |

18 | {{ end }} 19 | 20 |
21 | {{ safe (renderComments .CommentLines) }} 22 |
23 | 24 | {{ with (constantsOfType .) }} 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | {{- range . -}} 34 | 35 | {{- /* 36 | renderComments implicitly creates a

element, so we 37 | add one to the display name as well to make the contents 38 | of the two cells align evenly. 39 | */ -}} 40 |

41 | 42 | 43 | {{- end -}} 44 | 45 |
ValueDescription

{{ typeDisplayName . }}

{{ safe (renderComments .CommentLines) }}
46 | {{ end }} 47 | 48 | {{ if .Members }} 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | {{ if isExportedType . }} 58 | 59 | 62 | 67 | 68 | 69 | 73 | 74 | 75 | {{ end }} 76 | {{ template "members" .}} 77 | 78 |
FieldDescription
60 | apiVersion
61 | string
63 | 64 | {{apiGroup .}} 65 | 66 |
70 | kind
71 | string 72 |
{{.Name.Name}}
79 | {{ end }} 80 | 81 | {{ end }} -------------------------------------------------------------------------------- /hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2025 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ -------------------------------------------------------------------------------- /hack/generate-changelog.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | from github import Github 4 | 5 | REPO_NAME = "kubeflow/spark-operator" 6 | CHANGELOG_FILE = "CHANGELOG.md" 7 | 8 | parser = argparse.ArgumentParser() 9 | parser.add_argument("--token", type=str, help="GitHub Access Token") 10 | parser.add_argument( 11 | "--range", type=str, help="Changelog is generated for this release range" 12 | ) 13 | args = parser.parse_args() 14 | 15 | if args.token is None: 16 | raise Exception("GitHub Token must be set") 17 | try: 18 | previous_release = args.range.split("..")[0] 19 | current_release = args.range.split("..")[1] 20 | except Exception: 21 | raise Exception("Release range must be set in this format: v1.7.0..v1.8.0") 22 | 23 | # Get list of commits from the range. 24 | github_repo = Github(args.token).get_repo(REPO_NAME) 25 | comparison = github_repo.compare(previous_release, current_release) 26 | commits = comparison.commits 27 | 28 | # The latest commit contains the release date. 29 | release_date = str(commits[-1].commit.author.date).split(" ")[0] 30 | release_url = "https://github.com/{}/tree/{}".format(REPO_NAME, current_release) 31 | 32 | # Get all PRs in reverse chronological order from the commits. 33 | pr_list = "" 34 | pr_set = set() 35 | for commit in commits.reversed: 36 | # Only add commits with PRs. 37 | for pr in commit.get_pulls(): 38 | # Each PR is added only one time to the list. 39 | if pr.number in pr_set: 40 | continue 41 | if not pr.merged: 42 | continue 43 | pr_set.add(pr.number) 44 | 45 | new_pr = "- {title} ([#{id}]({pr_link}) by [@{user_id}]({user_url}))\n".format( 46 | title=pr.title, 47 | id=pr.number, 48 | pr_link=pr.html_url, 49 | user_id=pr.user.login, 50 | user_url=pr.user.html_url, 51 | ) 52 | pr_list += new_pr 53 | 54 | change_log = [ 55 | "\n", 56 | "## [{}]({}) ({})\n".format(current_release, release_url, release_date), 57 | "\n", 58 | pr_list, 59 | "\n", 60 | "[Full Changelog]({})\n".format(comparison.html_url), 61 | ] 62 | 63 | # Update Changelog with the new changes. 64 | with open(CHANGELOG_FILE, "r+") as f: 65 | lines = f.readlines() 66 | f.seek(0) 67 | lines = lines[:1] + change_log + lines[1:] 68 | f.writelines(lines) 69 | 70 | print("Changelog has been updated\n") 71 | print("Group PRs in the Changelog into Features, Bug fixes, Misc, etc.\n") 72 | print("After that, submit a PR with the updated Changelog") 73 | -------------------------------------------------------------------------------- /hack/install_packages.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Copyright 2019 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | set -e 17 | arg1=$(head -2 /opt/spark/credentials | tail -1) 18 | arg2=$(head -3 /opt/spark/credentials | tail -1) 19 | arg3=$(head -1 /opt/spark/credentials | tail -1) 20 | 21 | subscription-manager register --username=$arg1 --password=$arg2 --name=docker 22 | subscription-manager attach --pool=$arg3 && yum install -y openssl 23 | subscription-manager remove --all 24 | subscription-manager unregister 25 | subscription-manager clean 26 | -------------------------------------------------------------------------------- /hack/update-codegen.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2017 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | GO_CMD=${1:-go} 22 | SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")" 23 | SCRIPT_ROOT="${SCRIPT_DIR}/.." 24 | CODEGEN_PKG="$($GO_CMD list -m -mod=readonly -f "{{.Dir}}" k8s.io/code-generator)" 25 | SPARK_OPERATOR_PKG="github.com/kubeflow/spark-operator/v2" 26 | 27 | source "${CODEGEN_PKG}/kube_codegen.sh" 28 | 29 | # Generate register code 30 | kube::codegen::gen_register \ 31 | --boilerplate "${SCRIPT_ROOT}/hack/boilerplate.go.txt" \ 32 | "${SCRIPT_ROOT}" 33 | 34 | # Generate client code: client, lister, informer in client-go directory 35 | kube::codegen::gen_client \ 36 | --with-watch \ 37 | --output-dir "${SCRIPT_ROOT}/pkg/client" \ 38 | --output-pkg "${SPARK_OPERATOR_PKG}/pkg/client" \ 39 | --boilerplate "${SCRIPT_ROOT}/hack/boilerplate.go.txt" \ 40 | "${SCRIPT_ROOT}" 41 | -------------------------------------------------------------------------------- /hack/verify-codegen.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2017 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | SCRIPT_ROOT=$(dirname "${BASH_SOURCE}")/.. 22 | 23 | DIFFROOT="${SCRIPT_ROOT}/pkg" 24 | TMP_DIFFROOT="${SCRIPT_ROOT}/_tmp/pkg" 25 | _tmp="${SCRIPT_ROOT}/_tmp" 26 | 27 | cleanup() { 28 | rm -rf "${_tmp}" 29 | } 30 | trap "cleanup" EXIT SIGINT 31 | 32 | cleanup 33 | 34 | mkdir -p "${TMP_DIFFROOT}" 35 | cp -a "${DIFFROOT}"/* "${TMP_DIFFROOT}" 36 | 37 | "${SCRIPT_ROOT}/hack/update-codegen.sh" 38 | echo "diffing ${DIFFROOT} against freshly generated codegen" 39 | ret=0 40 | diff -Naupr "${DIFFROOT}" "${TMP_DIFFROOT}" || ret=$? 41 | cp -a "${TMP_DIFFROOT}"/* "${DIFFROOT}" 42 | if [[ $ret -eq 0 ]] 43 | then 44 | echo "${DIFFROOT} up to date." 45 | else 46 | echo "${DIFFROOT} is out of date. Please run hack/update-codegen.sh" 47 | exit 1 48 | fi 49 | -------------------------------------------------------------------------------- /internal/controller/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controller 18 | 19 | // Package controller implements the CustomResourceDefinition (CRD) controller for SparkApplications and 20 | // ScheduledSparkApplications. 21 | // 22 | // The ScheduledSparkApplication controller is responsible for watching ScheduledSparkApplications objects 23 | // and scheduling them according to the cron schedule in the ScheduledSparkApplication specification. For 24 | // each ScheduledSparkApplication, the controller creates a new SparkApplication instance when the next run 25 | // of the application is due and the condition for starting the next run is satisfied. 26 | // 27 | // The SparkApplication controller is responsible for watching SparkApplication objects and submitting 28 | // Spark applications described by the specs in the objects on behalf of users. After an application is 29 | // submitted, the controller monitors the application state and updates the status field of the 30 | // SparkApplication object accordingly. The controller uses a sparkSubmitRunner to submit applications 31 | // to run in the Kubernetes cluster where Spark Operator runs. The sparkSubmitRunner maintains a set of 32 | // workers, each of which is a goroutine, for actually running the spark-submit commands. The controller 33 | // also uses a sparkPodMonitor to watch Spark driver and executor pods. The sparkPodMonitor sends driver 34 | // and executor state updates to the controller, which then updates status field of SparkApplication 35 | // objects accordingly. 36 | -------------------------------------------------------------------------------- /internal/controller/mutatingwebhookconfiguration/event_filter.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package mutatingwebhookconfiguration 18 | 19 | import ( 20 | "sigs.k8s.io/controller-runtime/pkg/event" 21 | "sigs.k8s.io/controller-runtime/pkg/predicate" 22 | ) 23 | 24 | // EventFilter filters events for MutatingWebhookConfiguration. 25 | type EventFilter struct { 26 | name string 27 | } 28 | 29 | func NewEventFilter(name string) *EventFilter { 30 | return &EventFilter{ 31 | name: name, 32 | } 33 | } 34 | 35 | // MutatingWebhookConfigurationEventFilter implements predicate.Predicate. 36 | var _ predicate.Predicate = &EventFilter{} 37 | 38 | // Create implements predicate.Predicate. 39 | func (f *EventFilter) Create(e event.CreateEvent) bool { 40 | return e.Object.GetName() == f.name 41 | } 42 | 43 | // Update implements predicate.Predicate. 44 | func (f *EventFilter) Update(e event.UpdateEvent) bool { 45 | return e.ObjectOld.GetName() == f.name 46 | } 47 | 48 | // Delete implements predicate.Predicate. 49 | func (f *EventFilter) Delete(event.DeleteEvent) bool { 50 | return false 51 | } 52 | 53 | // Generic implements predicate.Predicate. 54 | func (f *EventFilter) Generic(event.GenericEvent) bool { 55 | return false 56 | } 57 | -------------------------------------------------------------------------------- /internal/controller/scheduledsparkapplication/event_filter.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package scheduledsparkapplication 18 | 19 | import ( 20 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 | "sigs.k8s.io/controller-runtime/pkg/event" 22 | "sigs.k8s.io/controller-runtime/pkg/predicate" 23 | 24 | "github.com/kubeflow/spark-operator/v2/api/v1beta2" 25 | ) 26 | 27 | // EventFilter filters out ScheduledSparkApplication events. 28 | type EventFilter struct { 29 | namespaces map[string]bool 30 | } 31 | 32 | // EventHandler handles ScheduledSparkApplication events. 33 | var _ predicate.Predicate = &EventFilter{} 34 | 35 | // NewEventFilter creates a new EventFilter instance. 36 | func NewEventFilter(namespaces []string) *EventFilter { 37 | nsMap := make(map[string]bool) 38 | if len(namespaces) == 0 { 39 | nsMap[metav1.NamespaceAll] = true 40 | } else { 41 | for _, ns := range namespaces { 42 | nsMap[ns] = true 43 | } 44 | } 45 | 46 | return &EventFilter{ 47 | namespaces: nsMap, 48 | } 49 | } 50 | 51 | // Create implements predicate.Predicate. 52 | func (f *EventFilter) Create(e event.CreateEvent) bool { 53 | app, ok := e.Object.(*v1beta2.ScheduledSparkApplication) 54 | if !ok { 55 | return false 56 | } 57 | return f.filter(app) 58 | } 59 | 60 | // Update implements predicate.Predicate. 61 | func (f *EventFilter) Update(e event.UpdateEvent) bool { 62 | newApp, ok := e.ObjectNew.(*v1beta2.ScheduledSparkApplication) 63 | if !ok { 64 | return false 65 | } 66 | 67 | return f.filter(newApp) 68 | } 69 | 70 | // Delete implements predicate.Predicate. 71 | func (f *EventFilter) Delete(_ event.DeleteEvent) bool { 72 | return false 73 | } 74 | 75 | // Generic implements predicate.Predicate. 76 | func (f *EventFilter) Generic(e event.GenericEvent) bool { 77 | app, ok := e.Object.(*v1beta2.ScheduledSparkApplication) 78 | if !ok { 79 | return false 80 | } 81 | return f.filter(app) 82 | } 83 | 84 | func (f *EventFilter) filter(app *v1beta2.ScheduledSparkApplication) bool { 85 | return f.namespaces[metav1.NamespaceAll] || f.namespaces[app.Namespace] 86 | } 87 | -------------------------------------------------------------------------------- /internal/controller/sparkapplication/validator.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package sparkapplication 18 | 19 | import ( 20 | "context" 21 | 22 | "k8s.io/apimachinery/pkg/runtime" 23 | "sigs.k8s.io/controller-runtime/pkg/webhook/admission" 24 | ) 25 | 26 | type Validator struct{} 27 | 28 | // Validator implements admission.CustomValidator. 29 | var _ admission.CustomValidator = &Validator{} 30 | 31 | // ValidateCreate implements admission.CustomValidator. 32 | func (s *Validator) ValidateCreate(_ context.Context, _ runtime.Object) (admission.Warnings, error) { 33 | return nil, nil 34 | } 35 | 36 | // ValidateDelete implements admission.CustomValidator. 37 | func (s *Validator) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) { 38 | return nil, nil 39 | } 40 | 41 | // ValidateUpdate implements admission.CustomValidator. 42 | func (s *Validator) ValidateUpdate(_ context.Context, _ runtime.Object, _ runtime.Object) (admission.Warnings, error) { 43 | return nil, nil 44 | } 45 | -------------------------------------------------------------------------------- /internal/controller/validatingwebhookconfiguration/event_filter.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package validatingwebhookconfiguration 18 | 19 | import ( 20 | "sigs.k8s.io/controller-runtime/pkg/event" 21 | "sigs.k8s.io/controller-runtime/pkg/predicate" 22 | ) 23 | 24 | // EventFilter filters events for the ValidatingWebhookConfiguration. 25 | type EventFilter struct { 26 | name string 27 | } 28 | 29 | func NewEventFilter(name string) *EventFilter { 30 | return &EventFilter{ 31 | name: name, 32 | } 33 | } 34 | 35 | // ValidatingWebhookConfigurationEventFilter implements predicate.Predicate interface. 36 | var _ predicate.Predicate = &EventFilter{} 37 | 38 | // Create implements predicate.Predicate. 39 | func (f *EventFilter) Create(e event.CreateEvent) bool { 40 | return e.Object.GetName() == f.name 41 | } 42 | 43 | // Update implements predicate.Predicate. 44 | func (f *EventFilter) Update(e event.UpdateEvent) bool { 45 | return e.ObjectOld.GetName() == f.name 46 | } 47 | 48 | // Delete implements predicate.Predicate. 49 | func (f *EventFilter) Delete(event.DeleteEvent) bool { 50 | return false 51 | } 52 | 53 | // Generic implements predicate.Predicate. 54 | func (f *EventFilter) Generic(event.GenericEvent) bool { 55 | return false 56 | } 57 | -------------------------------------------------------------------------------- /internal/metrics/metrcis.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package metrics 18 | 19 | import "sigs.k8s.io/controller-runtime/pkg/log" 20 | 21 | var ( 22 | logger = log.Log.WithName("") 23 | ) 24 | -------------------------------------------------------------------------------- /internal/scheduler/kubescheduler/util.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package kubescheduler 18 | 19 | import ( 20 | "fmt" 21 | 22 | "github.com/kubeflow/spark-operator/v2/api/v1beta2" 23 | ) 24 | 25 | func getPodGroupName(app *v1beta2.SparkApplication) string { 26 | return fmt.Sprintf("%s-pg", app.Name) 27 | } 28 | -------------------------------------------------------------------------------- /internal/scheduler/registry.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Google LLC 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package scheduler 18 | 19 | import ( 20 | "fmt" 21 | "sync" 22 | ) 23 | 24 | var registry *Registry 25 | 26 | // Registry is a registry of scheduler factories. 27 | type Registry struct { 28 | factories map[string]Factory 29 | 30 | mu sync.Mutex 31 | } 32 | 33 | func GetRegistry() *Registry { 34 | if registry == nil { 35 | registry = &Registry{ 36 | factories: make(map[string]Factory), 37 | } 38 | } 39 | return registry 40 | } 41 | 42 | func (r *Registry) GetScheduler(name string, config Config) (Interface, error) { 43 | r.mu.Lock() 44 | defer r.mu.Unlock() 45 | 46 | factory, exists := r.factories[name] 47 | if !exists { 48 | return nil, fmt.Errorf("scheduler %s not found", name) 49 | } 50 | 51 | return factory(config) 52 | } 53 | 54 | // RegisterScheduler registers a scheduler to the manager. 55 | func (r *Registry) Register(name string, factory Factory) error { 56 | r.mu.Lock() 57 | defer r.mu.Unlock() 58 | 59 | if _, ok := r.factories[name]; ok { 60 | return fmt.Errorf("scheduler %s is already registered", name) 61 | } 62 | 63 | r.factories[name] = factory 64 | logger.Info("Registered scheduler", "name", name) 65 | return nil 66 | } 67 | 68 | // GetRegisteredSchedulerNames gets the registered scheduler names. 69 | func (r *Registry) GetRegisteredSchedulerNames() []string { 70 | var names []string 71 | for name := range r.factories { 72 | names = append(names, name) 73 | } 74 | return names 75 | } 76 | -------------------------------------------------------------------------------- /internal/scheduler/scheduler.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Google LLC 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package scheduler 18 | 19 | import ( 20 | "sigs.k8s.io/controller-runtime/pkg/log" 21 | 22 | "github.com/kubeflow/spark-operator/v2/api/v1beta2" 23 | ) 24 | 25 | var ( 26 | logger = log.Log.WithName("") 27 | ) 28 | 29 | // Interface defines the interface of a batch scheduler. 30 | type Interface interface { 31 | Name() string 32 | ShouldSchedule(app *v1beta2.SparkApplication) bool 33 | Schedule(app *v1beta2.SparkApplication) error 34 | Cleanup(app *v1beta2.SparkApplication) error 35 | } 36 | 37 | // Config defines the configuration of a batch scheduler. 38 | type Config interface{} 39 | 40 | // Factory defines the factory of a batch scheduler. 41 | type Factory func(config Config) (Interface, error) 42 | -------------------------------------------------------------------------------- /internal/scheduler/volcano/util.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package volcano 18 | 19 | import ( 20 | "fmt" 21 | 22 | "github.com/kubeflow/spark-operator/v2/api/v1beta2" 23 | ) 24 | 25 | func getPodGroupName(app *v1beta2.SparkApplication) string { 26 | return fmt.Sprintf("spark-%s-pg", app.Name) 27 | } 28 | -------------------------------------------------------------------------------- /internal/scheduler/yunikorn/resourceusage/java.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package resourceusage 18 | 19 | import ( 20 | "fmt" 21 | "regexp" 22 | "strconv" 23 | "strings" 24 | ) 25 | 26 | var ( 27 | javaStringSuffixes = map[string]int64{ 28 | "b": 1, 29 | "kb": 1 << 10, 30 | "k": 1 << 10, 31 | "mb": 1 << 20, 32 | "m": 1 << 20, 33 | "gb": 1 << 30, 34 | "g": 1 << 30, 35 | "tb": 1 << 40, 36 | "t": 1 << 40, 37 | "pb": 1 << 50, 38 | "p": 1 << 50, 39 | } 40 | 41 | javaStringPattern = regexp.MustCompile(`^([0-9]+)([a-z]+)?$`) 42 | ) 43 | 44 | func byteStringAsBytes(byteString string) (int64, error) { 45 | matches := javaStringPattern.FindStringSubmatch(strings.ToLower(byteString)) 46 | if matches != nil { 47 | value, err := strconv.ParseInt(matches[1], 10, 64) 48 | if err != nil { 49 | return 0, err 50 | } 51 | if multiplier, present := javaStringSuffixes[matches[2]]; present { 52 | return value * multiplier, nil 53 | } 54 | } 55 | return 0, fmt.Errorf("unable to parse byte string: %s", byteString) 56 | } 57 | -------------------------------------------------------------------------------- /internal/scheduler/yunikorn/resourceusage/java_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package resourceusage 18 | 19 | import ( 20 | "testing" 21 | 22 | "github.com/stretchr/testify/assert" 23 | ) 24 | 25 | func TestByteStringAsMb(t *testing.T) { 26 | testCases := []struct { 27 | input string 28 | expected int 29 | }{ 30 | {"1k", 1024}, 31 | {"1m", 1024 * 1024}, 32 | {"1g", 1024 * 1024 * 1024}, 33 | {"1t", 1024 * 1024 * 1024 * 1024}, 34 | {"1p", 1024 * 1024 * 1024 * 1024 * 1024}, 35 | } 36 | 37 | for _, tc := range testCases { 38 | t.Run(tc.input, func(t *testing.T) { 39 | actual, err := byteStringAsBytes(tc.input) 40 | assert.Nil(t, err) 41 | assert.Equal(t, int64(tc.expected), actual) 42 | }) 43 | } 44 | } 45 | 46 | func TestByteStringAsMbInvalid(t *testing.T) { 47 | invalidInputs := []string{ 48 | "0.064", 49 | "0.064m", 50 | "500ub", 51 | "This breaks 600b", 52 | "This breaks 600", 53 | "600gb This breaks", 54 | "This 123mb breaks", 55 | } 56 | 57 | for _, input := range invalidInputs { 58 | t.Run(input, func(t *testing.T) { 59 | _, err := byteStringAsBytes(input) 60 | assert.NotNil(t, err) 61 | }) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /internal/scheduler/yunikorn/resourceusage/memory_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package resourceusage 18 | 19 | import ( 20 | "testing" 21 | 22 | "github.com/stretchr/testify/assert" 23 | ) 24 | 25 | func TestBytesToMi(t *testing.T) { 26 | testCases := []struct { 27 | input int64 28 | expected string 29 | }{ 30 | {(2 * 1024 * 1024) - 1, "1Mi"}, 31 | {2 * 1024 * 1024, "2Mi"}, 32 | {(1024 * 1024 * 1024) - 1, "1023Mi"}, 33 | {1024 * 1024 * 1024, "1024Mi"}, 34 | } 35 | 36 | for _, tc := range testCases { 37 | assert.Equal(t, tc.expected, bytesToMi(tc.input)) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /internal/scheduler/yunikorn/resourceusage/resource_usage.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package resourceusage 18 | 19 | import ( 20 | "fmt" 21 | 22 | "k8s.io/apimachinery/pkg/api/resource" 23 | 24 | "github.com/kubeflow/spark-operator/v2/api/v1beta2" 25 | ) 26 | 27 | func cpuRequest(cores *int32, coreRequest *string) (string, error) { 28 | // coreRequest takes precedence over cores if specified 29 | // coreLimit is not relevant as pods are scheduled based on request values 30 | if coreRequest != nil { 31 | // Fail fast by validating coreRequest before app submission even though 32 | // both Spark and Yunikorn validate this field anyway 33 | if _, err := resource.ParseQuantity(*coreRequest); err != nil { 34 | return "", fmt.Errorf("failed to parse %s: %w", *coreRequest, err) 35 | } 36 | return *coreRequest, nil 37 | } 38 | if cores != nil { 39 | return fmt.Sprintf("%d", *cores), nil 40 | } 41 | return "1", nil 42 | } 43 | 44 | func DriverPodRequests(app *v1beta2.SparkApplication) (map[string]string, error) { 45 | cpuValue, err := cpuRequest(app.Spec.Driver.Cores, app.Spec.Driver.CoreRequest) 46 | if err != nil { 47 | return nil, err 48 | } 49 | 50 | memoryValue, err := driverMemoryRequest(app) 51 | if err != nil { 52 | return nil, err 53 | } 54 | 55 | return map[string]string{ 56 | "cpu": cpuValue, 57 | "memory": memoryValue, 58 | }, nil 59 | } 60 | 61 | func ExecutorPodRequests(app *v1beta2.SparkApplication) (map[string]string, error) { 62 | cpuValue, err := cpuRequest(app.Spec.Executor.Cores, app.Spec.Executor.CoreRequest) 63 | if err != nil { 64 | return nil, err 65 | } 66 | 67 | memoryValue, err := executorMemoryRequest(app) 68 | if err != nil { 69 | return nil, err 70 | } 71 | 72 | return map[string]string{ 73 | "cpu": cpuValue, 74 | "memory": memoryValue, 75 | }, nil 76 | } 77 | -------------------------------------------------------------------------------- /internal/scheduler/yunikorn/resourceusage/resource_usage_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package resourceusage 18 | 19 | import ( 20 | "testing" 21 | 22 | "github.com/stretchr/testify/assert" 23 | 24 | "github.com/kubeflow/spark-operator/v2/pkg/util" 25 | ) 26 | 27 | func TestCpuRequest(t *testing.T) { 28 | testCases := []struct { 29 | cores *int32 30 | coreRequest *string 31 | expected string 32 | }{ 33 | {nil, nil, "1"}, 34 | {util.Int32Ptr(1), nil, "1"}, 35 | {nil, util.StringPtr("1"), "1"}, 36 | {util.Int32Ptr(1), util.StringPtr("500m"), "500m"}, 37 | } 38 | 39 | for _, tc := range testCases { 40 | actual, err := cpuRequest(tc.cores, tc.coreRequest) 41 | assert.Nil(t, err) 42 | assert.Equal(t, tc.expected, actual) 43 | } 44 | } 45 | 46 | func TestCpuRequestInvalid(t *testing.T) { 47 | invalidInputs := []string{ 48 | "", 49 | "asd", 50 | "Random 500m", 51 | } 52 | 53 | for _, input := range invalidInputs { 54 | _, err := cpuRequest(nil, &input) 55 | assert.NotNil(t, err) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /internal/webhook/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 Google LLC 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package webhook 18 | 19 | // Package webhook implements a mutating admission webhook for patching Spark driver and executor pods. 20 | // The webhook supports mutations that are not supported by Spark on Kubernetes itself, e.g., adding an 21 | // OwnerReference to the driver pod for the owning SparkApplications or setting the SecurityContext. 22 | -------------------------------------------------------------------------------- /internal/webhook/resourcequota_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package webhook 18 | 19 | import ( 20 | "testing" 21 | ) 22 | 23 | func assertMemory(memoryString string, expectedBytes int64, t *testing.T) { 24 | m, err := parseJavaMemoryString(memoryString) 25 | if err != nil { 26 | t.Error(err) 27 | return 28 | } 29 | if m != expectedBytes { 30 | t.Errorf("%s: expected %v bytes, got %v bytes", memoryString, expectedBytes, m) 31 | return 32 | } 33 | } 34 | 35 | func TestJavaMemoryString(t *testing.T) { 36 | assertMemory("1b", 1, t) 37 | assertMemory("100k", 100*1024, t) 38 | assertMemory("1gb", 1024*1024*1024, t) 39 | assertMemory("10TB", 10*1024*1024*1024*1024, t) 40 | assertMemory("10PB", 10*1024*1024*1024*1024*1024, t) 41 | } 42 | -------------------------------------------------------------------------------- /internal/webhook/scheduledsparkapplication_defaulter.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package webhook 18 | 19 | import ( 20 | "context" 21 | 22 | "k8s.io/apimachinery/pkg/runtime" 23 | "sigs.k8s.io/controller-runtime/pkg/webhook/admission" 24 | 25 | "github.com/kubeflow/spark-operator/v2/api/v1beta2" 26 | ) 27 | 28 | // +kubebuilder:webhook:admissionReviewVersions=v1,failurePolicy=fail,groups=sparkoperator.k8s.io,matchPolicy=Exact,mutating=false,name=mutate-scheduledsparkapplication.sparkoperator.k8s.io,path=/validate-sparkoperator-k8s-io-v1beta2-sparkapplication,reinvocationPolicy=Never,resources=scheduledsparkapplications,sideEffects=None,verbs=create;update,versions=v1beta2,webhookVersions=v1 29 | 30 | // ScheduledSparkApplicationDefaulter sets default values for a SparkApplication. 31 | type ScheduledSparkApplicationDefaulter struct{} 32 | 33 | // NewSparkApplicationValidator creates a new SparkApplicationValidator instance. 34 | func NewScheduledSparkApplicationDefaulter() *ScheduledSparkApplicationDefaulter { 35 | return &ScheduledSparkApplicationDefaulter{} 36 | } 37 | 38 | // SparkApplicationDefaulter implements admission.CustomDefaulter. 39 | var _ admission.CustomDefaulter = &ScheduledSparkApplicationDefaulter{} 40 | 41 | // Default implements admission.CustomDefaulter. 42 | func (d *ScheduledSparkApplicationDefaulter) Default(ctx context.Context, obj runtime.Object) error { 43 | app, ok := obj.(*v1beta2.ScheduledSparkApplication) 44 | if !ok { 45 | return nil 46 | } 47 | logger.Info("Defaulting ScheduledSparkApplication", "name", app.Name, "namespace", app.Namespace) 48 | return nil 49 | } 50 | -------------------------------------------------------------------------------- /internal/webhook/webhook.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package webhook 18 | 19 | import ( 20 | ctrl "sigs.k8s.io/controller-runtime" 21 | ) 22 | 23 | var ( 24 | logger = ctrl.Log.WithName("") 25 | ) 26 | 27 | type Options struct { 28 | SparkJobNamespaces []string 29 | WebhookName string 30 | WebhookPort int 31 | WebhookSecretName string 32 | WebhookSecretNamespace string 33 | WebhookServiceName string 34 | WebhookServiceNamespace string 35 | WebhookMetricsBindAddress string 36 | EnableResourceQuotaEnforcement bool 37 | } 38 | -------------------------------------------------------------------------------- /pkg/certificate/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package certificate 18 | -------------------------------------------------------------------------------- /pkg/certificate/util.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package certificate 18 | 19 | import ( 20 | "crypto/rand" 21 | "crypto/rsa" 22 | "crypto/x509" 23 | "crypto/x509/pkix" 24 | "fmt" 25 | "math" 26 | "math/big" 27 | "time" 28 | 29 | "k8s.io/client-go/util/cert" 30 | 31 | "github.com/kubeflow/spark-operator/v2/pkg/common" 32 | ) 33 | 34 | func NewPrivateKey() (*rsa.PrivateKey, error) { 35 | key, err := rsa.GenerateKey(rand.Reader, common.RSAKeySize) 36 | if err != nil { 37 | return nil, fmt.Errorf("failed to generate private key: %v", err) 38 | } 39 | return key, nil 40 | } 41 | 42 | func NewSignedServerCert(cfg cert.Config, caKey *rsa.PrivateKey, caCert *x509.Certificate, serverKey *rsa.PrivateKey) (*x509.Certificate, error) { 43 | // Generate a random serial number in [1, max). 44 | serial, err := rand.Int(rand.Reader, new(big.Int).SetInt64(math.MaxInt64-1)) 45 | if err != nil { 46 | return nil, fmt.Errorf("failed to generate serial number: %v", err) 47 | } 48 | serial.Add(serial, big.NewInt(1)) 49 | 50 | now := time.Now() 51 | notBefore := now.UTC() 52 | if !cfg.NotBefore.IsZero() { 53 | notBefore = cfg.NotBefore.UTC() 54 | } 55 | 56 | // Create a certificate template for webhook server 57 | certTmpl := x509.Certificate{ 58 | SerialNumber: serial, 59 | Subject: pkix.Name{ 60 | CommonName: cfg.CommonName, 61 | Organization: cfg.Organization, 62 | }, 63 | DNSNames: cfg.AltNames.DNSNames, 64 | IPAddresses: cfg.AltNames.IPs, 65 | NotBefore: notBefore, 66 | NotAfter: now.AddDate(10, 0, 0), 67 | KeyUsage: x509.KeyUsageContentCommitment | x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, 68 | ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, 69 | BasicConstraintsValid: true, 70 | IsCA: false, 71 | } 72 | 73 | certBytes, err := x509.CreateCertificate(rand.Reader, &certTmpl, caCert, serverKey.Public(), caKey) 74 | if err != nil { 75 | return nil, fmt.Errorf("failed to generate certificate: %v", err) 76 | } 77 | 78 | serverCert, err := x509.ParseCertificate(certBytes) 79 | if err != nil { 80 | return nil, fmt.Errorf("failed to parse certificate: %v", err) 81 | } 82 | 83 | return serverCert, nil 84 | } 85 | -------------------------------------------------------------------------------- /pkg/certificate/util_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package certificate_test 18 | 19 | import ( 20 | "crypto/rand" 21 | "crypto/rsa" 22 | "crypto/x509" 23 | "testing" 24 | "time" 25 | 26 | "k8s.io/client-go/util/cert" 27 | 28 | "github.com/kubeflow/spark-operator/v2/pkg/certificate" 29 | "github.com/kubeflow/spark-operator/v2/pkg/common" 30 | ) 31 | 32 | func TestNewPrivateKey(t *testing.T) { 33 | _, err := certificate.NewPrivateKey() 34 | if err != nil { 35 | t.Errorf("failed to generate private key: %v", err) 36 | } 37 | } 38 | 39 | func TestNewSignedServerCert(t *testing.T) { 40 | cfg := cert.Config{ 41 | CommonName: "test-server", 42 | Organization: []string{"test-org"}, 43 | NotBefore: time.Now(), 44 | } 45 | 46 | caKey, _ := rsa.GenerateKey(rand.Reader, common.RSAKeySize) 47 | caCert := &x509.Certificate{} 48 | serverKey, _ := rsa.GenerateKey(rand.Reader, common.RSAKeySize) 49 | 50 | serverCert, err := certificate.NewSignedServerCert(cfg, caKey, caCert, serverKey) 51 | if err != nil { 52 | t.Errorf("failed to generate signed server certificate: %v", err) 53 | } 54 | 55 | if serverCert == nil { 56 | t.Error("server certificate is nil") 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/fake/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2025 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | // This package has the automatically generated fake clientset. 19 | package fake 20 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/fake/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2025 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | package fake 19 | 20 | import ( 21 | sparkoperatorv1beta2 "github.com/kubeflow/spark-operator/v2/api/v1beta2" 22 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 23 | runtime "k8s.io/apimachinery/pkg/runtime" 24 | schema "k8s.io/apimachinery/pkg/runtime/schema" 25 | serializer "k8s.io/apimachinery/pkg/runtime/serializer" 26 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 27 | ) 28 | 29 | var scheme = runtime.NewScheme() 30 | var codecs = serializer.NewCodecFactory(scheme) 31 | 32 | var localSchemeBuilder = runtime.SchemeBuilder{ 33 | sparkoperatorv1beta2.AddToScheme, 34 | } 35 | 36 | // AddToScheme adds all types of this clientset into the given scheme. This allows composition 37 | // of clientsets, like in: 38 | // 39 | // import ( 40 | // "k8s.io/client-go/kubernetes" 41 | // clientsetscheme "k8s.io/client-go/kubernetes/scheme" 42 | // aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" 43 | // ) 44 | // 45 | // kclientset, _ := kubernetes.NewForConfig(c) 46 | // _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) 47 | // 48 | // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types 49 | // correctly. 50 | var AddToScheme = localSchemeBuilder.AddToScheme 51 | 52 | func init() { 53 | v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"}) 54 | utilruntime.Must(AddToScheme(scheme)) 55 | } 56 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/scheme/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2025 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | // This package contains the scheme of the automatically generated clientset. 19 | package scheme 20 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/scheme/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2025 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | package scheme 19 | 20 | import ( 21 | sparkoperatorv1beta2 "github.com/kubeflow/spark-operator/v2/api/v1beta2" 22 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 23 | runtime "k8s.io/apimachinery/pkg/runtime" 24 | schema "k8s.io/apimachinery/pkg/runtime/schema" 25 | serializer "k8s.io/apimachinery/pkg/runtime/serializer" 26 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 27 | ) 28 | 29 | var Scheme = runtime.NewScheme() 30 | var Codecs = serializer.NewCodecFactory(Scheme) 31 | var ParameterCodec = runtime.NewParameterCodec(Scheme) 32 | var localSchemeBuilder = runtime.SchemeBuilder{ 33 | sparkoperatorv1beta2.AddToScheme, 34 | } 35 | 36 | // AddToScheme adds all types of this clientset into the given scheme. This allows composition 37 | // of clientsets, like in: 38 | // 39 | // import ( 40 | // "k8s.io/client-go/kubernetes" 41 | // clientsetscheme "k8s.io/client-go/kubernetes/scheme" 42 | // aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" 43 | // ) 44 | // 45 | // kclientset, _ := kubernetes.NewForConfig(c) 46 | // _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) 47 | // 48 | // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types 49 | // correctly. 50 | var AddToScheme = localSchemeBuilder.AddToScheme 51 | 52 | func init() { 53 | v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) 54 | utilruntime.Must(AddToScheme(Scheme)) 55 | } 56 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/api/v1beta2/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2025 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | // This package has the automatically generated typed clients. 19 | package v1beta2 20 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/api/v1beta2/fake/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2025 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | // Package fake has the automatically generated clients. 19 | package fake 20 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/api/v1beta2/fake/fake_api_client.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2025 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | package fake 19 | 20 | import ( 21 | v1beta2 "github.com/kubeflow/spark-operator/v2/pkg/client/clientset/versioned/typed/api/v1beta2" 22 | rest "k8s.io/client-go/rest" 23 | testing "k8s.io/client-go/testing" 24 | ) 25 | 26 | type FakeSparkoperatorV1beta2 struct { 27 | *testing.Fake 28 | } 29 | 30 | func (c *FakeSparkoperatorV1beta2) ScheduledSparkApplications(namespace string) v1beta2.ScheduledSparkApplicationInterface { 31 | return newFakeScheduledSparkApplications(c, namespace) 32 | } 33 | 34 | func (c *FakeSparkoperatorV1beta2) SparkApplications(namespace string) v1beta2.SparkApplicationInterface { 35 | return newFakeSparkApplications(c, namespace) 36 | } 37 | 38 | // RESTClient returns a RESTClient that is used to communicate 39 | // with API server by this client implementation. 40 | func (c *FakeSparkoperatorV1beta2) RESTClient() rest.Interface { 41 | var ret *rest.RESTClient 42 | return ret 43 | } 44 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/api/v1beta2/fake/fake_scheduledsparkapplication.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2025 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | package fake 19 | 20 | import ( 21 | v1beta2 "github.com/kubeflow/spark-operator/v2/api/v1beta2" 22 | apiv1beta2 "github.com/kubeflow/spark-operator/v2/pkg/client/clientset/versioned/typed/api/v1beta2" 23 | gentype "k8s.io/client-go/gentype" 24 | ) 25 | 26 | // fakeScheduledSparkApplications implements ScheduledSparkApplicationInterface 27 | type fakeScheduledSparkApplications struct { 28 | *gentype.FakeClientWithList[*v1beta2.ScheduledSparkApplication, *v1beta2.ScheduledSparkApplicationList] 29 | Fake *FakeSparkoperatorV1beta2 30 | } 31 | 32 | func newFakeScheduledSparkApplications(fake *FakeSparkoperatorV1beta2, namespace string) apiv1beta2.ScheduledSparkApplicationInterface { 33 | return &fakeScheduledSparkApplications{ 34 | gentype.NewFakeClientWithList[*v1beta2.ScheduledSparkApplication, *v1beta2.ScheduledSparkApplicationList]( 35 | fake.Fake, 36 | namespace, 37 | v1beta2.SchemeGroupVersion.WithResource("scheduledsparkapplications"), 38 | v1beta2.SchemeGroupVersion.WithKind("ScheduledSparkApplication"), 39 | func() *v1beta2.ScheduledSparkApplication { return &v1beta2.ScheduledSparkApplication{} }, 40 | func() *v1beta2.ScheduledSparkApplicationList { return &v1beta2.ScheduledSparkApplicationList{} }, 41 | func(dst, src *v1beta2.ScheduledSparkApplicationList) { dst.ListMeta = src.ListMeta }, 42 | func(list *v1beta2.ScheduledSparkApplicationList) []*v1beta2.ScheduledSparkApplication { 43 | return gentype.ToPointerSlice(list.Items) 44 | }, 45 | func(list *v1beta2.ScheduledSparkApplicationList, items []*v1beta2.ScheduledSparkApplication) { 46 | list.Items = gentype.FromPointerSlice(items) 47 | }, 48 | ), 49 | fake, 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/api/v1beta2/fake/fake_sparkapplication.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2025 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | package fake 19 | 20 | import ( 21 | v1beta2 "github.com/kubeflow/spark-operator/v2/api/v1beta2" 22 | apiv1beta2 "github.com/kubeflow/spark-operator/v2/pkg/client/clientset/versioned/typed/api/v1beta2" 23 | gentype "k8s.io/client-go/gentype" 24 | ) 25 | 26 | // fakeSparkApplications implements SparkApplicationInterface 27 | type fakeSparkApplications struct { 28 | *gentype.FakeClientWithList[*v1beta2.SparkApplication, *v1beta2.SparkApplicationList] 29 | Fake *FakeSparkoperatorV1beta2 30 | } 31 | 32 | func newFakeSparkApplications(fake *FakeSparkoperatorV1beta2, namespace string) apiv1beta2.SparkApplicationInterface { 33 | return &fakeSparkApplications{ 34 | gentype.NewFakeClientWithList[*v1beta2.SparkApplication, *v1beta2.SparkApplicationList]( 35 | fake.Fake, 36 | namespace, 37 | v1beta2.SchemeGroupVersion.WithResource("sparkapplications"), 38 | v1beta2.SchemeGroupVersion.WithKind("SparkApplication"), 39 | func() *v1beta2.SparkApplication { return &v1beta2.SparkApplication{} }, 40 | func() *v1beta2.SparkApplicationList { return &v1beta2.SparkApplicationList{} }, 41 | func(dst, src *v1beta2.SparkApplicationList) { dst.ListMeta = src.ListMeta }, 42 | func(list *v1beta2.SparkApplicationList) []*v1beta2.SparkApplication { 43 | return gentype.ToPointerSlice(list.Items) 44 | }, 45 | func(list *v1beta2.SparkApplicationList, items []*v1beta2.SparkApplication) { 46 | list.Items = gentype.FromPointerSlice(items) 47 | }, 48 | ), 49 | fake, 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/api/v1beta2/generated_expansion.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2025 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | package v1beta2 19 | 20 | type ScheduledSparkApplicationExpansion interface{} 21 | 22 | type SparkApplicationExpansion interface{} 23 | -------------------------------------------------------------------------------- /pkg/client/informers/externalversions/api/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2025 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Code generated by informer-gen. DO NOT EDIT. 17 | 18 | package api 19 | 20 | import ( 21 | v1beta2 "github.com/kubeflow/spark-operator/v2/pkg/client/informers/externalversions/api/v1beta2" 22 | internalinterfaces "github.com/kubeflow/spark-operator/v2/pkg/client/informers/externalversions/internalinterfaces" 23 | ) 24 | 25 | // Interface provides access to each of this group's versions. 26 | type Interface interface { 27 | // V1beta2 provides access to shared informers for resources in V1beta2. 28 | V1beta2() v1beta2.Interface 29 | } 30 | 31 | type group struct { 32 | factory internalinterfaces.SharedInformerFactory 33 | namespace string 34 | tweakListOptions internalinterfaces.TweakListOptionsFunc 35 | } 36 | 37 | // New returns a new Interface. 38 | func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { 39 | return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} 40 | } 41 | 42 | // V1beta2 returns a new v1beta2.Interface. 43 | func (g *group) V1beta2() v1beta2.Interface { 44 | return v1beta2.New(g.factory, g.namespace, g.tweakListOptions) 45 | } 46 | -------------------------------------------------------------------------------- /pkg/client/informers/externalversions/api/v1beta2/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2025 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Code generated by informer-gen. DO NOT EDIT. 17 | 18 | package v1beta2 19 | 20 | import ( 21 | internalinterfaces "github.com/kubeflow/spark-operator/v2/pkg/client/informers/externalversions/internalinterfaces" 22 | ) 23 | 24 | // Interface provides access to all the informers in this group version. 25 | type Interface interface { 26 | // ScheduledSparkApplications returns a ScheduledSparkApplicationInformer. 27 | ScheduledSparkApplications() ScheduledSparkApplicationInformer 28 | // SparkApplications returns a SparkApplicationInformer. 29 | SparkApplications() SparkApplicationInformer 30 | } 31 | 32 | type version struct { 33 | factory internalinterfaces.SharedInformerFactory 34 | namespace string 35 | tweakListOptions internalinterfaces.TweakListOptionsFunc 36 | } 37 | 38 | // New returns a new Interface. 39 | func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { 40 | return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} 41 | } 42 | 43 | // ScheduledSparkApplications returns a ScheduledSparkApplicationInformer. 44 | func (v *version) ScheduledSparkApplications() ScheduledSparkApplicationInformer { 45 | return &scheduledSparkApplicationInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} 46 | } 47 | 48 | // SparkApplications returns a SparkApplicationInformer. 49 | func (v *version) SparkApplications() SparkApplicationInformer { 50 | return &sparkApplicationInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} 51 | } 52 | -------------------------------------------------------------------------------- /pkg/client/informers/externalversions/generic.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2025 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Code generated by informer-gen. DO NOT EDIT. 17 | 18 | package externalversions 19 | 20 | import ( 21 | fmt "fmt" 22 | 23 | v1beta2 "github.com/kubeflow/spark-operator/v2/api/v1beta2" 24 | schema "k8s.io/apimachinery/pkg/runtime/schema" 25 | cache "k8s.io/client-go/tools/cache" 26 | ) 27 | 28 | // GenericInformer is type of SharedIndexInformer which will locate and delegate to other 29 | // sharedInformers based on type 30 | type GenericInformer interface { 31 | Informer() cache.SharedIndexInformer 32 | Lister() cache.GenericLister 33 | } 34 | 35 | type genericInformer struct { 36 | informer cache.SharedIndexInformer 37 | resource schema.GroupResource 38 | } 39 | 40 | // Informer returns the SharedIndexInformer. 41 | func (f *genericInformer) Informer() cache.SharedIndexInformer { 42 | return f.informer 43 | } 44 | 45 | // Lister returns the GenericLister. 46 | func (f *genericInformer) Lister() cache.GenericLister { 47 | return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource) 48 | } 49 | 50 | // ForResource gives generic access to a shared informer of the matching type 51 | // TODO extend this to unknown resources with a client pool 52 | func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { 53 | switch resource { 54 | // Group=sparkoperator.k8s.io, Version=v1beta2 55 | case v1beta2.SchemeGroupVersion.WithResource("scheduledsparkapplications"): 56 | return &genericInformer{resource: resource.GroupResource(), informer: f.Sparkoperator().V1beta2().ScheduledSparkApplications().Informer()}, nil 57 | case v1beta2.SchemeGroupVersion.WithResource("sparkapplications"): 58 | return &genericInformer{resource: resource.GroupResource(), informer: f.Sparkoperator().V1beta2().SparkApplications().Informer()}, nil 59 | 60 | } 61 | 62 | return nil, fmt.Errorf("no informer found for %v", resource) 63 | } 64 | -------------------------------------------------------------------------------- /pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2025 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Code generated by informer-gen. DO NOT EDIT. 17 | 18 | package internalinterfaces 19 | 20 | import ( 21 | time "time" 22 | 23 | versioned "github.com/kubeflow/spark-operator/v2/pkg/client/clientset/versioned" 24 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | runtime "k8s.io/apimachinery/pkg/runtime" 26 | cache "k8s.io/client-go/tools/cache" 27 | ) 28 | 29 | // NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer. 30 | type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer 31 | 32 | // SharedInformerFactory a small interface to allow for adding an informer without an import cycle 33 | type SharedInformerFactory interface { 34 | Start(stopCh <-chan struct{}) 35 | InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer 36 | } 37 | 38 | // TweakListOptionsFunc is a function that transforms a v1.ListOptions. 39 | type TweakListOptionsFunc func(*v1.ListOptions) 40 | -------------------------------------------------------------------------------- /pkg/client/listers/api/v1beta2/expansion_generated.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2025 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Code generated by lister-gen. DO NOT EDIT. 17 | 18 | package v1beta2 19 | 20 | // ScheduledSparkApplicationListerExpansion allows custom methods to be added to 21 | // ScheduledSparkApplicationLister. 22 | type ScheduledSparkApplicationListerExpansion interface{} 23 | 24 | // ScheduledSparkApplicationNamespaceListerExpansion allows custom methods to be added to 25 | // ScheduledSparkApplicationNamespaceLister. 26 | type ScheduledSparkApplicationNamespaceListerExpansion interface{} 27 | 28 | // SparkApplicationListerExpansion allows custom methods to be added to 29 | // SparkApplicationLister. 30 | type SparkApplicationListerExpansion interface{} 31 | 32 | // SparkApplicationNamespaceListerExpansion allows custom methods to be added to 33 | // SparkApplicationNamespaceLister. 34 | type SparkApplicationNamespaceListerExpansion interface{} 35 | -------------------------------------------------------------------------------- /pkg/common/constants.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package common 18 | 19 | const ( 20 | ErrorCodePodAlreadyExists = "code=409" 21 | ) 22 | 23 | const ( 24 | SparkApplicationFinalizerName = "sparkoperator.k8s.io/finalizer" 25 | ScheduledSparkApplicationFinalizerName = "sparkoperator.k8s.io/finalizer" 26 | ) 27 | 28 | const ( 29 | RSAKeySize = 2048 30 | ) 31 | 32 | const ( 33 | // Internal Cert 34 | CAKeyPem = "ca-key.pem" 35 | CACertPem = "ca-cert.pem" 36 | ServerKeyPem = "server-key.pem" 37 | ServerCertPem = "server-cert.pem" 38 | 39 | // Cert Manager 40 | CACert = "ca.crt" 41 | TLSCert = "tls.crt" 42 | TLSKey = "tls.key" 43 | ) 44 | 45 | // Kubernetes volume types. 46 | const ( 47 | VolumeTypeEmptyDir = "emptyDir" 48 | VolumeTypeHostPath = "hostPath" 49 | VolumeTypeNFS = "nfs" 50 | VolumeTypePersistentVolumeClaim = "persistentVolumeClaim" 51 | ) 52 | 53 | const ( 54 | // Epsilon is a small number used to compare 64 bit floating point numbers. 55 | Epsilon = 1e-9 56 | ) 57 | -------------------------------------------------------------------------------- /pkg/common/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 Google LLC 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package common 18 | 19 | // Package common contains code that deals with configuration of Spark driver and executor pods, e.g., mounting 20 | // user-specified ConfigMaps, volumes, secrets, etc. 21 | -------------------------------------------------------------------------------- /pkg/common/event.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package common 18 | 19 | // SparkApplication events 20 | const ( 21 | EventSparkApplicationAdded = "SparkApplicationAdded" 22 | 23 | EventSparkApplicationSubmitted = "SparkApplicationSubmitted" 24 | 25 | EventSparkApplicationSubmissionFailed = "SparkApplicationSubmissionFailed" 26 | 27 | EventSparkApplicationCompleted = "SparkApplicationCompleted" 28 | 29 | EventSparkApplicationFailed = "SparkApplicationFailed" 30 | 31 | EventSparkApplicationPendingRerun = "SparkApplicationPendingRerun" 32 | ) 33 | 34 | // Spark driver events 35 | const ( 36 | EventSparkDriverPending = "SparkDriverPending" 37 | 38 | EventSparkDriverRunning = "SparkDriverRunning" 39 | 40 | EventSparkDriverCompleted = "SparkDriverCompleted" 41 | 42 | EventSparkDriverFailed = "SparkDriverFailed" 43 | 44 | EventSparkDriverUnknown = "SparkDriverUnknown" 45 | ) 46 | 47 | // Spark executor events 48 | const ( 49 | EventSparkExecutorPending = "SparkExecutorPending" 50 | 51 | EventSparkExecutorRunning = "SparkExecutorRunning" 52 | 53 | EventSparkExecutorCompleted = "SparkExecutorCompleted" 54 | 55 | EventSparkExecutorFailed = "SparkExecutorFailed" 56 | 57 | EventSparkExecutorUnknown = "SparkExecutorUnknown" 58 | ) 59 | -------------------------------------------------------------------------------- /pkg/common/metrics.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package common 18 | 19 | // Spark application metric names. 20 | const ( 21 | MetricSparkApplicationCount = "spark_application_count" 22 | 23 | MetricSparkApplicationSubmitCount = "spark_application_submit_count" 24 | 25 | MetricSparkApplicationFailedSubmissionCount = "spark_application_failed_submission_count" 26 | 27 | MetricSparkApplicationRunningCount = "spark_application_running_count" 28 | 29 | MetricSparkApplicationSuccessCount = "spark_application_success_count" 30 | 31 | MetricSparkApplicationFailureCount = "spark_application_failure_count" 32 | 33 | MetricSparkApplicationSuccessExecutionTimeSeconds = "spark_application_success_execution_time_seconds" 34 | 35 | MetricSparkApplicationFailureExecutionTimeSeconds = "spark_application_failure_execution_time_seconds" 36 | 37 | MetricSparkApplicationStartLatencySeconds = "spark_application_start_latency_seconds" 38 | 39 | MetricSparkApplicationStartLatencySecondsHistogram = "spark_application_start_latency_seconds_histogram" 40 | ) 41 | 42 | // Spark executor metric names. 43 | const ( 44 | MetricSparkExecutorRunningCount = "spark_executor_running_count" 45 | 46 | MetricSparkExecutorSuccessCount = "spark_executor_success_count" 47 | 48 | MetricSparkExecutorFailureCount = "spark_executor_failure_count" 49 | ) 50 | -------------------------------------------------------------------------------- /pkg/common/volcano.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package common 18 | 19 | const ( 20 | VolcanoSchedulerName = "volcano" 21 | 22 | VolcanoPodGroupName = "podgroups.scheduling.volcano.sh" 23 | ) 24 | -------------------------------------------------------------------------------- /pkg/util/capabilities.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 Google LLC 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | "strings" 21 | 22 | "github.com/golang/glog" 23 | "k8s.io/client-go/discovery" 24 | "k8s.io/client-go/kubernetes" 25 | ) 26 | 27 | type Capabilities map[string]bool 28 | 29 | func (c Capabilities) Has(wanted string) bool { 30 | return c[wanted] 31 | } 32 | 33 | func (c Capabilities) String() string { 34 | keys := make([]string, 0, len(c)) 35 | for k := range c { 36 | keys = append(keys, k) 37 | } 38 | return strings.Join(keys, ", ") 39 | } 40 | 41 | var ( 42 | IngressCapabilities Capabilities 43 | ) 44 | 45 | func InitializeIngressCapabilities(client kubernetes.Interface) (err error) { 46 | if IngressCapabilities != nil { 47 | return 48 | } 49 | 50 | IngressCapabilities, err = getPreferredAvailableAPIs(client, "Ingress") 51 | return 52 | } 53 | 54 | // getPreferredAvailableAPIs queries the cluster for the preferred resources information and returns a Capabilities 55 | // instance containing those api groups that support the specified kind. 56 | // 57 | // kind should be the title case singular name of the kind. For example, "Ingress" is the kind for a resource "ingress". 58 | func getPreferredAvailableAPIs(client kubernetes.Interface, kind string) (Capabilities, error) { 59 | discoveryclient := client.Discovery() 60 | lists, err := discoveryclient.ServerPreferredResources() 61 | if err != nil { 62 | if discovery.IsGroupDiscoveryFailedError(err) { 63 | glog.Infof("There is an orphaned API service. Server reports: %s", err) 64 | } else { 65 | return nil, err 66 | } 67 | } 68 | 69 | caps := Capabilities{} 70 | for _, list := range lists { 71 | if len(list.APIResources) == 0 { 72 | continue 73 | } 74 | for _, resource := range list.APIResources { 75 | if len(resource.Verbs) == 0 { 76 | continue 77 | } 78 | if resource.Kind == kind { 79 | caps[list.GroupVersion] = true 80 | } 81 | } 82 | } 83 | 84 | return caps, nil 85 | } 86 | -------------------------------------------------------------------------------- /pkg/util/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 Google LLC 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | // Package util contains utility code shared by other packages. 20 | -------------------------------------------------------------------------------- /pkg/util/metrics.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 Google LLC 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | "strings" 21 | ) 22 | 23 | func CreateValidMetricNameLabel(prefix, name string) string { 24 | // "-" is not a valid character for prometheus metric names or labels. 25 | return strings.ReplaceAll(prefix+name, "-", "_") 26 | } 27 | -------------------------------------------------------------------------------- /pkg/util/resourcequota.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | corev1 "k8s.io/api/core/v1" 21 | ) 22 | 23 | // SumResourceList sums the resource list. 24 | func SumResourceList(lists []corev1.ResourceList) corev1.ResourceList { 25 | total := corev1.ResourceList{} 26 | for _, list := range lists { 27 | for name, quantity := range list { 28 | if value, ok := total[name]; !ok { 29 | total[name] = quantity.DeepCopy() 30 | } else { 31 | value.Add(quantity) 32 | total[name] = value 33 | } 34 | } 35 | } 36 | return total 37 | } 38 | -------------------------------------------------------------------------------- /pkg/util/sparkpod.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | corev1 "k8s.io/api/core/v1" 21 | 22 | "github.com/kubeflow/spark-operator/v2/pkg/common" 23 | ) 24 | 25 | // IsLaunchedBySparkOperator returns whether the given pod is launched by the Spark Operator. 26 | func IsLaunchedBySparkOperator(pod *corev1.Pod) bool { 27 | return pod.Labels[common.LabelLaunchedBySparkOperator] == "true" 28 | } 29 | 30 | // IsDriverPod returns whether the given pod is a Spark driver Pod. 31 | func IsDriverPod(pod *corev1.Pod) bool { 32 | return pod.Labels[common.LabelSparkRole] == common.SparkRoleDriver 33 | } 34 | 35 | // IsExecutorPod returns whether the given pod is a Spark executor Pod. 36 | func IsExecutorPod(pod *corev1.Pod) bool { 37 | return pod.Labels[common.LabelSparkRole] == common.SparkRoleExecutor 38 | } 39 | 40 | // GetSparkExecutorID returns the Spark executor ID by checking out pod labels. 41 | func GetSparkExecutorID(pod *corev1.Pod) string { 42 | return pod.Labels[common.LabelSparkExecutorID] 43 | } 44 | 45 | // GetAppName returns the spark application name by checking out pod labels. 46 | func GetAppName(pod *corev1.Pod) string { 47 | return pod.Labels[common.LabelSparkAppName] 48 | } 49 | 50 | // GetConnName returns the spark connection name by checking out pod labels. 51 | func GetConnName(pod *corev1.Pod) string { 52 | return pod.Labels[common.LabelSparkConnectName] 53 | } 54 | 55 | // GetSparkApplicationID returns the spark application ID by checking out pod labels. 56 | func GetSparkApplicationID(pod *corev1.Pod) string { 57 | return pod.Labels[common.LabelSparkApplicationSelector] 58 | } 59 | 60 | func IsPodReady(pod *corev1.Pod) bool { 61 | for _, condition := range pod.Status.Conditions { 62 | if condition.Type == corev1.PodReady && condition.Status == corev1.ConditionTrue { 63 | return true 64 | } 65 | } 66 | return false 67 | } 68 | -------------------------------------------------------------------------------- /pkg/util/suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 The Kubeflow authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package util_test 18 | 19 | import ( 20 | "testing" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | 25 | "sigs.k8s.io/controller-runtime/pkg/log" 26 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 27 | ) 28 | 29 | func TestUtil(t *testing.T) { 30 | RegisterFailHandler(Fail) 31 | 32 | RunSpecs(t, "Util Suite") 33 | } 34 | 35 | var _ = BeforeSuite(func() { 36 | log.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) 37 | }) 38 | -------------------------------------------------------------------------------- /pkg/util/workqueue.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "time" 5 | 6 | "golang.org/x/time/rate" 7 | "k8s.io/client-go/util/workqueue" 8 | ) 9 | 10 | // This allow to create a new rate limiter while tuning the BucketRateLimiter parameters 11 | // This also prevent a "bug" in the BucketRateLimiter due to the fact that a BucketRateLimiter does not have a maxDelay parameter 12 | func NewRateLimiter[T comparable](qps int, bucketSize int, maxDelay time.Duration) workqueue.TypedRateLimiter[T] { 13 | return workqueue.NewTypedWithMaxWaitRateLimiter( 14 | workqueue.NewTypedMaxOfRateLimiter( 15 | workqueue.NewTypedItemExponentialFailureRateLimiter[T](5*time.Millisecond, 1000*time.Second), 16 | &workqueue.TypedBucketRateLimiter[T]{Limiter: rate.NewLimiter(rate.Limit(qps), bucketSize)}, 17 | ), maxDelay) 18 | } 19 | -------------------------------------------------------------------------------- /proposals/README.md: -------------------------------------------------------------------------------- 1 | # Proposals 2 | 3 | Kubeflow uses the KEP process to document large scale changes to the project. 4 | 5 | Details on the process (including the KEP template, recommendations, etc.) can be found at 6 | [kubeflow/community/proposals](https://github.com/kubeflow/community/blob/master/proposals/README.md) 7 | -------------------------------------------------------------------------------- /spark-docker/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2018 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | ARG SPARK_IMAGE=spark:3.5.5 18 | FROM ${SPARK_IMAGE} 19 | 20 | # Switch to user root so we can add additional jars and configuration files. 21 | USER root 22 | 23 | # Setup dependencies for Google Cloud Storage access. 24 | RUN rm $SPARK_HOME/jars/guava-14.0.1.jar 25 | ADD https://repo1.maven.org/maven2/com/google/guava/guava/23.0/guava-23.0.jar $SPARK_HOME/jars 26 | RUN chmod 644 $SPARK_HOME/jars/guava-23.0.jar 27 | # Add the connector jar needed to access Google Cloud Storage using the Hadoop FileSystem API. 28 | ADD https://storage.googleapis.com/hadoop-lib/gcs/gcs-connector-latest-hadoop2.jar $SPARK_HOME/jars 29 | RUN chmod 644 $SPARK_HOME/jars/gcs-connector-latest-hadoop2.jar 30 | ADD https://storage.googleapis.com/spark-lib/bigquery/spark-bigquery-latest_2.12.jar $SPARK_HOME/jars 31 | RUN chmod 644 $SPARK_HOME/jars/spark-bigquery-latest_2.12.jar 32 | 33 | # Setup for the Prometheus JMX exporter. 34 | # Add the Prometheus JMX exporter Java agent jar for exposing metrics sent to the JmxSink to Prometheus. 35 | ADD https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/0.11.0/jmx_prometheus_javaagent-0.11.0.jar /prometheus/ 36 | RUN chmod 644 /prometheus/jmx_prometheus_javaagent-0.11.0.jar 37 | 38 | USER ${spark_uid} 39 | 40 | RUN mkdir -p /etc/metrics/conf 41 | COPY conf/metrics.properties /etc/metrics/conf 42 | COPY conf/prometheus.yaml /etc/metrics/conf 43 | 44 | ENTRYPOINT ["/opt/entrypoint.sh"] 45 | -------------------------------------------------------------------------------- /spark-docker/README.md: -------------------------------------------------------------------------------- 1 | This directory contains a Dockerfile for a variant of the Spark image with built-in support for accessing Google Cloud Storage using the Hadoop FileSystem API and exposing Spark metrics (e.g., driver and executor metrics) to Prometheus in the Prometheus data model. The `conf` directory contains `metrics.properties` that configures the Spark metric system and `prometheus.yaml` that is the configuration file to be used with the [Prometheus JMX exporter](https://github.com/prometheus/jmx_exporter). 2 | 3 | By default both configuration files under `conf` are put under `/prometheus` in the image. To make Spark be aware of `metrics.properties`, please set the Spark configuration property `spark.metrics.conf=/prometheus/metrics.properties`. The Prometheus JMX exporter runs as a Java agent to scrape metrics exposed through JMX. To configure the Java agent for the exporter, add the following to the Spark configuration property `spark.driver.extraJavaOptions` for the driver (or `spark.executor.extraJavaOptions` for executors): 4 | 5 | ``` 6 | -javaagent:/prometheus/jmx_prometheus_javaagent-0.11.0.jar=8090:/prometheus/prometheus.yaml 7 | ``` 8 | 9 | The JMX exporter exposes a HTTP server serving the metrics on the specified port (`8090` in the example above). To make Prometheus discover and scrape the metrics, please add the following annotations to the Spark driver or executors. Make sure the value of `prometheus.io/port` is the same as the port specified in the Java agent configuration. 10 | 11 | ``` 12 | "prometheus.io/scrape": "true" 13 | "prometheus.io/port": "8090" 14 | "prometheus.io/path": "/metrics" 15 | ``` 16 | 17 | A complete example `SparkApplication` specification with metric exporting to Prometheus enabled can be found [here](../examples/spark-pi-prometheus.yaml). -------------------------------------------------------------------------------- /spark-docker/conf/metrics.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2018 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | *.sink.jmx.class=org.apache.spark.metrics.sink.JmxSink 18 | driver.source.jvm.class=org.apache.spark.metrics.source.JvmSource 19 | executor.source.jvm.class=org.apache.spark.metrics.source.JvmSource 20 | -------------------------------------------------------------------------------- /test/e2e/bad_examples/fail-application.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2024 The Kubeflow authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | apiVersion: sparkoperator.k8s.io/v1beta2 17 | kind: SparkApplication 18 | metadata: 19 | name: fail-submission 20 | namespace: default 21 | spec: 22 | type: Scala 23 | mode: cluster 24 | image: spark:4.0.0 25 | imagePullPolicy: IfNotPresent 26 | mainClass: non-existent 27 | mainApplicationFile: local:///non-existent.jar 28 | sparkVersion: 4.0.0 29 | restartPolicy: 30 | type: OnFailure 31 | onFailureRetries: 3 32 | onFailureRetryInterval: 1 33 | driver: 34 | labels: 35 | version: 4.0.0 36 | cores: 1 37 | memory: 512m 38 | serviceAccount: spark-operator-spark 39 | executor: 40 | labels: 41 | version: 4.0.0 42 | instances: 1 43 | cores: 1 44 | memory: 512m 45 | -------------------------------------------------------------------------------- /test/e2e/bad_examples/fail-submission.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2024 The Kubeflow authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | apiVersion: sparkoperator.k8s.io/v1beta2 17 | kind: SparkApplication 18 | metadata: 19 | name: fail-submission 20 | namespace: default 21 | spec: 22 | type: Scala 23 | mode: cluster 24 | image: spark:4.0.0 25 | imagePullPolicy: IfNotPresent 26 | mainClass: dummy 27 | mainApplicationFile: local:///dummy.jar 28 | sparkVersion: 4.0.0 29 | restartPolicy: 30 | type: OnFailure 31 | onSubmissionFailureRetries: 3 32 | onSubmissionFailureRetryInterval: 1 33 | driver: 34 | labels: 35 | version: 4.0.0 36 | cores: 1 37 | memory: 512m 38 | serviceAccount: non-existent # This is the important part that causes submission to fail. 39 | executor: 40 | labels: 41 | version: 4.0.0 42 | instances: 1 43 | cores: 1 44 | memory: 512m 45 | --------------------------------------------------------------------------------