├── .github ├── mergify.yml └── workflows │ └── container-image.yml ├── .gitignore ├── .gitlint ├── .yamllint.yaml ├── LICENSE ├── Makefile ├── Makefile.opensuse ├── README.md ├── docs ├── development.md ├── release-process.md └── server.md ├── examples ├── kubernetes │ ├── README.md │ ├── pv.yml │ ├── pvc.yml │ ├── samba-ad-server-deployment.yml │ ├── samba-ctdb-dm-sset.yml │ ├── samba-ctdb-sset.yml │ ├── sambadeployment.converged.yml │ ├── sambadeployment.yml │ ├── sambadmpod.yml │ └── sambapod.yml └── podman │ ├── README.md │ ├── config.json │ └── smb-wb-pod.sh ├── hack ├── build-image ├── install-tools.sh └── release-gen-download-section.sh ├── images ├── ad-server │ ├── Containerfile.centos │ ├── Containerfile.fedora │ ├── Containerfile.opensuse │ ├── install-packages.sh │ └── install-sambacc.sh ├── client │ ├── Containerfile.centos │ ├── Containerfile.fedora │ └── Containerfile.opensuse ├── common │ └── install-sambacc-common.sh ├── server │ ├── Containerfile.centos │ ├── Containerfile.fedora │ ├── Containerfile.opensuse │ ├── install-packages.sh │ ├── install-sambacc.sh │ └── smb.conf └── toolbox │ ├── Containerfile.centos │ ├── Containerfile.fedora │ └── Containerfile.opensuse └── tests ├── common.sh ├── files ├── coredns-snippet.template ├── samba-ad-server-deployment.yml └── samba-domain-member-pod.yml ├── test-deploy-ad-member.sh ├── test-deploy-ad-server.sh ├── test-remove-ad-member.sh ├── test-remove-ad-server.sh ├── test-samba-ad-server-kubernetes.sh └── test-samba-container.sh /.github/mergify.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # each test should be listed separately, do not use regular expressions: 3 | # https://docs.mergify.io/conditions.html#validating-all-status-check 4 | # TODO: Use mergify's recently added 'shared configuration support' 5 | # to dedup some of the check-x=y repetition in the future. 6 | queue_rules: 7 | - name: default 8 | conditions: 9 | - check-success=checks 10 | - check-success=check-commits 11 | - check-success=build-server (default, centos, amd64) 12 | - check-success=build-server (default, fedora, amd64) 13 | - check-success=build-server (default, opensuse, amd64) 14 | - check-success=build-server (nightly, centos, amd64) 15 | - check-success=build-server (nightly, fedora, amd64) 16 | - check-success=build-ad-server (default, fedora, amd64) 17 | - check-success=build-ad-server (default, opensuse, amd64) 18 | - check-success=build-ad-server (nightly, centos, amd64) 19 | - check-success=build-ad-server (nightly, fedora, amd64) 20 | - check-success=build-client (centos, amd64) 21 | - check-success=build-client (fedora, amd64) 22 | - check-success=build-client (opensuse, amd64) 23 | - check-success=build-toolbox (centos, amd64) 24 | - check-success=build-toolbox (fedora, amd64) 25 | - check-success=build-toolbox (opensuse, amd64) 26 | - check-success=test-server (default, centos, amd64) 27 | - check-success=test-server (default, fedora, amd64) 28 | - check-success=test-server (default, opensuse, amd64) 29 | - check-success=test-server (nightly, centos, amd64) 30 | - check-success=test-server (nightly, fedora, amd64) 31 | - check-success=test-ad-server-kubernetes (default, fedora, amd64) 32 | - check-success=test-ad-server-kubernetes (default, opensuse, amd64) 33 | - check-success=test-ad-server-kubernetes (nightly, centos, amd64) 34 | - check-success=test-ad-server-kubernetes (nightly, fedora, amd64) 35 | - check-success=dpulls 36 | merge_method: rebase 37 | update_method: rebase 38 | 39 | 40 | pull_request_rules: 41 | # Clearing approvals after content changes 42 | - name: Remove outdated approvals 43 | conditions: 44 | - base=master 45 | actions: 46 | dismiss_reviews: 47 | approved: true 48 | changes_requested: false 49 | # Perform automatic merge on conditions 50 | - name: Automatic merge on approval 51 | conditions: 52 | - check-success=checks 53 | - check-success=check-commits 54 | - check-success=build-server (default, centos, amd64) 55 | - check-success=build-server (default, fedora, amd64) 56 | - check-success=build-server (default, opensuse, amd64) 57 | - check-success=build-server (nightly, centos, amd64) 58 | - check-success=build-server (nightly, fedora, amd64) 59 | - check-success=build-ad-server (default, fedora, amd64) 60 | - check-success=build-ad-server (default, opensuse, amd64) 61 | - check-success=build-ad-server (nightly, centos, amd64) 62 | - check-success=build-ad-server (nightly, fedora, amd64) 63 | - check-success=build-client (centos, amd64) 64 | - check-success=build-client (fedora, amd64) 65 | - check-success=build-client (opensuse, amd64) 66 | - check-success=build-toolbox (centos, amd64) 67 | - check-success=build-toolbox (fedora, amd64) 68 | - check-success=build-toolbox (opensuse, amd64) 69 | - check-success=test-server (default, centos, amd64) 70 | - check-success=test-server (default, fedora, amd64) 71 | - check-success=test-server (default, opensuse, amd64) 72 | - check-success=test-server (nightly, centos, amd64) 73 | - check-success=test-server (nightly, fedora, amd64) 74 | - check-success=test-ad-server-kubernetes (default, fedora, amd64) 75 | - check-success=test-ad-server-kubernetes (default, opensuse, amd64) 76 | - check-success=test-ad-server-kubernetes (nightly, centos, amd64) 77 | - check-success=test-ad-server-kubernetes (nightly, fedora, amd64) 78 | - check-success=dpulls 79 | - "-draft" 80 | # Contributors should set the 'do-not-merge' label if they don't want 81 | # the PR to be (auto)merged for some reason. 82 | - "label!=do-not-merge" 83 | # A reviewer should set a label starting with 'review-in-progress' (and 84 | # suffixed by their username) in order to indicate a detailed review has 85 | # been started and not completed. This will hold the PR until the 86 | # label has been removed. 87 | - "-label~=^review-in-progress" 88 | - "base=master" 89 | # Even if there are 2 or more approvals we won't automerge if there are 90 | # any changes requested. 91 | - "#changes-requested-reviews-by=0" 92 | - or: 93 | # Any contributor's PR can be automerged with 2 (or more) reviews. 94 | - "#approved-reviews-by>=2" 95 | # A maintainer's contribution that has already aged long enough to 96 | # earn the "priority-review" label can be merged immediately. 97 | # The label can also be applied manually in case of an important 98 | # bugfix, etc. 99 | - and: 100 | - "label=priority-review" 101 | - "author=@maintainers" 102 | - "#approved-reviews-by>=1" 103 | actions: 104 | queue: {} 105 | dismiss_reviews: {} 106 | # Conflict resolution prompt 107 | - name: Ask contributor to resolve a conflict 108 | conditions: 109 | - conflict 110 | actions: 111 | comment: 112 | message: "This pull request now has conflicts with the target branch. 113 | Please resolve these conflicts and force push the updated branch." 114 | # Label PRs that have been sitting there unchanged, aging like a fine wine 115 | # 116 | # NOTE: the updated-at "counter" resets every time the PR is changed so 117 | # reacting to a reviewer's feedback and fixing a typo (for example) will 118 | # reset the counter. Thus we now apply a label once we hit the 15 day window 119 | # so that we know that PR had, at some time, sat unchanged for that long. 120 | - name: Label aged PRs 121 | conditions: 122 | - "updated-at<15 days ago" 123 | - "-draft" 124 | actions: 125 | label: 126 | add: 127 | - "priority-review" 128 | -------------------------------------------------------------------------------- /.github/workflows/container-image.yml: -------------------------------------------------------------------------------- 1 | name: Samba Container Image CI 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | pull_request: 7 | branches: [master] 8 | schedule: 9 | - cron: '0 2 * * *' 10 | # Allow manually triggering a run in the github ui. 11 | # See: https://docs.github.com/en/actions/using-workflows/manually-running-a-workflow 12 | workflow_dispatch: {} 13 | 14 | env: 15 | CONTAINER_CMD: docker 16 | jobs: 17 | checks: 18 | runs-on: ubuntu-latest 19 | steps: 20 | - uses: actions/checkout@v4 21 | # We need a newer version of shellcheck to avoid problems with the 22 | # relative imports. Our scripts work on v0.7.2 and up but not the 23 | # v0.7.0 preinstalled in the ubutnu image. We can force a local 24 | # install by expliclity setting SHELLCHECK to `$ALT_BIN/shellcheck` 25 | - name: Run static check tools 26 | run: make check SHELLCHECK=$PWD/.bin/shellcheck 27 | 28 | check-commits: 29 | runs-on: ubuntu-latest 30 | if: github.event_name == 'pull_request' 31 | steps: 32 | - uses: actions/checkout@v4 33 | with: 34 | fetch-depth: 0 35 | ref: ${{ github.event.pull_request.head.sha }} 36 | - name: Ensure branches 37 | run: git fetch 38 | - name: Lint git commit messages 39 | run: make check-gitlint 40 | 41 | build-server: 42 | # Reminder: the nightly-server images consume nightly samba rpm builds 43 | # it is not *just* an image that gets built nightly 44 | strategy: 45 | matrix: 46 | package_source: [default, nightly] 47 | os: [centos, fedora, opensuse] 48 | arch: [amd64, arm64] 49 | exclude: 50 | # there are no nightly packages for opensuse 51 | - package_source: nightly 52 | os: opensuse 53 | - os: centos 54 | arch: arm64 55 | include: 56 | - package_source: devbuilds 57 | os: centos 58 | arch: amd64 59 | runs-on: ubuntu-latest 60 | env: 61 | BUILDAH_FORMAT: oci 62 | IMG_TAG: ${{ matrix.package_source }}-${{ matrix.os }}-${{ matrix.arch }} 63 | steps: 64 | - uses: actions/checkout@v4 65 | - name: Build the server image 66 | run: make KIND=server PACKAGE_SOURCE=${{ matrix.package_source }} OS_NAME=${{ matrix.os}} BUILD_ARCH=${{ matrix.arch}} build-image 67 | - name: Upload server image 68 | uses: ishworkh/container-image-artifact-upload@v2.0.0 69 | with: 70 | image: "samba-server:${{ env.IMG_TAG }}" 71 | container_engine: ${{ env.CONTAINER_CMD }} 72 | retention_days: 1 73 | 74 | build-ad-server: 75 | strategy: 76 | matrix: 77 | package_source: [default, nightly] 78 | os: [centos, fedora, opensuse] 79 | arch: [amd64, arm64] 80 | exclude: 81 | # there are no nightly packages for opensuse 82 | - package_source: nightly 83 | os: opensuse 84 | # the distro packages for centos do not include an ad-dc 85 | - package_source: default 86 | os: centos 87 | - os: centos 88 | arch: arm64 89 | runs-on: ubuntu-latest 90 | env: 91 | BUILDAH_FORMAT: oci 92 | IMG_TAG: ${{ matrix.package_source }}-${{ matrix.os }}-${{ matrix.arch }} 93 | steps: 94 | - uses: actions/checkout@v4 95 | - name: Build the ad server image 96 | run: make KIND=ad-server PACKAGE_SOURCE=${{ matrix.package_source }} OS_NAME=${{ matrix.os }} BUILD_ARCH=${{ matrix.arch }} build-image 97 | - name: Upload ad server image 98 | uses: ishworkh/container-image-artifact-upload@v2.0.0 99 | with: 100 | image: "samba-ad-server:${{ env.IMG_TAG }}" 101 | container_engine: ${{ env.CONTAINER_CMD }} 102 | retention_days: 1 103 | 104 | build-client: 105 | strategy: 106 | matrix: 107 | os: [centos, fedora, opensuse] 108 | arch: [amd64, arm64] 109 | exclude: 110 | - os: centos 111 | arch: arm64 112 | runs-on: ubuntu-latest 113 | env: 114 | BUILDAH_FORMAT: oci 115 | IMG_TAG: default-${{ matrix.os }}-${{ matrix.arch }} 116 | steps: 117 | - uses: actions/checkout@v4 118 | - name: build the client image 119 | run: make KIND=client OS_NAME=${{ matrix.os }} BUILD_ARCH=${{ matrix.arch }} build-image 120 | # The client image is used as a base for the samba-toolbox build process. 121 | - name: Upload the client image 122 | uses: ishworkh/container-image-artifact-upload@v2.0.0 123 | with: 124 | image: "samba-client:${{ env.IMG_TAG }}" 125 | container_engine: ${{ env.CONTAINER_CMD }} 126 | retention_days: 1 127 | 128 | build-toolbox: 129 | strategy: 130 | matrix: 131 | os: [centos, fedora, opensuse] 132 | arch: [amd64] 133 | needs: build-client 134 | runs-on: ubuntu-latest 135 | env: 136 | BUILDAH_FORMAT: oci 137 | IMG_TAG: default-${{ matrix.os }}-${{ matrix.arch }} 138 | steps: 139 | - uses: actions/checkout@v4 140 | # Download locally stored samba-client image to be used as base for building 141 | # samba-toolbox. 142 | - name: Download client image 143 | uses: ishworkh/container-image-artifact-download@v2.0.0 144 | with: 145 | image: "samba-client:${{ env.IMG_TAG }}" 146 | container_engine: ${{ env.CONTAINER_CMD }} 147 | # Workaround: retag the image so that the FQIN image matches the name in 148 | # the toolbox containerfiles. 149 | - name: Apply OS-latest tag to image (for centos) 150 | run: ${{ env.CONTAINER_CMD }} tag samba-client:${{ env.IMG_TAG }} quay.io/samba.org/samba-client:${{ matrix.os }}-latest 151 | - name: Apply latest tag to image (for fedora) 152 | run: ${{ env.CONTAINER_CMD }} tag samba-client:${{ env.IMG_TAG }} quay.io/samba.org/samba-client:latest 153 | - name: Build the toolbox image 154 | run: make KIND=toolbox OS_NAME=${{ matrix.os }} BUILD_ARCH=${{ matrix.arch }} build-image 155 | # Upload the toolbox image for reference and/or image push 156 | - name: Upload the toolbox image 157 | uses: ishworkh/container-image-artifact-upload@v2.0.0 158 | with: 159 | image: "samba-toolbox:${{ env.IMG_TAG }}" 160 | container_engine: ${{ env.CONTAINER_CMD }} 161 | retention_days: 1 162 | 163 | test-server: 164 | strategy: 165 | matrix: 166 | package_source: [default, nightly] 167 | os: [centos, fedora, opensuse] 168 | arch: [amd64] 169 | exclude: 170 | # there are no nightly packages for opensuse 171 | - package_source: nightly 172 | os: opensuse 173 | include: 174 | - package_source: devbuilds 175 | os: centos 176 | arch: amd64 177 | needs: build-server 178 | runs-on: ubuntu-latest 179 | env: 180 | BUILDAH_FORMAT: oci 181 | IMG_TAG: ${{ matrix.package_source }}-${{ matrix.os }}-${{ matrix.arch }} 182 | steps: 183 | - uses: actions/checkout@v4 184 | - name: Download server image 185 | uses: ishworkh/container-image-artifact-download@v2.0.0 186 | with: 187 | image: "samba-server:${{ env.IMG_TAG }}" 188 | container_engine: ${{ env.CONTAINER_CMD }} 189 | - name: Test the server image 190 | run: LOCAL_TAG=samba-server:${{ env.IMG_TAG }} tests/test-samba-container.sh 191 | 192 | test-ad-server-kubernetes: 193 | strategy: 194 | matrix: 195 | package_source: [default, nightly] 196 | os: [centos, fedora, opensuse] 197 | arch: [amd64] 198 | exclude: 199 | # there are no nightly packages for opensuse 200 | - package_source: nightly 201 | os: opensuse 202 | # the distro packages for centos do not include an ad-dc 203 | - package_source: default 204 | os: centos 205 | needs: 206 | - build-ad-server 207 | - build-server 208 | runs-on: ubuntu-latest 209 | env: 210 | BUILDAH_FORMAT: oci 211 | IMG_TAG: ${{ matrix.package_source }}-${{ matrix.os }}-${{ matrix.arch }} 212 | steps: 213 | - uses: actions/checkout@v4 214 | - uses: nolar/setup-k3d-k3s@v1 215 | - name: get nodes 216 | run: kubectl get nodes 217 | - name: Download ad server image 218 | uses: ishworkh/container-image-artifact-download@v2.0.0 219 | with: 220 | image: "samba-ad-server:${{ env.IMG_TAG }}" 221 | container_engine: ${{ env.CONTAINER_CMD }} 222 | - name: Download file server image 223 | uses: ishworkh/container-image-artifact-download@v2.0.0 224 | with: 225 | image: "samba-server:${{ env.IMG_TAG }}" 226 | container_engine: ${{ env.CONTAINER_CMD }} 227 | - name: import images to k3d 228 | run: k3d image import samba-server:${{ env.IMG_TAG }} samba-ad-server:${{ env.IMG_TAG }} 229 | - name: run the ad-dc deployment test 230 | run: ./tests/test-samba-ad-server-kubernetes.sh 231 | 232 | push: 233 | # verify it passes the test jobs first 234 | needs: 235 | - build-client 236 | - build-toolbox 237 | - test-server 238 | - test-ad-server-kubernetes 239 | runs-on: ubuntu-latest 240 | env: 241 | REPO_BASE: quay.io/samba.org 242 | # NOTE: the fromJSON below is needed beause the syntax github uses 243 | # doesn't actually understand JS/JSON style arrays (inline). When I left it 244 | # out I just got an error. It is present in their example(s). 245 | if: > 246 | contains(fromJSON('["push", "schedule", "workflow_dispatch"]'), github.event_name) 247 | && github.repository == 'samba-in-kubernetes/samba-container' 248 | steps: 249 | - uses: actions/checkout@v4 250 | - name: log in to quay.io 251 | run: ${CONTAINER_CMD} login -u "${{ secrets.QUAY_USER }}" -p "${{ secrets.QUAY_PASS }}" quay.io 252 | # pull in already built images we plan on pushing 253 | # (server images) 254 | - name: Fetch server default-fedora-amd64 255 | uses: ishworkh/container-image-artifact-download@v2.0.0 256 | with: 257 | image: "samba-server:default-fedora-amd64" 258 | container_engine: ${{ env.CONTAINER_CMD }} 259 | - name: Fetch server default-fedora-arm64 260 | uses: ishworkh/container-image-artifact-download@v2.0.0 261 | with: 262 | image: "samba-server:default-fedora-arm64" 263 | container_engine: ${{ env.CONTAINER_CMD }} 264 | - name: Fetch server default-opensuse-arm64 265 | uses: ishworkh/container-image-artifact-download@v2.0.0 266 | with: 267 | image: "samba-server:default-opensuse-arm64" 268 | container_engine: ${{ env.CONTAINER_CMD }} 269 | - name: Fetch server nightly-fedora-amd64 270 | uses: ishworkh/container-image-artifact-download@v2.0.0 271 | with: 272 | image: "samba-server:nightly-fedora-amd64" 273 | container_engine: ${{ env.CONTAINER_CMD }} 274 | - name: Fetch server nightly-fedora-arm64 275 | uses: ishworkh/container-image-artifact-download@v2.0.0 276 | with: 277 | image: "samba-server:nightly-fedora-arm64" 278 | container_engine: ${{ env.CONTAINER_CMD }} 279 | - name: Fetch server nightly-centos-amd64 280 | uses: ishworkh/container-image-artifact-download@v2.0.0 281 | with: 282 | image: "samba-server:nightly-centos-amd64" 283 | container_engine: ${{ env.CONTAINER_CMD }} 284 | - name: Fetch server devbuilds-centos-amd64 285 | uses: ishworkh/container-image-artifact-download@v2.0.0 286 | with: 287 | image: "samba-server:devbuilds-centos-amd64" 288 | container_engine: ${{ env.CONTAINER_CMD }} 289 | # (ad server images) 290 | - name: Fetch ad-server default-fedora-amd64 291 | uses: ishworkh/container-image-artifact-download@v2.0.0 292 | with: 293 | image: "samba-ad-server:default-fedora-amd64" 294 | container_engine: ${{ env.CONTAINER_CMD }} 295 | - name: Fetch ad-server default-fedora-arm64 296 | uses: ishworkh/container-image-artifact-download@v2.0.0 297 | with: 298 | image: "samba-ad-server:default-fedora-arm64" 299 | container_engine: ${{ env.CONTAINER_CMD }} 300 | - name: Fetch ad-server default-opensuse-arm64 301 | uses: ishworkh/container-image-artifact-download@v2.0.0 302 | with: 303 | image: "samba-ad-server:default-opensuse-arm64" 304 | container_engine: ${{ env.CONTAINER_CMD }} 305 | - name: Fetch ad-server nightly-fedora-amd64 306 | uses: ishworkh/container-image-artifact-download@v2.0.0 307 | with: 308 | image: "samba-ad-server:nightly-fedora-amd64" 309 | container_engine: ${{ env.CONTAINER_CMD }} 310 | - name: Fetch ad-server nightly-fedora-arm64 311 | uses: ishworkh/container-image-artifact-download@v2.0.0 312 | with: 313 | image: "samba-ad-server:nightly-fedora-arm64" 314 | container_engine: ${{ env.CONTAINER_CMD }} 315 | # (client images) 316 | - name: Fetch client default-fedora-amd64 317 | uses: ishworkh/container-image-artifact-download@v2.0.0 318 | with: 319 | image: "samba-client:default-fedora-amd64" 320 | container_engine: ${{ env.CONTAINER_CMD }} 321 | - name: Fetch client default-fedora-arm64 322 | uses: ishworkh/container-image-artifact-download@v2.0.0 323 | with: 324 | image: "samba-client:default-fedora-arm64" 325 | container_engine: ${{ env.CONTAINER_CMD }} 326 | - name: Fetch client default-opensuse-arm64 327 | uses: ishworkh/container-image-artifact-download@v2.0.0 328 | with: 329 | image: "samba-client:default-opensuse-arm64" 330 | container_engine: ${{ env.CONTAINER_CMD }} 331 | # (toolbox images) 332 | - name: Fetch toolbox default-fedora-amd64 333 | uses: ishworkh/container-image-artifact-download@v2.0.0 334 | with: 335 | image: "samba-toolbox:default-fedora-amd64" 336 | container_engine: ${{ env.CONTAINER_CMD }} 337 | # reapply missing tags 338 | - name: Retag images 339 | run: > 340 | ./hack/build-image 341 | --retag 342 | --container-engine=${CONTAINER_CMD} 343 | --repo-base=${REPO_BASE} 344 | --no-distro-qualified 345 | -i samba-server:default-fedora-amd64 346 | -i samba-server:default-fedora-arm64 347 | -i samba-server:default-opensuse-arm64 348 | -i samba-server:nightly-fedora-amd64 349 | -i samba-server:nightly-fedora-arm64 350 | -i samba-server:nightly-centos-amd64 351 | -i samba-server:devbuilds-centos-amd64 352 | -i samba-ad-server:default-fedora-amd64 353 | -i samba-ad-server:default-fedora-arm64 354 | -i samba-ad-server:default-opensuse-arm64 355 | -i samba-ad-server:nightly-fedora-amd64 356 | -i samba-ad-server:nightly-fedora-arm64 357 | -i samba-client:default-fedora-amd64 358 | -i samba-client:default-fedora-arm64 359 | -i samba-client:default-opensuse-arm64 360 | -i samba-toolbox:default-fedora-amd64 361 | - name: Push images 362 | run: > 363 | ./hack/build-image 364 | --push 365 | --container-engine=${CONTAINER_CMD} 366 | --verbose 367 | --push-state=exists 368 | --push-selected-tags=mixed 369 | -i ${REPO_BASE}/samba-server:default-fedora-amd64 370 | -i ${REPO_BASE}/samba-server:default-fedora-arm64 371 | -i ${REPO_BASE}/samba-server:default-opensuse-arm64 372 | -i ${REPO_BASE}/samba-server:nightly-fedora-amd64 373 | -i ${REPO_BASE}/samba-server:nightly-centos-amd64 374 | -i ${REPO_BASE}/samba-server:devbuilds-centos-amd64 375 | -i ${REPO_BASE}/samba-ad-server:default-fedora-amd64 376 | -i ${REPO_BASE}/samba-ad-server:default-fedora-arm64 377 | -i ${REPO_BASE}/samba-ad-server:default-opensuse-arm64 378 | -i ${REPO_BASE}/samba-ad-server:nightly-fedora-amd64 379 | -i ${REPO_BASE}/samba-client:default-fedora-amd64 380 | -i ${REPO_BASE}/samba-client:default-fedora-arm64 381 | -i ${REPO_BASE}/samba-client:default-opensuse-arm64 382 | -i ${REPO_BASE}/samba-toolbox:default-fedora-amd64 383 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | .build.server 3 | .build.opensuse-server 4 | .build.ad-server 5 | .build.opensuse-ad-server 6 | .build.client 7 | .build.opensuse-client 8 | .build.toolbox 9 | .build.opensuse-toolbox 10 | .build.nightly.server 11 | .build.nightly.ad-server 12 | .common 13 | .bin 14 | -------------------------------------------------------------------------------- /.gitlint: -------------------------------------------------------------------------------- 1 | # Edit this file as you like. 2 | # 3 | # All these sections are optional. Each section with the exception of [general] represents 4 | # one rule and each key in it is an option for that specific rule. 5 | # 6 | # Rules and sections can be referenced by their full name or by id. For example 7 | # section "[body-max-line-length]" could also be written as "[B1]". Full section names are 8 | # used in here for clarity. 9 | # 10 | [general] 11 | # Ignore certain rules, this example uses both full name and id 12 | # ignore=title-trailing-punctuation, T3 13 | 14 | # verbosity should be a value between 1 and 3, the commandline -v flags take precedence over this 15 | verbosity=3 16 | 17 | # By default gitlint will ignore merge, revert, fixup and squash commits. 18 | ignore-merge-commits=true 19 | # ignore-revert-commits=true 20 | # ignore-fixup-commits=true 21 | # ignore-squash-commits=true 22 | 23 | # Ignore any data send to gitlint via stdin 24 | # ignore-stdin=true 25 | 26 | # Fetch additional meta-data from the local repository when manually passing a 27 | # commit message to gitlint via stdin or --commit-msg. Disabled by default. 28 | # staged=true 29 | 30 | # Enable debug mode (prints more output). Disabled by default. 31 | # debug=true 32 | 33 | # Enable search regex and remove warning message. 34 | regex-style-search=true 35 | 36 | # Enable community contributed rules 37 | # See http://jorisroovers.github.io/gitlint/contrib_rules for details 38 | # contrib=contrib-body-requires-signed-off-by 39 | 40 | # Set the extra-path where gitlint will search for user defined rules 41 | # See http://jorisroovers.github.io/gitlint/user_defined_rules for details 42 | # extra-path=examples/ 43 | 44 | # This is an example of how to configure the "title-max-length" rule and 45 | # set the line-length it enforces to 80 46 | [title-max-length] 47 | line-length=72 48 | 49 | # Conversely, you can also enforce minimal length of a title with the 50 | # "title-min-length" rule: 51 | # [title-min-length] 52 | # min-length=5 53 | 54 | [title-must-not-contain-word] 55 | # Comma-separated list of words that should not occur in the title. Matching is case 56 | # insensitive. It's fine if the keyword occurs as part of a larger word (so "WIPING" 57 | # will not cause a violation, but "WIP: my title" will. 58 | words=wip,WIP 59 | 60 | [title-match-regex] 61 | # python-style regex that the commit-msg title must match 62 | # Note that the regex can contradict with other rules if not used correctly 63 | # (e.g. title-must-not-contain-word). 64 | regex=^.* 65 | 66 | # [body-max-line-length] 67 | # line-length=72 68 | 69 | # [body-min-length] 70 | # min-length=5 71 | 72 | # [body-is-missing] 73 | # Whether to ignore this rule on merge commits (which typically only have a title) 74 | # default = True 75 | # ignore-merge-commits=false 76 | 77 | # [body-changed-file-mention] 78 | # List of files that need to be explicitly mentioned in the body when they are changed 79 | # This is useful for when developers often erroneously edit certain files or git submodules. 80 | # By specifying this rule, developers can only change the file when they explicitly reference 81 | # it in the commit message. 82 | # files=gitlint/rules.py,README.md 83 | 84 | # [body-match-regex] 85 | # python-style regex that the commit-msg body must match. 86 | # E.g. body must end in My-Commit-Tag: foo 87 | # regex=My-Commit-Tag: foo$ 88 | 89 | # [author-valid-email] 90 | # python-style regex that the commit author email address must match. 91 | # For example, use the following regex if you only want to allow email addresses from foo.com 92 | # regex=[^@]+@foo.com 93 | 94 | # [ignore-by-title] 95 | # Ignore certain rules for commits of which the title matches a regex 96 | # E.g. Match commit titles that start with "Release" 97 | # regex=^Release(.*) 98 | 99 | # Ignore certain rules, you can reference them by their id or by their full name 100 | # Use 'all' to ignore all rules 101 | # ignore=T1,body-min-length 102 | 103 | # [ignore-by-body] 104 | # Ignore certain rules for commits of which the body has a line that matches a regex 105 | # E.g. Match bodies that have a line that that contain "release" 106 | # regex=(.*)release(.*) 107 | # 108 | # Ignore certain rules, you can reference them by their id or by their full name 109 | # Use 'all' to ignore all rules 110 | # ignore=T1,body-min-length 111 | 112 | [ignore-body-lines] 113 | # Ignore certain lines in a commit body that match a regex. 114 | # E.g. Ignore all lines that start with 'Co-Authored-By' 115 | # regex=^Co-Authored-By 116 | 117 | # ignore lines that are "footnotes", that start like `[1]: ` or `[2]: ` and so on 118 | # this will make it easy to put long urls in commit messages without 119 | # triggering gitlint body rules 120 | regex=^\[[0-9]+\]:? + 121 | 122 | # This is a contrib rule - a community contributed rule. These are disabled by default. 123 | # You need to explicitly enable them one-by-one by adding them to the "contrib" option 124 | # under [general] section above. 125 | # [contrib-title-conventional-commits] 126 | # Specify allowed commit types. For details see: https://www.conventionalcommits.org/ 127 | # types = bugfix,user-story,epic 128 | -------------------------------------------------------------------------------- /.yamllint.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | extends: default 3 | yaml-files: 4 | - '*.yaml' 5 | - '*.yml' 6 | - '.yamllint' 7 | ignore: | 8 | vendor 9 | rules: 10 | braces: enable 11 | brackets: enable 12 | colons: enable 13 | commas: enable 14 | comments: disable 15 | comments-indentation: 16 | level: warning 17 | document-end: disable 18 | document-start: disable 19 | empty-lines: 20 | max-start: 1 21 | level: warning 22 | empty-values: disable 23 | hyphens: enable 24 | indentation: 25 | level: warning 26 | key-duplicates: enable 27 | key-ordering: disable 28 | line-length: disable 29 | new-line-at-end-of-file: enable 30 | new-lines: enable 31 | octal-values: enable 32 | quoted-strings: disable 33 | trailing-spaces: enable 34 | truthy: 35 | level: warning 36 | allowed-values: ['true', 'false', 'on'] 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SELF = $(lastword $(MAKEFILE_LIST)) 2 | ROOT_DIR = $(realpath $(dir $(SELF))) 3 | 4 | CONTAINER_CMD ?= 5 | 6 | ALT_BIN=$(CURDIR)/.bin 7 | SHELLCHECK=$(shell command -v shellcheck || echo $(ALT_BIN)/shellcheck) 8 | GITLINT=$(shell command -v gitlint || echo $(ALT_BIN)/gitlint) 9 | YAMLLINT_CMD=$(shell command -v yamllint || echo $(ALT_BIN)/yamllint) 10 | BUILD_IMAGE=$(ROOT_DIR)/hack/build-image --without-repo-bases 11 | 12 | 13 | SERVER_DIR:=images/server 14 | AD_SERVER_DIR:=images/ad-server 15 | CLIENT_DIR:=images/client 16 | TOOLBOX_DIR:=images/toolbox 17 | 18 | OS_NAME= 19 | SRC_OS_NAME=$(if $(OS_NAME),$(OS_NAME),fedora) 20 | 21 | SERVER_SRC_FILE=$(SERVER_DIR)/Containerfile.$(SRC_OS_NAME) 22 | SERVER_SOURCES=\ 23 | $(SERVER_DIR)/smb.conf \ 24 | $(SERVER_DIR)/install-packages.sh \ 25 | $(SERVER_DIR)/install-sambacc.sh 26 | AD_SERVER_SRC_FILE=$(AD_SERVER_DIR)/Containerfile.$(SRC_OS_NAME) 27 | AD_SERVER_SOURCES=\ 28 | $(AD_SERVER_DIR)/install-packages.sh \ 29 | $(AD_SERVER_DIR)/install-sambacc.sh 30 | CLIENT_SRC_FILE=$(CLIENT_DIR)/Containerfile.$(SRC_OS_NAME) 31 | TOOLBOX_SRC_FILE=$(TOOLBOX_DIR)/Containerfile.$(SRC_OS_NAME) 32 | 33 | BUILDFILE_PREFIX=.build 34 | BUILDFILE_SERVER=$(shell $(call _BUILD_KP,server,default,--print-buildfile)) 35 | BUILDFILE_NIGHTLY_SERVER=$(shell $(call _BUILD_KP,server,nightly,--print-buildfile)) 36 | BUILDFILE_AD_SERVER=$(shell $(call _BUILD_KP,ad-server,default,--print-buildfile)) 37 | BUILDFILE_NIGHTLY_AD_SERVER=$(shell $(call _BUILD_KP,ad-server,nightly,--print-buildfile)) 38 | BUILDFILE_CLIENT=$(shell $(call _BUILD_KP,client,default,--print-buildfile)) 39 | BUILDFILE_TOOLBOX=$(shell $(call _BUILD_KP,toolbox,default,--print-buildfile)) 40 | DYN_BUILDFILE=$(shell $(call _BUILD_KP,$(KIND),$(if $(PACKAGE_SOURCE),$(PACKAGE_SOURCE),default),--print-buildfile) 2>/dev/null || echo invalid) 41 | 42 | REPO_BASE=quay.io/samba.org/ 43 | 44 | _BUILD_KP=$(BUILD_IMAGE) $(if $(CONTAINER_CMD),--container-engine=$(CONTAINER_CMD)) $(BI_PREFIX_ARGS) --kind=$1 --package-source=$2 --distro-base=$(SRC_OS_NAME) --repo-base=$(REPO_BASE) $(if $(BUILD_ARCH),--arch=$(BUILD_ARCH)) $3 45 | 46 | 47 | arch_flag=$(strip $(if $(filter docker,$(CONTAINER_CMD)),\ 48 | $(if $(filter-out $(HOST_ARCH),$(BUILD_ARCH)),\ 49 | $(error Setting BUILD_ARCH != $(HOST_ARCH) not supported on docker)),\ 50 | $(if $(BUILD_ARCH),--arch $(BUILD_ARCH)))) 51 | 52 | build: build-server build-nightly-server build-ad-server build-client \ 53 | build-toolbox 54 | .PHONY: build 55 | 56 | 57 | .PHONY: debug-vars 58 | debug-vars: 59 | @echo OS_NAME: $(OS_NAME) 60 | @echo TAG: $(TAG) 61 | @echo NIGHTLY_TAG: $(NIGHTLY_TAG) 62 | @echo SERVER_NAME: $(SERVER_NAME) 63 | @echo NIGHTLY_SERVER_NAME: $(NIGHTLY_SERVER_NAME) 64 | @echo AD_SERVER_NAME: $(AD_SERVER_NAME) 65 | 66 | @echo BUILDFILE_SERVER: $(BUILDFILE_SERVER) 67 | @echo BUILDFILE_AD_SERVER: $(BUILDFILE_AD_SERVER) 68 | @echo BUILDFILE_NIGHTLY_AD_SERVER: $(BUILDFILE_iNIGHTLY_AD_SERVER) 69 | @echo BUILDFILE_NIGHTLY_SERVER: $(BUILDFILE_NIGHTLY_SERVER) 70 | @echo BUILDFILE_CLIENT: $(BUILDFILE_CLIENT) 71 | @echo BUILDFILE_TOOLBOX: $(BUILDFILE_TOOLBOX) 72 | 73 | @echo SERVER_SRC_FILE: $(SERVER_SRC_FILE) 74 | @echo AD_SERVER_SRC_FILE: $(AD_SERVER_SRC_FILE) 75 | @echo CLIENT_SERVER_SRC_FILE: $(CLIENT_SRC_FILE) 76 | @echo TOOLBOX_SRC_FILE: $(TOOLBOX_SRC_FILE) 77 | 78 | 79 | ### Image Build and Push Rules ### 80 | 81 | build-image: $(DYN_BUILDFILE) 82 | .PHONY: build-image 83 | 84 | $(DYN_BUILDFILE): 85 | @[ "$(KIND)" ] || (echo "KIND must be specfied"; exit 1) 86 | $(call _BUILD_KP,$(KIND),$(if $(PACKAGE_SOURCE),$(PACKAGE_SOURCE),default)) $(EXTRA_BUILD_ARGS) 87 | 88 | build-server: $(BUILDFILE_SERVER) 89 | .PHONY: build-server 90 | $(BUILDFILE_SERVER): Makefile $(SERVER_SRC_FILE) $(SERVER_SOURCES) 91 | $(call _BUILD_KP,server,default) $(EXTRA_BUILD_ARGS) 92 | 93 | push-server: build-server 94 | $(call _BUILD_KP,server,default,--push) 95 | .PHONY: push-server 96 | 97 | build-nightly-server: $(BUILDFILE_NIGHTLY_SERVER) 98 | .PHONY: build-nightly-server 99 | $(BUILDFILE_NIGHTLY_SERVER): Makefile $(SERVER_SRC_FILE) $(SERVER_SOURCES) 100 | $(call _BUILD_KP,server,nightly) $(EXTRA_BUILD_ARGS) 101 | 102 | push-nightly-server: build-nightly-server 103 | $(call _BUILD_KP,server,nightly,--push) 104 | .PHONY: push-nightly-server 105 | 106 | build-ad-server: $(BUILDFILE_AD_SERVER) 107 | .PHONY: build-ad-server 108 | $(BUILDFILE_AD_SERVER): Makefile $(AD_SERVER_SRC_FILE) $(AD_SERVER_SOURCES) 109 | $(call _BUILD_KP,ad-server,default) $(EXTRA_BUILD_ARGS) 110 | 111 | push-ad-server: build-ad-server 112 | $(call _BUILD_KP,ad-server,default,--push) 113 | .PHONY: push-ad-server 114 | 115 | build-nightly-ad-server: $(BUILDFILE_NIGHTLY_AD_SERVER) 116 | .PHONY: build-nightly-ad-server 117 | $(BUILDFILE_NIGHTLY_AD_SERVER): Makefile $(AD_SERVER_SRC_FILE) $(AD_SERVER_SOURCES) 118 | $(call _BUILD_KP,ad-server,nightly) $(EXTRA_BUILD_ARGS) 119 | 120 | push-nightly-ad-server: build-nightly-ad-server 121 | $(call _BUILD_KP,ad-server,nightly,--push) 122 | .PHONY: push-nightly-ad-server 123 | 124 | build-client: $(BUILDFILE_CLIENT) 125 | .PHONY: build-client 126 | $(BUILDFILE_CLIENT): Makefile $(CLIENT_SRC_FILE) 127 | $(call _BUILD_KP,client,default) $(EXTRA_BUILD_ARGS) 128 | 129 | push-client: build-client 130 | $(call _BUILD_KP,client,default,--push) 131 | .PHONY: push-client 132 | 133 | build-toolbox: $(BUILDFILE_TOOLBOX) 134 | .PHONY: build-toolbox 135 | $(BUILDFILE_TOOLBOX): Makefile $(TOOLBOX_SRC_FILE) 136 | $(call _BUILD_KP,toolbox,default) $(EXTRA_BUILD_ARGS) 137 | 138 | push-toolbox: build-toolbox 139 | $(call _BUILD_KP,toolbox,default,--push) 140 | .PHONY: push-toolbox 141 | 142 | 143 | ### Test Rules: executes test scripts ### 144 | 145 | test: test-server test-nightly-server 146 | .PHONY: test 147 | 148 | test-server: build-server 149 | CONTAINER_CMD=$(CONTAINER_CMD) \ 150 | LOCAL_TAG=$(shell cat $(BUILDFILE_SERVER) |cut -d' ' -f2) \ 151 | tests/test-samba-container.sh 152 | .PHONY: test-server 153 | 154 | test-nightly-server: $(BUILDFILE_NIGHTLY_SERVER) 155 | CONTAINER_CMD=$(CONTAINER_CMD) \ 156 | LOCAL_TAG=$(shell cat $(BUILDFILE_NIGHTLY_SERVER) |cut -d' ' -f2) \ 157 | tests/test-samba-container.sh 158 | .PHONY: test-nightly-server 159 | 160 | 161 | ### Check Rules: static checks, quality tools ### 162 | 163 | check: check-shell-scripts check-yaml 164 | .PHONY: check 165 | # rule requires shellcheck and find to run 166 | check-shell-scripts: $(filter $(ALT_BIN)%,$(SHELLCHECK)) 167 | $(SHELLCHECK) -P tests/ -eSC2181 -fgcc $$(find $(ROOT_DIR) -name "*.sh") 168 | .PHONY: check-shell-scripts 169 | 170 | 171 | check-yaml: $(filter $(ALT_BIN)%,$(YAMLLINT_CMD)) 172 | $(YAMLLINT_CMD) -c $(CURDIR)/.yamllint.yaml $(CURDIR) 173 | .PHONY: check-yaml 174 | 175 | # not included in check to not disrupt wip branches 176 | check-gitlint: $(filter $(ALT_BIN)%,$(GITLINT)) 177 | $(GITLINT) -C .gitlint --commits origin/master.. lint 178 | .PHONY: check-gitlint 179 | 180 | 181 | ### Misc. Rules ### 182 | 183 | $(ALT_BIN)/%: 184 | $(CURDIR)/hack/install-tools.sh --$* $(ALT_BIN) 185 | 186 | clean: clean-buildfiles clean-altbin 187 | .PHONY: clean 188 | 189 | clean-buildfiles: 190 | $(RM) $(BUILDFILE_PREFIX)* 191 | .PHONY: clean-buildfiles 192 | 193 | clean-altbin: 194 | $(RM) -r $(ALT_BIN) 195 | .PHONY: clean-altbin 196 | -------------------------------------------------------------------------------- /Makefile.opensuse: -------------------------------------------------------------------------------- 1 | include Makefile 2 | 3 | OS_NAME=opensuse 4 | SERVER_SOURCES:=$(SERVER_DIR)/smb.conf 5 | REPO_BASE=registry.opensuse.org/opensuse/ 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # samba-container 2 | 3 | Container images for [Samba](https://samba.org) services. 4 | 5 | ### Our images: 6 | * Are [OCI](https://opencontainers.org/) formatted container images 7 | * Provide application-like high-level entrypoint scripts 8 | * Are available as pre-built stable and "nightly" [variants](#image-variants) 9 | * Are used by the [samba-operator](https://github.com/samba-in-kubernetes/samba-operator) for Kubernetes 10 | * Don't require Kubernetes 11 | * Are [available at quay.io](https://quay.io/organization/samba.org) 12 | * Are used by the [ceph project](https://github.com/ceph/ceph) to provide SMB services on CephFS 13 | 14 | ### Image Types: 15 | 16 | |Image Type | Repository | Custom Entrypoint | Features | 17 | |-------------|------------|-------------------|----------| 18 | |[Samba Server](#samba-server) | [quay.io](https://quay.io/repository/samba.org/samba-server) | Yes | Standalone file server, Domain member file server | 19 | |[AD Domain Controller](#ad-dc) | [quay.io](https://quay.io/repository/samba.org/samba-ad-server) | Yes | Active Directory Domain Controller | 20 | |[Client](#client) | [quay.io](https://quay.io/repository/samba.org/samba-client) | No | Basic Userspace Client Utilities | 21 | |[Toolbox](#toolbox) | [quay.io](https://quay.io/repository/samba.org/samba-toolbox) | No | Extra debugging and testing tools | 22 | 23 | 24 | ## Samba Server 25 | 26 | The Samba server image defaults to the `samba-container` entrypoint. 27 | 28 | In the default configuration, the server container image exports one share, 29 | named "share", with the path `/share` which is expected to be a volume provided 30 | by the host. A default user, named "sambauser" is predefined with a password of 31 | "samba". This simple mode of operation is great for quick demos. Example: 32 | 33 | ```sh 34 | podman run --name samba --publish 10445:445 --volume=/path/on/host/to/share:/share:Z --rm quay.io/samba.org/samba-server:latest 35 | ``` 36 | > **Note** 37 | > The port mapping option (`--publish`) is only needed when running 38 | > as non-root, e.g. for testing purposes. 39 | 40 | The `samba-container` entrypoint can perform many functions and is 41 | designed to make the container image act like a cohesive application. 42 | It can automate the management of Samba as well as the container environment 43 | to make them work together. This tool is provided by the 44 | [sambacc project](https://github.com/samba-in-kubernetes/sambacc). 45 | 46 | ```sh 47 | # print help 48 | podman run --rm quay.io/samba.org/samba-server:latest --help 49 | # print help for the run subcommand 50 | podman run --rm quay.io/samba.org/samba-server:latest run --help 51 | ``` 52 | 53 | ### Changing the configuration 54 | 55 | The behavior of the container can be changed by invoking it with specific 56 | arguments for the `samba-container` script and/or setting environment 57 | variables. 58 | 59 | You can include a custom configuration via the following method: 60 | ``` 61 | $EDITOR /path/to/config/config.json 62 | podman run --name samba --publish 10445:445 --volume=/path/on/host/to/share:/share:Z --volume=/path/to/config:/etc/samba-container -e SAMBACC_CONFIG=/etc/samba-container/config.json -e SAMBA_CONTAINER_ID=myid --rm quay.io/samba.org/samba-server:latest 63 | ``` 64 | 65 | 66 | 67 | ## AD DC 68 | 69 | The AD DC image defaults to the `samba-dc-container` entrypoint. 70 | 71 | In the default configuration, the AD DC container image automatically 72 | provisions and serves a simple stock domain `DOMAIN1.SINK.TEST`. 73 | Because the Samba AD DC uses certain file system xattrs this container 74 | must currently be run with privileges. Example: 75 | 76 | ```sh 77 | podman run --rm --privileged quay.io/samba.org/samba-ad-server:latest 78 | ``` 79 | 80 | The `samba-dc-container` entrypoint can perform multiple functions as is 81 | designed to make the container image act like a cohesive application. 82 | It helps automate the provisioning of and/or connection to a domain. 83 | This tool is provided by the 84 | [sambacc project](https://github.com/samba-in-kubernetes/sambacc). 85 | 86 | 87 | 88 | ## Client 89 | 90 | The project provides a simple samba client container image that can be 91 | useful for testing. One does not need to install the user space samba client 92 | locally but rather use the container image. It can run the samba client 93 | interactively when a TTY is available and can also be scripted for 94 | automated testing purposes. Example: 95 | 96 | ```sh 97 | podman run --rm -it quay.io/samba.org/samba-client:latest 98 | [root@dc0419d28c4e /]# smbclient -U 'sambauser' //foo.example.org/share 99 | ``` 100 | 101 | ## Toolbox 102 | 103 | The project provides a container image container containing the samba test 104 | suite program 105 | ([smbtorture](https://wiki.samba.org/index.php/Writing_Torture_Tests)) as well 106 | as the user space client. This can be used for debugging and testing purposes. 107 | Example: 108 | 109 | ```sh 110 | podman run --rm -it quay.io/samba.org/samba-toolbox:latest 111 | [root@dc0419d28c4e /]# smbtorture --help 112 | ``` 113 | ## Image Variants 114 | 115 | The server images come in two variants: stable and nightly. The 116 | stable variant is what you get with the "latest" tag and includes 117 | Samba packages from the Linux distribution used in our base images. 118 | The "nightly" images are based on Samba RPM packages created by the 119 | [samba-build project](https://github.com/samba-in-kubernetes/samba-build) 120 | which builds and tests Samba builds before release. The nightly images 121 | are tagged with "nightly" instead of "latest". 122 | 123 | ## Developers 124 | 125 | ### Building the containers 126 | 127 | ```sh 128 | # Build Everything 129 | make build 130 | ``` 131 | 132 | Each container image type has a build target: 133 | ```sh 134 | # Build the server image 135 | make build-server 136 | # Build the server with "nightly" samba 137 | make build-nightly-server 138 | # Build the client 139 | make build-client 140 | # And so on... 141 | ``` 142 | 143 | There are matching `push-*` rules that default to pushing the images to the 144 | "official" quay.io repositories. These rules can be executed by the appropriate 145 | github actions or by project maintainers. 146 | -------------------------------------------------------------------------------- /docs/development.md: -------------------------------------------------------------------------------- 1 | # Development Guide 2 | 3 | 4 | ## Building samba containers with unreleased sambacc code 5 | 6 | Changes to `sambacc` are validated by a suite of unit tests to ensure a minium 7 | level of quality, but that is often not enough to fully validate a 8 | work-in-progress feature, especially one that needs to interact with components 9 | from Samba in complex ways. One may want to try out an unreleased branch of 10 | sambacc code as part of a samba container image. Two methods of doing this are: 11 | * Build sambacc RPMs and put them in a yum/dnf repo 12 | * Customize the Containerfile to use a sambacc build stage 13 | 14 | Both methods make use of the sambacc build image. The files needed to build the 15 | image are part of the [sambacc 16 | repo](https://github.com/samba-in-kubernetes/sambacc) and already-created 17 | images are available at quay.io: 18 | [quay.io/samba.org/sambacc](https://quay.io/repository/samba.org/sambacc). 19 | 20 | ### RPMs 21 | 22 | One can build rpms using the sambacc test-and-build container. 23 | In this example we assume you have a git checkout of sambacc as the 24 | local path. Create a new directory to store build artifacts in: 25 | ``` 26 | mkdir -p _build 27 | ``` 28 | 29 | Then run the container command like follows: 30 | ``` 31 | podman run -v $PWD:/var/tmp/build/sambacc -v $PWD/_build:/srv/dist/:z -e SAMBACC_DISTNAME=dev quay.io/samba.org/sambacc:latest 32 | ``` 33 | 34 | Breaking it down, we're mounting the current dir at `/var/tmp/build/sambacc`, 35 | mounting the build dir at `/srv/dist` and telling the build container 36 | to store artifacts under the "distribution name" of `dev`. This should 37 | result in rpms, whl files and other artifacts in `_build/dev`. You can 38 | name your "dist" anything. 39 | 40 | Now you have a directory with rpms in it you can run `createrepo` on them 41 | and/or publish them on the web. Managing the rpms is an exercise left to the 42 | reader. 43 | 44 | To get them into a samba-container image, like the samba-server or 45 | samba-ad-server image, we need to get or create a repo file pointing to the 46 | repo hosting your rpms. The repo file must be saved into the build container at 47 | a path named like `/tmp/sambacc-dist-latest/sambacc*.repo`, so that the 48 | `install-sambacc.sh` script that is run during the image build can find it. 49 | 50 | Typically this means modifying the Containerfile. Here's an example modification 51 | to the `images/server/Containerfile.fedora` file: 52 | ``` 53 | COPY .common/install-sambacc-common.sh /usr/local/bin/install-sambacc-common.sh 54 | COPY install-sambacc.sh /usr/local/bin/install-sambacc.sh 55 | # Add an ADD command to copy our repofile into the build 56 | ADD https://my-cool-repo.example.org/mystuff/sambacc.repo /tmp/sambacc-dist-latest 57 | RUN /usr/local/bin/install-sambacc.sh \ 58 | "/tmp/sambacc-dist-latest" \ 59 | "${SAMBACC_VERSION_SUFFIX}" 60 | ``` 61 | 62 | Now build the image the usual way. It should contain your specific sambacc rpms. 63 | 64 | 65 | ### Build Stage 66 | 67 | Rather than building the sambacc RPMs and creating a repo for them, the build 68 | steps can be combined by modifying the `Containerfile`s to add a specific build 69 | stage. First add the build stage to the top of the Containerfile: 70 | ``` 71 | # --- new stuff --- 72 | FROM quay.io/samba.org/sambacc:latest AS sccbuilder 73 | ARG SAMBACC_VER=my-cool-branch 74 | ARG SAMBACC_REPO=https://github.com/example-user/sambacc 75 | RUN SAMBACC_DISTNAME=latest \ 76 | /usr/local/bin/build.sh ${SAMBACC_VER} ${SAMBACC_REPO} 77 | # create yum/dnf repo for temp. packages (file uses paths in dest container) 78 | RUN dnf install -y /usr/bin/createrepo_c \ 79 | && createrepo_c /srv/dist/latest \ 80 | && echo -e '[sambacc]\nbaseurl=file:///tmp/sambacc-dist-latest\nenabled=1\ngpgcheck=0\n' > /srv/dist/latest/sambacc.repo 81 | # --- end new stuff --- 82 | 83 | FROM registry.fedoraproject.org/fedora:38 84 | ``` 85 | 86 | The variables `SAMBACC_VER` and `SAMBACC_REPO` can be overridden on the command 87 | line so you don't have to keep modifying the Containerfile to set them, unless 88 | you want to. `SAMBACC_VER` takes a git ref and that can be a barnch name or a 89 | commit hash. Using a commit hash can be handy to avoid caching issues. 90 | 91 | Next, we need to make a modification to the RUN command that executes 92 | `install-sambacc.sh`: 93 | ``` 94 | # add the --mount argument to map the dist dir of the sccbuilder 95 | # container to the /tmp/sambacc-dist-latest dir in the current build 96 | # container. 97 | RUN --mount=type=bind,from=sccbuilder,source=/srv/dist/latest,destination=/tmp/sambacc-dist-latest bash -x /usr/local/bin/install-sambacc.sh \ 98 | "/tmp/sambacc-dist-latest" \ 99 | "${SAMBACC_VERSION_SUFFIX}" 100 | ``` 101 | 102 | Very old versions of podman and docker may not support `--mount`. As an 103 | alternative, you can add a `COPY` command to copy the rpms from one container 104 | to the other. 105 | -------------------------------------------------------------------------------- /docs/release-process.md: -------------------------------------------------------------------------------- 1 | # samba-container Release Process 2 | 3 | ## Preparation 4 | 5 | The samba-container project has a dedicated branch, called `release`, for 6 | release versions. This is done to update certain files which control 7 | dependencies and versioning. Tags are applied directly to this branch 8 | and only this branch. 9 | 10 | 11 | ### Tagging 12 | 13 | Prior to tagging, check out the `release` branch and merge `master` into it. 14 | Example: 15 | 16 | ``` 17 | git checkout master 18 | git pull --ff-only 19 | git checkout release 20 | git pull --ff-only 21 | git merge master 22 | # resolve any conflicts 23 | ``` 24 | 25 | Now we need to "pin" the appropriate versions of samba and sambacc so that only 26 | explicitly specified versions of those packages will be included on release 27 | branch builds. Set `SAMBA_VERSION_SUFFIX` and `SAMBACC_VERSION_SUFFIX` in the 28 | container files in `images/`. Currently, only the fedora based images are 29 | included in the release. Thus you must set those variables in the fedora 30 | container files for server and ad-server. Commit these changes to the `release` 31 | branch. Currently, there is no PR process for release branches so make the 32 | commits directly to the `release` branch and push them. This implies that 33 | releases must be managed by users with the rights to push directly to the 34 | project's release branch. 35 | 36 | At this point, an optional but recommended step is to do a test build before 37 | tagging. Run `make build-ad-server build-server build-client build-toolbox`. 38 | You do not need to build the nightly package variants or other OS bases as 39 | these are not part of the released images. You can push the images to quay.io 40 | under your own repos to perform a early security scan as well. 41 | 42 | If you are happy with the content of the `release` branch, tag it. Example: 43 | 44 | ``` 45 | git checkout release 46 | git tag -a -m 'Release v0.3' v0.3 47 | ``` 48 | 49 | This creates an annotated tag. Release tags must be annotated tags. 50 | 51 | ### Build 52 | 53 | Using the tagged `release` branch, the container images for release will be 54 | built. It is very important to ensure that base images are up-to-date. 55 | It is very important to ensure that you perform the next set of steps with 56 | clean new builds and do not use cached images. To accomplish both tasks it 57 | is recommended to purge your local container engine of cached images 58 | (Example: `podman image rm --all`). You should have no images named like 59 | `quay.io/samba.org` in your local cache. 60 | 61 | Build the images from scratch. Example: 62 | ``` 63 | make build-ad-server build-server build-client build-toolbox 64 | ``` 65 | 66 | For each image that was just built, apply a temporary pre-release tag 67 | to it. Example: 68 | ``` 69 | for img_name in ad-server server client toolbox ; do 70 | podman tag quay.io/samba.org/samba-${img_name}:{latest,v0.3pre1} 71 | done 72 | ``` 73 | 74 | Log into quay.io. Push the images to quay.io using the temporary tag. Example: 75 | ``` 76 | for img_name in ad-server server client toolbox ; do 77 | podman push quay.io/samba.org/samba-${img_name}:v0.3pre1 78 | done 79 | ``` 80 | 81 | Wait for the security scan to complete. There shouldn't be any issues if you 82 | properly updated the base images before building. If there are issues and you 83 | are sure you used the newest base images, check the base images on quay.io and 84 | make sure that the number of issues are identical. The security scan can take 85 | some time, while it runs you may want to do other things. 86 | 87 | 88 | ## GitHub Release 89 | 90 | When you are satisfied that the tagged version is suitable for release, you 91 | can push the tag to the public repo: 92 | ``` 93 | git push --follow-tags 94 | ``` 95 | 96 | Draft a new set of release notes. Select the recently pushed tag. Start with 97 | the auto-generated release notes from GitHub (activate the `Generate release 98 | notes` button/link). Add an introductory section (see previous notes for an 99 | example). Add a "Highlights" section if there are any notable features or fixes 100 | in the release. The Highlights section can be skipped if the content of the 101 | release is unremarkable (e.g. few changes occurred since the previous release). 102 | 103 | Because this is a container based release we do not provide any build artifacts 104 | on GitHub (beyond the sources automatically provided there). Instead we add 105 | a Downloads section that notes the exact tags and digests that the images can 106 | be found at on quay.io. 107 | 108 | The downloads section can be generated using the shell script 109 | https://github.com/samba-in-kubernetes/samba-container/blob/master/hack/install-tools.sh in this repository. 110 | 111 | It needs to be invoked with the release tag as the only argument. E. G. : 112 | 113 | ```console 114 | 115 | $ ./hack/release-gen-download-section.sh v0.3 116 | ``` 117 | 118 | 119 | It is important that the digest is fetched from qauy.io after it has been 120 | pushed. Do not use any local digest hashes. You may want to double check the 121 | values produced by the script with those in the quay.io UI. Click on the 122 | SHA256 link and then compare the full manifest hash using the UI widget that 123 | appears. 124 | 125 | Perform a final round of reviews, as needed, for the release notes and then 126 | publish the release. 127 | 128 | Once the release notes are drafted and then either immediately before or after 129 | publishing them, use the quay.io UI to copy each pre-release tag to the "latest" 130 | tag and a final "vX.Y" tag. Delete the temporary pre-release tags using the 131 | quay.io UI as they are no longer needed. 132 | -------------------------------------------------------------------------------- /docs/server.md: -------------------------------------------------------------------------------- 1 | 2 | # Using the Samba Server Image 3 | 4 | The container image for the Samba server defaults to the `samba-container` 5 | entrypoint. If invoked without arguments, the container image defaults to the 6 | arguments `run smbd`. You can bypass the `samba-container` entrypoint to run 7 | any of the binaries in the container if you wish. However, the document that 8 | follows assumes the use of the `samba-container` entrypoint. 9 | 10 | 11 | The `samba-container` entrypoint is designed to make the container image 12 | feel like a cohesive application rather than just a collection of parts. 13 | However, there are times that a low-level understanding of Samba and its 14 | parts are useful and this document will assume some familiarity 15 | with Samba. If you're reading this document and find sections that you feel 16 | need better explanation, please file an issue in our project. 17 | 18 | The `samba-container` tool has a built in help system. Pass --help to 19 | the command or after any subcommand (example: `run --help`) to 20 | display the internal help text. The built-in help text will be the 21 | most up to date reflecting the version in use, but likely terser than 22 | this document. 23 | 24 | 25 | ## General Configuration 26 | 27 | There are two critical values that control the samba-container tool. First, 28 | the command line option `--config` and the equivalent environment variable 29 | `SAMBACC_CONFIG` specifies a path (or colon separated paths) to a JSON based 30 | configuration file. The JSON based configuration can contain multiple 31 | "instances" and so the `--identity` option and/or the equivalent environment 32 | variable `SAMBA_CONTAINER_ID` provides a name to identify which configuration 33 | to use. 34 | 35 | The complete [documentation for the JSON configuration 36 | file](https://github.com/samba-in-kubernetes/sambacc/blob/master/docs/configuration.md) 37 | can be found in the sambacc project. A default configuration file is included 38 | as part of container image which specifies a simple demonstration share. 39 | 40 | Other global CLI options include: 41 | * `--username` For any command that may require a username, specify a user name. 42 | * `--password` For any command that may require a password, specify a password. 43 | * `--join-marker` Specify the location of a file that indicates a domain join 44 | has already been performed. 45 | * `--samba-debug-level` Specify an integer, from 0 to 10, that will be 46 | passed to Samba commands for debugging purposes. 47 | * `--skip-if-file` Specify the location of a file. If the file exists the 48 | command will be skipped (it will not be further executed). 49 | 50 | 51 | ## Running Servers 52 | 53 | The `run` subcommand starts Samba servers. Valid Samba servers include: `smbd`, 54 | `winbindd`, and `ctdbd`. For example to start smbd explicitly you can run 55 | `podman run --rm --name smbd quay.io/samba.org/samba-server:latest run smbd` or 56 | to start winbind execute `podman run --rm --name winbindd 57 | quay.io/samba.org/samba-server:latest run winbindd`. The servers run in the foreground as is typical for application containers. 58 | 59 | The option `--setup` may be specified one or more times. The values 60 | to the setup option tell the tool what setup steps to perform before 61 | starting up the server. This allows one to have more precise control 62 | over the container configuration and environment. 63 | 64 | Valid values include: 65 | * `init-all` - A special value that tells the tool to perform all known 66 | and valid setup steps. 67 | * `config` - Import sambacc configuration into Samba's configuration registry. 68 | * `users` - Import users into the systems /etc files 69 | * `users_passdb` - Import users into Samba's password db 70 | * `nsswitch` - Configure the container's `/etc/nsswitch` file 71 | * `share_paths` - Create and/or update Share paths and their permissions 72 | 73 | Here's an example of running an smbd server with a specific set of setup steps. 74 | One might want to do something like this if Samba's db files are persisted 75 | across restarts of the container. Example: 76 | `podman run --rm --name -v /var/lib/sambactr/var:/var/lib/samba smbd quay.io/samba.org/samba-server:latest run --setup=users --setup=nsswitch --setup=share_paths smbd` 77 | 78 | 79 | ## Environment & System Control 80 | 81 | The `samba-container` tool provides a number of subcommands that help 82 | configure the general environment that the Samba servers run in. 83 | This includes the ephemeral system level files, Samba configuration, 84 | and the data volume(s) that contain the shares. 85 | 86 | ### init 87 | 88 | The `init` command works much like the `--setup=init-all` setup step, 89 | only it exits after completion rather than trying to start a server. 90 | This command can be used to prepare a directory (or directories) that 91 | will be later be mapped into a running server container. 92 | 93 | ### import 94 | 95 | The `import` command will import configuration parameters from the sambacc 96 | config to samba's registry-based configuration database. 97 | 98 | ### ensure-share-paths 99 | 100 | The `ensure-share-paths` command will examine the configured shares and check 101 | if the share paths already exist. If not, the command will create them. 102 | Depending on the configuration it may also check and/or update the permissions 103 | on the share directories as well. 104 | 105 | ### import-users 106 | 107 | The `import-users` command will take the users and groups listed in the 108 | JSON based configuration file and translate them to the "system files" 109 | `/etc/passwd` and `/etc/group` of the container. This allows the use of 110 | local (non-domain) user logons. Note that these files 111 | are part of the ephemeral base image of the container and thus largely 112 | exists to reflect the equivalent functionality in `--setup=users`. 113 | 114 | ### print-config 115 | 116 | The `print-config` subcommand translates the JSON based configuration 117 | into an smb.conf-style output of Samba specific parameters. It does not 118 | change any configuration. It is most useful for debugging what configuration 119 | values will be set by a sub-command like `import`. 120 | 121 | 122 | For example, the default configuration of the server image: 123 | ``` 124 | podman run --rm quay.io/samba.org/samba-server:latest print-config 125 | [global] 126 | security = user 127 | server min protocol = SMB2 128 | load printers = no 129 | printing = bsd 130 | printcap name = /dev/null 131 | disable spoolss = yes 132 | guest ok = no 133 | netbios name = SAMBA 134 | 135 | [share] 136 | path = /share 137 | valid users = sambauser, otheruser 138 | ``` 139 | 140 | 141 | ## Domain Join 142 | 143 | 144 | The `samba-container` tool provides mechanisms that wrap Samba's domain 145 | join functionality. The commands are only useful when the Samba state 146 | directory `/var/lib/samba` is persisted. 147 | 148 | The `join` command attempts an immediate domain join. The inputs for 149 | domain credentials is outlined below. The `must-join` command will 150 | check for available credentials but is allowed to wait until 151 | credentials become available or another process performs the join. 152 | The `must-join` subcommand is mostly useful when building a declarative 153 | set of container commands and the pipeline should block until 154 | the "instance" has been joined to a domain. 155 | 156 | Both `join` and `must-join` support the options: 157 | * `--insecure` Enable sourcing a domain username/password from CLI arguments 158 | or environment variables 159 | * `--no-insecure` Disable sourcing a domain username/password from CLI 160 | arguments or environment variables 161 | * `--files` Enable sourcing a domain username/password from dedicated 162 | JSON files. 163 | * `--no-files` Disable sourcing a domain username/password from dedicated 164 | JSON files. 165 | * `--join-file` (`-j`) Specify the path to a JSON file containing a 166 | domain user's name and password. May be specified more than once. 167 | 168 | 169 | The `join` command also supports the options: 170 | * `--interactive` Enable interactive password prompt 171 | * `--no-interactive` Disable interactive password prompt 172 | 173 | The `must-join` command also supports the options: 174 | * `--wait` Do not exit until a join to the domain has been completed 175 | * `--no-wait` Exit even if a join has not been completed 176 | 177 | For fully automated deployment of samba-server container with domain 178 | access the best currently supported method is to combine the `must-join` 179 | command with a secret store. For example, podman supports the `podman create 180 | secret` command and the `--secret` option to the run command. This 181 | allows one to store a JSON file with the required username and password. 182 | Other systems such as Kubernetes can combine the Secret resource with 183 | a store such as HashiCorp Vault. 184 | 185 | However, if one is not comfortable with storing a domain user with a password a 186 | partially automated deployment with a domain join can still be performed. One 187 | option is a workflow similar to a traditional Samba server on a physical or VM 188 | host. Execute containers with the `init` and then `join` subcommands (with tty 189 | support enabled (podman -it) and ensure that the Samba state directory(s) are 190 | persisted before starting the servers. Another option is to let the 191 | `must-join` command run and while it is in its wait loop, exec into the 192 | container and run the `join`. 193 | 194 | Example: 195 | ``` 196 | $ podman run -d --rm --name joiner -v /var/lib/sambactr/var:/var/lib/samba quay.io/samba.org/samba-server:latest must-join --wait 197 | $ podman exec --rm -it joiner 198 | # samba-container join --interactive 199 | ``` 200 | 201 | 202 | # Dynamic Configuration 203 | 204 | The `update-config` command can be used to support more dynamic configuration 205 | in the case of a JSON configuration shared between the host and the container. 206 | When the JSON configuration file is updated a container running `update-config` 207 | in concert with an smbd (and optional winbind) container can automatically 208 | update the configuration of the running Samba server. 209 | 210 | The `update-config` command can be launched in a container that shares the 211 | same pid namespace and persisted directories as the smbd/winbind containers. 212 | It will automatically check the Samba configuration matches the JSON 213 | configuration and update it if needed. It will also create any missing 214 | shares and update permissions like the `ensure-share-paths` subcommand. 215 | 216 | Passing the `--watch` option to `update-config` makes the process 217 | continue running rather than exiting after the initial updates. Periodically, 218 | this command will check for changes and repeat the configuration update 219 | action. 220 | 221 | 222 | # Combining Containers 223 | 224 | In a typical hardware or VM based Samba installation that is a domain member 225 | multiple server processes act in concert. The smbd process handles the SMB 226 | protocol while winbindd takes care of integration with Active Directory. 227 | Accomplishing this with the samba server containers is possible by starting 228 | multiple containers with namespaces shared between them. 229 | 230 | Namespaces that must be shared: 231 | * PID Namespace 232 | * UTS Namespace 233 | * Network namespace 234 | 235 | In addition you should share the directories/volumes that contain the samba 236 | state files (samba's TDB databases). You do not have to expose the volumes or 237 | directories containing shares to the winbind pod. 238 | 239 | An example script setting this up using [podman CLI commands is available in 240 | our examples 241 | directory](https://github.com/samba-in-kubernetes/samba-container/blob/master/examples/podman/smb-wb-pod.sh). 242 | Another example using [kubernetes 243 | YAML](https://github.com/samba-in-kubernetes/samba-container/blob/master/examples/kubernetes/sambadmpod.yml) 244 | is also available. 245 | 246 | 247 | 254 | -------------------------------------------------------------------------------- /examples/kubernetes/README.md: -------------------------------------------------------------------------------- 1 | Examples for deploying samba as an application on top of a pvc. 2 | -------------------------------------------------------------------------------- /examples/kubernetes/pv.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolume 3 | metadata: 4 | name: mypv 5 | labels: 6 | type: local 7 | spec: 8 | storageClassName: manual 9 | capacity: 10 | storage: 1Gi 11 | accessModes: 12 | - ReadWriteOnce 13 | hostPath: 14 | path: "/mnt/pv" 15 | -------------------------------------------------------------------------------- /examples/kubernetes/pvc.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | name: mypvc 5 | spec: 6 | storageClassName: manual 7 | accessModes: 8 | - ReadWriteOnce 9 | resources: 10 | requests: 11 | storage: 1Gi 12 | -------------------------------------------------------------------------------- /examples/kubernetes/samba-ad-server-deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: samba-ad-server 5 | labels: 6 | app: samba-ad 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: samba-ad 12 | template: 13 | metadata: 14 | labels: 15 | app: samba-ad 16 | spec: 17 | containers: 18 | - name: samba-ad 19 | image: quay.io/samba.org/samba-ad-server:latest 20 | securityContext: 21 | capabilities: 22 | add: ["SYS_ADMIN"] 23 | ports: 24 | # https://wiki.samba.org/index.php/Samba_AD_DC_Port_Usage 25 | - containerPort: 53 26 | name: dns 27 | - containerPort: 135 28 | name: epm 29 | protocol: TCP 30 | - containerPort: 137 31 | name: netbios-ns 32 | protocol: UDP 33 | - containerPort: 138 34 | name: netbios-dgram 35 | protocol: UDP 36 | - containerPort: 139 37 | name: netbios-session 38 | protocol: TCP 39 | - containerPort: 389 40 | name: ldap 41 | - containerPort: 445 42 | name: smb 43 | protocol: TCP 44 | - containerPort: 464 45 | name: kerberos 46 | - containerPort: 636 47 | name: ldaps 48 | protocol: TCP 49 | - containerPort: 3268 50 | name: gc 51 | protocol: TCP 52 | - containerPort: 3269 53 | name: gc-ssl 54 | protocol: TCP 55 | # need 49152-65535 for dynamic RPC ports 56 | # but currently not possible to specify ranges 57 | -------------------------------------------------------------------------------- /examples/kubernetes/samba-ctdb-dm-sset.yml: -------------------------------------------------------------------------------- 1 | # 2 | # An example of running samba with ctdb replication as a kubernetes 3 | # StatefulSet. 4 | # 5 | # This is *highly experimental* and not meant for real use. Use only if you're 6 | # interested in helping test or develop samba-container/sambacc CTDB support. 7 | # 8 | # This does not integrate with active directory. 9 | # This directly uses "rook-cephfs" for ReadWriteMany PVCs. If you have some 10 | # other storage class that supports rwx pvcs you need to edit the yaml below. 11 | # This only works with creating a clean set of pvcs & stateful set and scaling 12 | # up. It does *not* currently support pods getting restarted or scaling down. 13 | # 14 | # Use at your own risk, and have fun! 15 | # 16 | --- 17 | # Configuration for the samba smbd+winbind+ctdb pod. 18 | apiVersion: v1 19 | kind: ConfigMap 20 | metadata: 21 | name: samba-container-config-swc 22 | data: 23 | config.json: | 24 | { 25 | "samba-container-config": "v0", 26 | "configs": { 27 | "demo": { 28 | "shares": [ 29 | "share" 30 | ], 31 | "globals": [ 32 | "noprinting", 33 | "sambadm1", 34 | "vfs_fileid" 35 | ], 36 | "instance_features": ["ctdb"], 37 | "instance_name": "SAMBASWC" 38 | } 39 | }, 40 | "shares": { 41 | "share": { 42 | "options": { 43 | "path": "/share", 44 | "read only": "no" 45 | } 46 | } 47 | }, 48 | "_NOTE": "Change the security and workgroup keys to match your domain.", 49 | "globals": { 50 | "noprinting": { 51 | "options": { 52 | "load printers": "no", 53 | "printing": "bsd", 54 | "printcap name": "/dev/null", 55 | "disable spoolss": "yes" 56 | } 57 | }, 58 | "sambadm1": { 59 | "options": { 60 | "log level": "10", 61 | "security": "ads", 62 | "workgroup": "CHANGEME", 63 | "realm": "CHANGEME.YOURDOMAIN.TLD", 64 | "server min protocol": "SMB2", 65 | "idmap config * : backend": "autorid", 66 | "idmap config * : range": "2000-9999999" 67 | } 68 | }, 69 | "vfs_fileid": { 70 | "options": { 71 | "vfs objects": "fileid", 72 | "fileid:algorithm": "fsid" 73 | } 74 | } 75 | } 76 | } 77 | --- 78 | # Secret used to pass a AD join password to the pod. 79 | apiVersion: v1 80 | kind: Secret 81 | metadata: 82 | name: ad-join-secret 83 | type: Opaque 84 | stringData: 85 | # Change the value below to match the username and password for a user that 86 | # can join systems your test AD Domain 87 | join.json: | 88 | {"username": "Administrator", "password": "Passw0rd"} 89 | --- 90 | apiVersion: v1 91 | kind: PersistentVolumeClaim 92 | metadata: 93 | name: ctdb-shared-swc 94 | spec: 95 | accessModes: 96 | - ReadWriteMany 97 | storageClassName: rook-cephfs 98 | resources: 99 | requests: 100 | storage: 1Gi 101 | --- 102 | apiVersion: v1 103 | kind: PersistentVolumeClaim 104 | metadata: 105 | name: samba-share-data-swc 106 | spec: 107 | accessModes: 108 | - ReadWriteMany 109 | storageClassName: rook-cephfs 110 | resources: 111 | requests: 112 | storage: 2Gi 113 | --- 114 | apiVersion: v1 115 | kind: Service 116 | metadata: 117 | name: sssamba3-swc 118 | labels: 119 | app: clustered-samba-swc 120 | spec: 121 | ports: 122 | - port: 445 123 | name: smb 124 | clusterIP: None 125 | selector: 126 | app: clustered-samba-swc 127 | --- 128 | apiVersion: apps/v1 129 | kind: StatefulSet 130 | metadata: 131 | name: clustered-samba-swc 132 | spec: 133 | serviceName: "sssamba3-swc" 134 | replicas: 3 135 | selector: 136 | matchLabels: 137 | app: clustered-samba-swc 138 | template: 139 | metadata: 140 | labels: 141 | app: clustered-samba-swc 142 | spec: 143 | shareProcessNamespace: true 144 | initContainers: 145 | - image: quay.io/samba.org/samba-server:latest 146 | imagePullPolicy: Always 147 | name: init 148 | args: 149 | - "--config=/etc/samba-container/config.json" 150 | - "--id=demo" 151 | - "--skip-if-file=/var/lib/ctdb/shared/nodes" 152 | - "init" 153 | env: [] 154 | securityContext: 155 | allowPrivilegeEscalation: true 156 | volumeMounts: 157 | - mountPath: "/etc/samba-container" 158 | name: samba-container-config 159 | - mountPath: "/var/lib/samba" 160 | name: samba-state-dir 161 | - mountPath: "/var/lib/ctdb/shared" 162 | name: ctdb-shared 163 | - image: quay.io/samba.org/samba-server:latest 164 | imagePullPolicy: Always 165 | name: import 166 | args: 167 | - "--config=/etc/samba-container/config.json" 168 | - "--id=demo" 169 | - "--skip-if-file=/var/lib/ctdb/shared/nodes" 170 | - "import" 171 | securityContext: 172 | allowPrivilegeEscalation: true 173 | volumeMounts: 174 | - mountPath: "/etc/samba-container" 175 | name: samba-container-config 176 | - mountPath: "/var/lib/samba" 177 | name: samba-state-dir 178 | - mountPath: "/var/lib/ctdb/shared" 179 | name: ctdb-shared 180 | - image: quay.io/samba.org/samba-server:latest 181 | imagePullPolicy: Always 182 | name: must-join 183 | args: 184 | - "--config=/etc/samba-container/config.json" 185 | - "--id=demo" 186 | - "--skip-if-file=/var/lib/ctdb/shared/nodes" 187 | - "must-join" 188 | - "--files" 189 | - "--join-file=/etc/join-data/join.json" 190 | securityContext: 191 | allowPrivilegeEscalation: true 192 | volumeMounts: 193 | - mountPath: "/etc/samba-container" 194 | name: samba-container-config 195 | - mountPath: "/var/lib/samba" 196 | name: samba-state-dir 197 | - mountPath: "/var/lib/ctdb/shared" 198 | name: ctdb-shared 199 | - mountPath: "/etc/join-data" 200 | name: samba-join-data 201 | readOnly: true 202 | - image: quay.io/samba.org/samba-server:latest 203 | imagePullPolicy: Always 204 | name: ctdb-migrate 205 | args: 206 | - "--config=/etc/samba-container/config.json" 207 | - "--id=demo" 208 | - "--skip-if-file=/var/lib/ctdb/shared/nodes" 209 | - "ctdb-migrate" 210 | - "--dest-dir=/var/lib/ctdb/persistent" 211 | env: 212 | - name: SAMBACC_CTDB 213 | value: "ctdb-is-experimental" 214 | securityContext: 215 | allowPrivilegeEscalation: true 216 | volumeMounts: 217 | - mountPath: "/etc/samba-container" 218 | name: samba-container-config 219 | - mountPath: "/var/lib/samba" 220 | name: samba-state-dir 221 | - mountPath: "/var/lib/ctdb/persistent" 222 | name: ctdb-persistent 223 | - mountPath: "/var/lib/ctdb/shared" 224 | name: ctdb-shared 225 | - image: quay.io/samba.org/samba-server:latest 226 | imagePullPolicy: Always 227 | name: ctdb-set-node 228 | args: 229 | - "--config=/etc/samba-container/config.json" 230 | - "--id=demo" 231 | - "ctdb-set-node" 232 | - "--hostname=$(HOSTNAME)" 233 | - "--take-node-number-from-hostname=after-last-dash" 234 | env: 235 | - name: SAMBACC_CTDB 236 | value: "ctdb-is-experimental" 237 | - name: HOSTNAME 238 | valueFrom: 239 | fieldRef: 240 | fieldPath: metadata.name 241 | securityContext: 242 | allowPrivilegeEscalation: true 243 | volumeMounts: 244 | - mountPath: "/etc/samba-container" 245 | name: samba-container-config 246 | - mountPath: "/var/lib/ctdb/shared" 247 | name: ctdb-shared 248 | - mountPath: "/etc/ctdb" 249 | name: ctdb-config 250 | - image: quay.io/samba.org/samba-server:latest 251 | imagePullPolicy: Always 252 | name: ctdb-must-have-node 253 | args: 254 | - "--config=/etc/samba-container/config.json" 255 | - "--id=demo" 256 | - "ctdb-must-have-node" 257 | - "--hostname=$(HOSTNAME)" 258 | - "--take-node-number-from-hostname=after-last-dash" 259 | env: 260 | - name: SAMBACC_CTDB 261 | value: "ctdb-is-experimental" 262 | - name: HOSTNAME 263 | valueFrom: 264 | fieldRef: 265 | fieldPath: metadata.name 266 | securityContext: 267 | allowPrivilegeEscalation: true 268 | volumeMounts: 269 | - mountPath: "/etc/samba-container" 270 | name: samba-container-config 271 | - mountPath: "/var/lib/ctdb/shared" 272 | name: ctdb-shared 273 | - mountPath: "/etc/ctdb" 274 | name: ctdb-config 275 | containers: 276 | - image: quay.io/samba.org/samba-server:latest 277 | imagePullPolicy: Always 278 | name: ctdb 279 | args: 280 | - "--config=/etc/samba-container/config.json" 281 | - "--id=demo" 282 | - "--debug-delay=2" 283 | - "run" 284 | - "ctdbd" 285 | - "--setup=smb_ctdb" 286 | - "--setup=ctdb_config" 287 | - "--setup=ctdb_etc" 288 | - "--setup=ctdb_nodes" 289 | securityContext: 290 | capabilities: 291 | add: 292 | - NET_RAW 293 | env: 294 | - name: SAMBACC_CTDB 295 | value: "ctdb-is-experimental" 296 | volumeMounts: 297 | - mountPath: "/etc/samba-container" 298 | name: samba-container-config 299 | - mountPath: "/var/lib/ctdb/shared" 300 | name: ctdb-shared 301 | - mountPath: "/var/lib/ctdb/persistent" 302 | name: ctdb-persistent 303 | - mountPath: "/var/lib/ctdb/volatile" 304 | name: ctdb-volatile 305 | - mountPath: "/etc/ctdb" 306 | name: ctdb-config 307 | - mountPath: "/var/run/ctdb" 308 | name: ctdb-sockets-dir 309 | - image: quay.io/samba.org/samba-server:latest 310 | imagePullPolicy: Always 311 | name: ctdb-manage-nodes 312 | args: 313 | - "--config=/etc/samba-container/config.json" 314 | - "--id=demo" 315 | - "ctdb-manage-nodes" 316 | - "--hostname=$(HOSTNAME)" 317 | - "--take-node-number-from-hostname=after-last-dash" 318 | env: 319 | - name: SAMBACC_CTDB 320 | value: "ctdb-is-experimental" 321 | - name: HOSTNAME 322 | valueFrom: 323 | fieldRef: 324 | fieldPath: metadata.name 325 | volumeMounts: 326 | - mountPath: "/etc/samba-container" 327 | name: samba-container-config 328 | - mountPath: "/var/lib/ctdb/shared" 329 | name: ctdb-shared 330 | - mountPath: "/etc/ctdb" 331 | name: ctdb-config 332 | - mountPath: "/var/run/ctdb" 333 | name: ctdb-sockets-dir 334 | - image: quay.io/samba.org/samba-server:latest 335 | imagePullPolicy: Always 336 | name: smb 337 | args: 338 | - "--config=/etc/samba-container/config.json" 339 | - "--id=demo" 340 | - "--debug-delay=12" 341 | - "run" 342 | - "smbd" 343 | - "--setup=nsswitch" 344 | - "--setup=smb_ctdb" 345 | ports: 346 | - containerPort: 445 347 | protocol: TCP 348 | name: "smb" 349 | securityContext: 350 | allowPrivilegeEscalation: true 351 | volumeMounts: 352 | - mountPath: "/etc/samba-container" 353 | name: samba-container-config 354 | - mountPath: "/share" 355 | name: samba-share-data 356 | - mountPath: "/var/lib/samba" 357 | name: samba-state-dir 358 | - mountPath: "/var/lib/ctdb/shared" 359 | name: ctdb-shared 360 | - mountPath: "/var/lib/ctdb/persistent" 361 | name: ctdb-persistent 362 | - mountPath: "/var/lib/ctdb/volatile" 363 | name: ctdb-volatile 364 | - mountPath: "/etc/ctdb" 365 | name: ctdb-config 366 | - mountPath: "/var/run/ctdb" 367 | name: ctdb-sockets-dir 368 | - mountPath: "/run/samba/winbindd" 369 | name: samba-sockets-dir 370 | - image: quay.io/samba.org/samba-server:latest 371 | name: winbind 372 | args: 373 | - "--config=/etc/samba-container/config.json" 374 | - "--id=demo" 375 | - "--debug-delay=10" 376 | - "run" 377 | - "winbindd" 378 | - "--setup=nsswitch" 379 | - "--setup=smb_ctdb" 380 | securityContext: 381 | allowPrivilegeEscalation: true 382 | volumeMounts: 383 | - mountPath: "/etc/samba-container" 384 | name: samba-container-config 385 | - mountPath: "/var/lib/samba" 386 | name: samba-state-dir 387 | - mountPath: "/var/lib/ctdb/shared" 388 | name: ctdb-shared 389 | - mountPath: "/var/lib/ctdb/persistent" 390 | name: ctdb-persistent 391 | - mountPath: "/var/lib/ctdb/volatile" 392 | name: ctdb-volatile 393 | - mountPath: "/etc/ctdb" 394 | name: ctdb-config 395 | - mountPath: "/var/run/ctdb" 396 | name: ctdb-sockets-dir 397 | - mountPath: "/run/samba/winbindd" 398 | name: samba-sockets-dir 399 | volumes: 400 | # /etc/ctdb 401 | - emptyDir: {} 402 | name: ctdb-config 403 | # /var/lib/ctdb/persistent 404 | - emptyDir: {} 405 | name: ctdb-persistent 406 | # /var/lib/ctdb/volatile 407 | - emptyDir: {} 408 | name: ctdb-volatile 409 | # /var/lib/ctdb/shared 410 | - persistentVolumeClaim: 411 | claimName: ctdb-shared-swc 412 | name: ctdb-shared 413 | # /var/run/ctdb 414 | - emptyDir: 415 | medium: Memory 416 | name: ctdb-sockets-dir 417 | # /var/lib/samba 418 | - emptyDir: {} 419 | name: samba-state-dir 420 | # /share 421 | - persistentVolumeClaim: 422 | claimName: samba-share-data-swc 423 | name: samba-share-data 424 | - emptyDir: 425 | medium: Memory 426 | name: samba-sockets-dir 427 | - configMap: 428 | name: samba-container-config-swc 429 | name: samba-container-config 430 | - secret: 431 | secretName: ad-join-secret 432 | items: 433 | - key: join.json 434 | path: join.json 435 | name: samba-join-data 436 | -------------------------------------------------------------------------------- /examples/kubernetes/samba-ctdb-sset.yml: -------------------------------------------------------------------------------- 1 | # 2 | # An example of running samba with ctdb replication as a kubernetes 3 | # StatefulSet. 4 | # 5 | # This is *highly experimental* and not meant for real use. Use only if you're 6 | # interested in helping test or develop samba-container/sambacc CTDB support. 7 | # 8 | # This does not integrate with active directory. 9 | # This directly uses "rook-cephfs" for ReadWriteMany PVCs. If you have some 10 | # other storage class that supports rwx pvcs you need to edit the yaml below. 11 | # This only works with creating a clean set of pvcs & stateful set and scaling 12 | # up. It does *not* currently support pods getting restarted or scaling down. 13 | # 14 | # Use at your own risk, and have fun! 15 | # 16 | --- 17 | apiVersion: v1 18 | kind: PersistentVolumeClaim 19 | metadata: 20 | name: ctdb-shared 21 | spec: 22 | accessModes: 23 | - ReadWriteMany 24 | storageClassName: rook-cephfs 25 | resources: 26 | requests: 27 | storage: 1Gi 28 | --- 29 | apiVersion: v1 30 | kind: PersistentVolumeClaim 31 | metadata: 32 | name: samba-share-data 33 | spec: 34 | accessModes: 35 | - ReadWriteMany 36 | storageClassName: rook-cephfs 37 | resources: 38 | requests: 39 | storage: 2Gi 40 | --- 41 | apiVersion: v1 42 | kind: Service 43 | metadata: 44 | name: sssamba 45 | labels: 46 | app: clustered-samba 47 | spec: 48 | ports: 49 | - port: 445 50 | name: smb 51 | clusterIP: None 52 | selector: 53 | app: clustered-samba 54 | --- 55 | apiVersion: apps/v1 56 | kind: StatefulSet 57 | metadata: 58 | name: clustered-samba 59 | spec: 60 | serviceName: "sssamba" 61 | replicas: 3 62 | selector: 63 | matchLabels: 64 | app: clustered-samba 65 | template: 66 | metadata: 67 | labels: 68 | app: clustered-samba 69 | spec: 70 | shareProcessNamespace: true 71 | initContainers: 72 | - image: quay.io/samba.org/samba-server:latest 73 | imagePullPolicy: Always 74 | name: init 75 | args: 76 | - "--config=/usr/local/share/sambacc/examples/ctdb.json" 77 | - "--id=demo" 78 | - "--skip-if-file=/var/lib/ctdb/shared/nodes" 79 | - "init" 80 | env: [] 81 | securityContext: 82 | allowPrivilegeEscalation: true 83 | volumeMounts: 84 | - mountPath: "/var/lib/samba" 85 | name: samba-state-dir 86 | - mountPath: "/var/lib/ctdb/shared" 87 | name: ctdb-shared 88 | - image: quay.io/samba.org/samba-server:latest 89 | imagePullPolicy: Always 90 | name: import 91 | args: 92 | - "--config=/usr/local/share/sambacc/examples/ctdb.json" 93 | - "--id=demo" 94 | - "--skip-if-file=/var/lib/ctdb/shared/nodes" 95 | - "import" 96 | securityContext: 97 | allowPrivilegeEscalation: true 98 | volumeMounts: 99 | - mountPath: "/var/lib/samba" 100 | name: samba-state-dir 101 | - mountPath: "/var/lib/ctdb/shared" 102 | name: ctdb-shared 103 | - image: quay.io/samba.org/samba-server:latest 104 | imagePullPolicy: Always 105 | name: import-users 106 | args: 107 | - "--config=/usr/local/share/sambacc/examples/ctdb.json" 108 | - "--id=demo" 109 | - "--skip-if-file=/var/lib/ctdb/shared/nodes" 110 | - "import-users" 111 | securityContext: 112 | allowPrivilegeEscalation: true 113 | volumeMounts: 114 | - mountPath: "/var/lib/samba" 115 | name: samba-state-dir 116 | - mountPath: "/var/lib/ctdb/shared" 117 | name: ctdb-shared 118 | - image: quay.io/samba.org/samba-server:latest 119 | imagePullPolicy: Always 120 | name: ctdb-migrate 121 | args: 122 | - "--config=/usr/local/share/sambacc/examples/ctdb.json" 123 | - "--id=demo" 124 | - "--skip-if-file=/var/lib/ctdb/shared/nodes" 125 | - "ctdb-migrate" 126 | - "--dest-dir=/var/lib/ctdb/persistent" 127 | env: 128 | - name: SAMBACC_CTDB 129 | value: "ctdb-is-experimental" 130 | securityContext: 131 | allowPrivilegeEscalation: true 132 | volumeMounts: 133 | - mountPath: "/var/lib/samba" 134 | name: samba-state-dir 135 | - mountPath: "/var/lib/ctdb/persistent" 136 | name: ctdb-persistent 137 | - mountPath: "/var/lib/ctdb/shared" 138 | name: ctdb-shared 139 | - image: quay.io/samba.org/samba-server:latest 140 | imagePullPolicy: Always 141 | name: ctdb-set-node 142 | args: 143 | - "--config=/usr/local/share/sambacc/examples/ctdb.json" 144 | - "--id=demo" 145 | - "ctdb-set-node" 146 | - "--hostname=$(HOSTNAME)" 147 | - "--take-node-number-from-hostname=after-last-dash" 148 | env: 149 | - name: SAMBACC_CTDB 150 | value: "ctdb-is-experimental" 151 | - name: HOSTNAME 152 | valueFrom: 153 | fieldRef: 154 | fieldPath: metadata.name 155 | securityContext: 156 | allowPrivilegeEscalation: true 157 | volumeMounts: 158 | - mountPath: "/var/lib/ctdb/shared" 159 | name: ctdb-shared 160 | - mountPath: "/etc/ctdb" 161 | name: ctdb-config 162 | - image: quay.io/samba.org/samba-server:latest 163 | imagePullPolicy: Always 164 | name: ctdb-must-have-node 165 | args: 166 | - "--config=/usr/local/share/sambacc/examples/ctdb.json" 167 | - "--id=demo" 168 | - "ctdb-must-have-node" 169 | - "--hostname=$(HOSTNAME)" 170 | - "--take-node-number-from-hostname=after-last-dash" 171 | env: 172 | - name: SAMBACC_CTDB 173 | value: "ctdb-is-experimental" 174 | - name: HOSTNAME 175 | valueFrom: 176 | fieldRef: 177 | fieldPath: metadata.name 178 | securityContext: 179 | allowPrivilegeEscalation: true 180 | volumeMounts: 181 | - mountPath: "/var/lib/ctdb/shared" 182 | name: ctdb-shared 183 | - mountPath: "/etc/ctdb" 184 | name: ctdb-config 185 | containers: 186 | - image: quay.io/samba.org/samba-server:latest 187 | imagePullPolicy: Always 188 | name: ctdb 189 | args: 190 | - "--config=/usr/local/share/sambacc/examples/ctdb.json" 191 | - "--id=demo" 192 | - "--debug-delay=2" 193 | - "run" 194 | - "ctdbd" 195 | - "--setup=smb_ctdb" 196 | - "--setup=ctdb_config" 197 | - "--setup=ctdb_etc" 198 | - "--setup=ctdb_nodes" 199 | env: 200 | - name: SAMBACC_CTDB 201 | value: "ctdb-is-experimental" 202 | volumeMounts: 203 | - mountPath: "/var/lib/ctdb/shared" 204 | name: ctdb-shared 205 | - mountPath: "/var/lib/ctdb/persistent" 206 | name: ctdb-persistent 207 | - mountPath: "/var/lib/ctdb/volatile" 208 | name: ctdb-volatile 209 | - mountPath: "/etc/ctdb" 210 | name: ctdb-config 211 | - mountPath: "/var/run/ctdb" 212 | name: ctdb-sockets-dir 213 | - image: quay.io/samba.org/samba-server:latest 214 | imagePullPolicy: Always 215 | name: ctdb-manage-nodes 216 | args: 217 | - "--config=/usr/local/share/sambacc/examples/ctdb.json" 218 | - "--id=demo" 219 | - "ctdb-manage-nodes" 220 | - "--hostname=$(HOSTNAME)" 221 | - "--take-node-number-from-hostname=after-last-dash" 222 | env: 223 | - name: SAMBACC_CTDB 224 | value: "ctdb-is-experimental" 225 | - name: HOSTNAME 226 | valueFrom: 227 | fieldRef: 228 | fieldPath: metadata.name 229 | volumeMounts: 230 | - mountPath: "/var/lib/ctdb/shared" 231 | name: ctdb-shared 232 | - mountPath: "/etc/ctdb" 233 | name: ctdb-config 234 | - mountPath: "/var/run/ctdb" 235 | name: ctdb-sockets-dir 236 | - image: quay.io/samba.org/samba-server:latest 237 | imagePullPolicy: Always 238 | name: smb 239 | args: 240 | - "--config=/usr/local/share/sambacc/examples/ctdb.json" 241 | - "--id=demo" 242 | - "--debug-delay=12" 243 | - "run" 244 | - "smbd" 245 | - "--setup=users" 246 | - "--setup=smb_ctdb" 247 | ports: 248 | - containerPort: 445 249 | protocol: TCP 250 | name: "smb" 251 | securityContext: 252 | allowPrivilegeEscalation: true 253 | volumeMounts: 254 | - mountPath: "/share" 255 | name: samba-share-data 256 | - mountPath: "/var/lib/ctdb/shared" 257 | name: ctdb-shared 258 | - mountPath: "/var/lib/ctdb/persistent" 259 | name: ctdb-persistent 260 | - mountPath: "/var/lib/ctdb/volatile" 261 | name: ctdb-volatile 262 | - mountPath: "/etc/ctdb" 263 | name: ctdb-config 264 | - mountPath: "/var/run/ctdb" 265 | name: ctdb-sockets-dir 266 | volumes: 267 | # /etc/ctdb 268 | - emptyDir: {} 269 | name: ctdb-config 270 | # /var/lib/ctdb/persistent 271 | - emptyDir: {} 272 | name: ctdb-persistent 273 | # /var/lib/ctdb/volatile 274 | - emptyDir: {} 275 | name: ctdb-volatile 276 | # /var/lib/ctdb/shared 277 | - persistentVolumeClaim: 278 | claimName: ctdb-shared 279 | name: ctdb-shared 280 | # /var/run/ctdb 281 | - emptyDir: 282 | medium: Memory 283 | name: ctdb-sockets-dir 284 | # /var/lib/samba 285 | - emptyDir: {} 286 | name: samba-state-dir 287 | # /share 288 | - persistentVolumeClaim: 289 | claimName: samba-share-data 290 | name: samba-share-data 291 | -------------------------------------------------------------------------------- /examples/kubernetes/sambadeployment.converged.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: samba-pvc-deployment 6 | labels: 7 | app: samba 8 | spec: 9 | replicas: 1 10 | selector: 11 | matchLabels: 12 | app: samba 13 | template: 14 | metadata: 15 | labels: 16 | app: samba 17 | spec: 18 | volumes: 19 | - name: myvol 20 | persistentVolumeClaim: 21 | claimName: mypvc 22 | containers: 23 | - name: samba 24 | image: quay.io/samba.org/samba-server:latest 25 | ports: 26 | - containerPort: 445 27 | volumeMounts: 28 | - mountPath: "/share" 29 | name: myvol 30 | --- 31 | apiVersion: v1 32 | kind: PersistentVolumeClaim 33 | metadata: 34 | name: mypvc 35 | spec: 36 | storageClassName: manual 37 | accessModes: 38 | - ReadWriteOnce 39 | resources: 40 | requests: 41 | storage: 1Gi 42 | --- 43 | apiVersion: v1 44 | kind: PersistentVolume 45 | metadata: 46 | name: mypv 47 | labels: 48 | type: local 49 | spec: 50 | storageClassName: manual 51 | capacity: 52 | storage: 1Gi 53 | accessModes: 54 | - ReadWriteOnce 55 | hostPath: 56 | path: "/mnt/pv" 57 | -------------------------------------------------------------------------------- /examples/kubernetes/sambadeployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: samba-pvc-deployment 5 | labels: 6 | app: samba 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: samba 12 | template: 13 | metadata: 14 | labels: 15 | app: samba 16 | spec: 17 | volumes: 18 | - name: myvol 19 | persistentVolumeClaim: 20 | claimName: mypvc 21 | containers: 22 | - name: samba 23 | image: quay.io/samba.org/samba-server:latest 24 | ports: 25 | - containerPort: 445 26 | volumeMounts: 27 | - mountPath: "/share" 28 | name: myvol 29 | -------------------------------------------------------------------------------- /examples/kubernetes/sambadmpod.yml: -------------------------------------------------------------------------------- 1 | # 2 | # A Samba smbd + winbindd pod that automatically becomes a domain member. 3 | # This setup requires the config map "samba-conainer-config" to match 4 | # your test domain. It requires the Administrator password to be present 5 | # in the "ad-join-secret" secret. 6 | # 7 | # This configuration assumes you can reach your AD's DNS via the normal 8 | # Kubernetes DNS configuration. If not you may wish to look into the 9 | # customizing the Pod DNS settings or Kubernetes DNS customization. 10 | # 11 | # Edit the lines below that contain "CHANGEME" and make them match 12 | # your domain's setting. 13 | # 14 | # Edit the string value for "JOIN_PASSWORD" in the secret below and 15 | # make sure it matches your domain administrator's password. 16 | # 17 | # You can tweak the samba-sharedir volume under "volumes" at the end 18 | # of the pod yaml below. Use this to toggle between a temporary share 19 | # or a PVC backed share. 20 | # 21 | # NOTE: All settings below can be modified but those mentioned above 22 | # will get you a running container more quickly, feel free to start 23 | # there and then begin tinkering! 24 | # 25 | --- 26 | # Configuration for the samba domain member pod. 27 | apiVersion: v1 28 | kind: ConfigMap 29 | metadata: 30 | name: samba-container-config 31 | data: 32 | config.json: | 33 | { 34 | "samba-container-config": "v0", 35 | "configs": { 36 | "sambadm1": { 37 | "shares": [ 38 | "share" 39 | ], 40 | "globals": [ 41 | "noprinting", 42 | "sambadm1" 43 | ], 44 | "instance_name": "SMBDM1" 45 | } 46 | }, 47 | "shares": { 48 | "share": { 49 | "options": { 50 | "path": "/share", 51 | "read only": "no" 52 | } 53 | } 54 | }, 55 | "_NOTE": "Change the security and workgroup keys to match your domain.", 56 | "globals": { 57 | "noprinting": { 58 | "options": { 59 | "load printers": "no", 60 | "printing": "bsd", 61 | "printcap name": "/dev/null", 62 | "disable spoolss": "yes" 63 | } 64 | }, 65 | "sambadm1": { 66 | "options": { 67 | "log level": "10", 68 | "security": "ads", 69 | "workgroup": "CHANGEME", 70 | "realm": "CHANGEME.YOURDOMAIN.TLD", 71 | "server min protocol": "SMB2", 72 | "idmap config * : backend": "autorid", 73 | "idmap config * : range": "2000-9999999" 74 | } 75 | } 76 | } 77 | } 78 | --- 79 | # Secret used to pass a AD join password to the winbind pod. 80 | apiVersion: v1 81 | kind: Secret 82 | metadata: 83 | name: ad-join-secret 84 | type: Opaque 85 | stringData: 86 | # Change the value below to match the username and password for a user that 87 | # can join systems your test AD Domain 88 | join.json: | 89 | {"username": "Administrator", "password": "Passw0rd"} 90 | --- 91 | # The pod itself. 92 | apiVersion: v1 93 | kind: Pod 94 | metadata: 95 | labels: 96 | app: samba-dm-example 97 | name: samba-dm 98 | spec: 99 | shareProcessNamespace: true 100 | containers: 101 | - image: quay.io/samba.org/samba-server:latest 102 | name: smb 103 | command: 104 | - "samba-container" 105 | - "--debug-delay=1" 106 | - "run" 107 | - "smbd" 108 | env: 109 | - name: SAMBACC_CONFIG 110 | value: /etc/samba-container/config.json 111 | - name: SAMBA_CONTAINER_ID 112 | value: sambadm1 113 | - name: SAMBACC_VERSION 114 | value: "0.1" 115 | - name: HOSTNAME 116 | value: sambadm1 117 | ports: 118 | - containerPort: 445 119 | hostPort: 455 120 | protocol: TCP 121 | name: "smb" 122 | securityContext: 123 | allowPrivilegeEscalation: true 124 | volumeMounts: 125 | - mountPath: "/share" 126 | name: samba-sharedir 127 | - mountPath: "/etc/samba-container" 128 | name: samba-container-config 129 | - mountPath: "/var/lib/samba" 130 | name: samba-state-dir 131 | - mountPath: "/run/samba/winbindd" 132 | name: samba-sockets-dir 133 | - image: quay.io/samba.org/samba-server:latest 134 | name: winbind 135 | command: 136 | - "samba-container" 137 | - "run" 138 | - "winbindd" 139 | env: 140 | - name: SAMBACC_VERSION 141 | value: "0.1" 142 | - name: SAMBACC_CONFIG 143 | value: /etc/samba-container/config.json 144 | - name: SAMBA_CONTAINER_ID 145 | value: sambadm1 146 | - name: HOSTNAME 147 | value: sambadm1 148 | securityContext: 149 | allowPrivilegeEscalation: true 150 | volumeMounts: 151 | - mountPath: "/etc/samba-container" 152 | name: samba-container-config 153 | - mountPath: "/var/lib/samba" 154 | name: samba-state-dir 155 | - mountPath: "/run/samba/winbindd" 156 | name: samba-sockets-dir 157 | initContainers: 158 | - image: quay.io/samba.org/samba-server:latest 159 | name: init 160 | args: 161 | - "init" 162 | env: 163 | - name: SAMBACC_VERSION 164 | value: "0.1" 165 | - name: SAMBACC_CONFIG 166 | value: /etc/samba-container/config.json 167 | - name: SAMBA_CONTAINER_ID 168 | value: sambadm1 169 | - name: HOSTNAME 170 | value: sambadm1 171 | securityContext: 172 | allowPrivilegeEscalation: true 173 | volumeMounts: 174 | - mountPath: "/etc/samba-container" 175 | name: samba-container-config 176 | - mountPath: "/var/lib/samba" 177 | name: samba-state-dir 178 | - image: quay.io/samba.org/samba-server:latest 179 | name: must-join 180 | args: 181 | - "must-join" 182 | - "--files" 183 | - "--join-file=/etc/join-data/join.json" 184 | env: 185 | - name: SAMBACC_VERSION 186 | value: "0.1" 187 | - name: SAMBACC_CONFIG 188 | value: /etc/samba-container/config.json 189 | - name: SAMBA_CONTAINER_ID 190 | value: sambadm1 191 | - name: HOSTNAME 192 | value: sambadm1 193 | securityContext: 194 | allowPrivilegeEscalation: true 195 | volumeMounts: 196 | - mountPath: "/etc/samba-container" 197 | name: samba-container-config 198 | - mountPath: "/var/lib/samba" 199 | name: samba-state-dir 200 | - mountPath: "/etc/join-data" 201 | name: samba-join-data 202 | readOnly: true 203 | volumes: 204 | - configMap: 205 | name: samba-container-config 206 | name: samba-container-config 207 | - secret: 208 | secretName: ad-join-secret 209 | items: 210 | - key: join.json 211 | path: join.json 212 | name: samba-join-data 213 | - emptyDir: 214 | medium: Memory 215 | name: samba-sockets-dir 216 | - emptyDir: {} 217 | name: samba-state-dir 218 | # Comment out the section below to skip using a PVC for the share 219 | - persistentVolumeClaim: 220 | claimName: mypvc 221 | name: samba-sharedir 222 | # Uncomment the section below to use an empty dir for the share 223 | # - emptyDir: 224 | # medium: Memory 225 | # name: samba-sharedir 226 | -------------------------------------------------------------------------------- /examples/kubernetes/sambapod.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: sambapod 5 | spec: 6 | volumes: 7 | - name: myvol 8 | persistentVolumeClaim: 9 | claimName: mypvc 10 | containers: 11 | - name: mycontainer 12 | image: quay.io/samba.org/samba-server:latest 13 | ports: 14 | - containerPort: 445 15 | name: "samba445" 16 | volumeMounts: 17 | - mountPath: "/share" 18 | name: myvol 19 | -------------------------------------------------------------------------------- /examples/podman/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Podman Examples 3 | 4 | These examples demonstrate using samba container images with podman. 5 | 6 | ## Domain Joined SMB Shares 7 | 8 | Included here is a shell script and a JSON config template that demonstrates 9 | using podman to run an smbd instance joined to Active Directory. Do note that 10 | the Active Directory in question must already exist and permit new joins using 11 | the Administrator account. You *must* edit the provided files to match your 12 | domain/environment. 13 | 14 | If you plan to run the pod with rootless podman do note that the smbd processes 15 | make use of the setuid and setgroups system apis. Rootless podman is restricted 16 | to a limited set of ids that are controlled by /etc/subuid and /etc/subgid. If 17 | the ID range configured for winbind exceed these limits the smbd process will 18 | panic when the user connects to the share. See the 19 | [rootless podman documentation](https://github.com/containers/podman/blob/master/docs/tutorials/rootless_tutorial.md#etcsubuid-and-etcsubgid-configuration) 20 | for more detail on this subject. 21 | 22 | Example: 23 | ``` 24 | cd ./examples/podman 25 | # configure the example config for your domain: 26 | $EDITOR config.json 27 | # tweak script parameters for your environment: 28 | $EDITOR smb-wb-pod.sh 29 | 30 | ./smb-wb-pod.sh /tmp/samba-container-demo start 31 | # wait a little bit 32 | smbclient --port 4450 -U 'DOM\User%Pass' //localhost/share 33 | 34 | # stop it 35 | ./smb-wb-pod.sh /tmp/samba-container-demo stop 36 | 37 | # clean up working dir 38 | ./smb-wb-pod.sh /tmp/samba-container-demo clean 39 | ``` 40 | 41 | -------------------------------------------------------------------------------- /examples/podman/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "samba-container-config": "v0", 3 | "configs": { 4 | "wbtest": { 5 | "shares": [ 6 | "share" 7 | ], 8 | "globals": [ 9 | "noprinting", 10 | "wbtest" 11 | ], 12 | "instance_name": "WB1" 13 | } 14 | }, 15 | "shares": { 16 | "share": { 17 | "options": { 18 | "path": "/share", 19 | "read only": "no" 20 | } 21 | } 22 | }, 23 | "_NOTE": "Change the security and workgroup keys to match your domain.", 24 | "globals": { 25 | "noprinting": { 26 | "options": { 27 | "load printers": "no", 28 | "printing": "bsd", 29 | "printcap name": "/dev/null", 30 | "disable spoolss": "yes" 31 | } 32 | }, 33 | "wbtest": { 34 | "options": { 35 | "log level": "10", 36 | "security": "ads", 37 | "workgroup": "CHANGEME", 38 | "realm": "CHANGEME.YOURDOMAIN.TLD", 39 | "server min protocol": "SMB2", 40 | "idmap config * : backend": "autorid", 41 | "idmap config * : range": "2000-9999999" 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /examples/podman/smb-wb-pod.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # This script demonstrates using podman's pods feature to run a smbd 4 | # and winbind container together, configured via samba-container json. 5 | # It automatically joins the domain with the password specified below. 6 | # We don't currently have a secure containerized join so please only 7 | # use this on scratch testing domains. 8 | 9 | set -e 10 | 11 | # NOTE: This script depnds on the sambacc config json to: 12 | # a) Reside in the same directory as this script 13 | # b) Be configured for your AD domain settings 14 | 15 | #-- user settable options --- 16 | # 17 | # The container image to use 18 | image=quay.io/samba.org/samba-server:latest 19 | # The name of the pod 20 | name=domsamba 21 | # The port that 445 will be mapped to 22 | pubport=4450 23 | # Use the following vars to customize the podman cli for your particular 24 | # environment 25 | podextraopts=() 26 | ctrextraopts=() 27 | # The AD administrator password for INSECURE join 28 | ad_password="Passw0rd" 29 | #---------------------------- 30 | 31 | workdir="$1" 32 | 33 | case "$2" in 34 | start) 35 | set -x 36 | 37 | mkdir -p "${workdir}"/state/private 38 | mkdir -p "${workdir}"/wbsockets 39 | mkdir -p "${workdir}"/config 40 | mkdir -p "${workdir}"/share 41 | chmod 0755 "${workdir}"/wbsockets 42 | chmod 0777 "${workdir}"/share 43 | cp config.json "${workdir}"/config/config.json 44 | 45 | podman pod create \ 46 | --hostname="${name}" \ 47 | --name="${name}" \ 48 | --share=pid,uts,net \ 49 | --publish="${pubport}:445" \ 50 | "${podextraopts[@]}" 51 | podman pod start "${name}" 52 | 53 | podman container run \ 54 | --detach \ 55 | --pod="${name}" \ 56 | --name="${name}-wb" \ 57 | -v "${workdir}/config":/usr/local/etc \ 58 | -v "${workdir}/state":/var/lib/samba:z \ 59 | -v "${workdir}/wbsockets":/run/samba/winbindd:z \ 60 | -e SAMBA_CONTAINER_ID="${name}" \ 61 | -e SAMBACC_CONFIG="/usr/local/etc/config.json" \ 62 | "${ctrextraopts[@]}" \ 63 | "${image}" \ 64 | --password="${ad_password}" \ 65 | run \ 66 | --insecure-auto-join \ 67 | winbindd 68 | sleep 1s 69 | podman container run \ 70 | --detach \ 71 | --pod="${name}" \ 72 | --name="${name}-smb" \ 73 | -v "${workdir}/config":/usr/local/etc \ 74 | -v "${workdir}/state":/var/lib/samba:z \ 75 | -v "${workdir}/wbsockets":/run/samba/winbindd:z \ 76 | -v "${workdir}/share":/share:z \ 77 | -e SAMBA_CONTAINER_ID="${name}" \ 78 | -e SAMBACC_CONFIG="/usr/local/etc/config.json" \ 79 | "${ctrextraopts[@]}" \ 80 | "${image}" \ 81 | run \ 82 | smbd 83 | ;; 84 | stop) 85 | podman pod stop wbtest 86 | podman pod rm wbtest 87 | ;; 88 | restart) 89 | "$0" "$1" stop 90 | "$0" "$1" start 91 | ;; 92 | clean) 93 | rm -rf "$workdir" 94 | ;; 95 | *) 96 | echo "Run smb filesharing with domain join in podman" 97 | echo "" 98 | echo "$0 {start,stop,clean}" 99 | echo " workdir: the directory to place shared container data" 100 | echo " start: start the pod" 101 | echo " stop: stop the pod" 102 | echo " restart: stop and then start the pod" 103 | echo " clean: remove the shared workdir" 104 | echo "" 105 | echo "Example:" 106 | echo " $0 /tmp/samba-container-demo start" 107 | ;; 108 | esac 109 | -------------------------------------------------------------------------------- /hack/build-image: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | """ 3 | build-image - A script for building a matrix of samba container images. 4 | 5 | In order to cleanly implement both logic and maintain backwards compatibility 6 | with image naming schemes already in the wild the build-image script 7 | can be used to create "Fully Qualified Image Names" that combine the 8 | image kind (samba-server, client, etc) and a tag that indicates all 9 | the unique properties of the image. This includes the package source, 10 | the base os, and the architecture. 11 | 12 | In addition to building the images, one can push images, list images, 13 | and list build status files (aka buildfiles). 14 | 15 | Usage: 16 | # build an image 17 | ./hack/build-image --kind server --distro-base fedora --arch amd64 18 | 19 | # print out the FQIN 20 | ./hack/build-image --kind samba-server --distro-base fedora \\ 21 | --arch amd64 --print 22 | 23 | # print out the FQIN and additional tags 24 | ./hack/build-image --kind samba-server --distro-base fedora \\ 25 | --arch amd64 --print-tags 26 | 27 | # print out the FQIN and additional tags for multiple images, with 28 | # and without a repository base 29 | ./hack/build-image --kind samba-server \\ 30 | --distro-base fedora \\ 31 | --distro-base centos \\ 32 | --distro-base opensuse \\ 33 | --arch amd64 \\ 34 | --repo-base quay.io/foobar --without-repo-bases --print-tags 35 | 36 | """ 37 | 38 | import argparse 39 | import logging 40 | import os 41 | import pathlib 42 | import platform 43 | import shlex 44 | import shutil 45 | import subprocess 46 | import sys 47 | 48 | 49 | logger = logging.getLogger("build-image") 50 | 51 | # Set FORCE_ARCH_FLAG if you want to test passing the --arch flag to podman all 52 | # the time. This was the previous behavior but we found it to have some issues. 53 | # When this is false the --arch flag is passed to podman ONLY when the target 54 | # arch != the host system arch. 55 | FORCE_ARCH_FLAG = False 56 | 57 | # IMAGE_KINDS - map aliases/names to canonical names for the kinds 58 | # of images we can build 59 | IMG_SERVER = "samba-server" 60 | IMG_AD_SERVER = "samba-ad-server" 61 | IMG_CLIENT = "samba-client" 62 | IMG_TOOLBOX = "samba-toolbox" 63 | IMAGE_KINDS = { 64 | # short names 65 | "server": IMG_SERVER, 66 | "ad-server": IMG_AD_SERVER, 67 | "client": IMG_CLIENT, 68 | "toolbox": IMG_TOOLBOX, 69 | # canonical names 70 | "samba-server": IMG_SERVER, 71 | "samba-ad-server": IMG_AD_SERVER, 72 | "samba-client": IMG_CLIENT, 73 | "samba-toolbox": IMG_TOOLBOX, 74 | } 75 | 76 | # ARCHITECTURES - map supported arch names/alias to canonical names 77 | AMD64 = "amd64" 78 | ARM64 = "arm64" 79 | ARCHITECTURES = { 80 | # alternate names 81 | "x86_64": AMD64, 82 | "aarch64": ARM64, 83 | # canonical names 84 | "amd64": AMD64, 85 | "arm64": ARM64, 86 | } 87 | 88 | # DISTROS - list of supported distro bases 89 | FEDORA = "fedora" 90 | CENTOS = "centos" 91 | OPENSUSE = "opensuse" 92 | DISTROS = [ 93 | FEDORA, 94 | CENTOS, 95 | OPENSUSE, 96 | ] 97 | 98 | # PACKAGE_SOURCES - list of known package sources 99 | DEFAULT = "default" 100 | NIGHTLY = "nightly" 101 | DEVBUILDS = "devbuilds" 102 | PACKAGE_SOURCES = [DEFAULT, NIGHTLY, DEVBUILDS] 103 | 104 | PACKAGES_FROM = { 105 | DEFAULT: "", 106 | NIGHTLY: "samba-nightly", 107 | DEVBUILDS: "devbuilds", 108 | } 109 | 110 | # SOURCE_DIRS - image source paths 111 | # (paths are relative to common image source dir) 112 | SOURCE_DIRS = { 113 | IMG_SERVER: "server", 114 | IMG_AD_SERVER: "ad-server", 115 | IMG_CLIENT: "client", 116 | IMG_TOOLBOX: "toolbox", 117 | } 118 | 119 | DEFAULT_PKG_SOURCES = [DEFAULT] 120 | DEFAULT_DISTRO_BASES = [FEDORA] 121 | LATEST = "latest" 122 | QUAL_NONE = "unqualified" 123 | QUAL_DISTRO = "distro-qualified" 124 | QUAL_FQIN = "fqin" 125 | 126 | 127 | _DISCOVERED_CONTAINER_ENGINES = [] 128 | 129 | 130 | def check_kind(kind): 131 | """Return the canonical name for the image kind or raise a ValueError.""" 132 | try: 133 | return IMAGE_KINDS[kind] 134 | except KeyError: 135 | raise ValueError(f"invalid kind: {kind}") 136 | 137 | 138 | def check_arch(arch): 139 | """Return the canonical name for the arch or raise a ValueError.""" 140 | try: 141 | return ARCHITECTURES[arch] 142 | except KeyError: 143 | raise ValueError(f"invalid arch: {arch}") 144 | 145 | 146 | def check_distro(distro): 147 | """Return the canonical name for a distro base or raise a ValueError.""" 148 | if distro in DISTROS: 149 | return distro 150 | raise ValueError(f"invalid distro: {distro}") 151 | 152 | 153 | def check_pkg_source(source): 154 | """Return the canonical name for a package source or raise a ValueError.""" 155 | if source in PACKAGE_SOURCES: 156 | return source 157 | raise ValueError(f"invalid package source: {source}") 158 | 159 | 160 | def check_repo_base_for(value): 161 | """Return a tuple with a (distro_base, repo_base) pair or raise a 162 | ValueError. 163 | """ 164 | if "=" not in value: 165 | raise ValueError("expected '=' in value") 166 | db, rb = value.split("=", 1) 167 | db = check_distro(db) 168 | return (db, rb) 169 | 170 | 171 | def _cmd_to_str(cmd): 172 | """Format a command for logging.""" 173 | return " ".join(shlex.quote(arg) for arg in cmd) 174 | 175 | 176 | def run(cli, cmd, capture_output=False, check=False): 177 | """Execute a command. Wraps subprocess.run.""" 178 | if cli.dry_run and not capture_output: 179 | logger.info("Would run: %s", _cmd_to_str(cmd)) 180 | return subprocess.CompletedProcess(cmd, 0) 181 | logger.info("Running: %s", _cmd_to_str(cmd)) 182 | return subprocess.run(cmd, capture_output=capture_output, check=check) 183 | 184 | 185 | def container_engine(cli): 186 | """Return the path to a container engine. If the container engine is not 187 | yet known, discover it and cache the result. 188 | """ 189 | eng = cli.container_engine 190 | if eng: 191 | logger.info("Using specified container engine: %s", eng) 192 | return eng 193 | if _DISCOVERED_CONTAINER_ENGINES: 194 | return _DISCOVERED_CONTAINER_ENGINES[0] 195 | podman = shutil.which("podman") 196 | if podman: 197 | _DISCOVERED_CONTAINER_ENGINES.append(podman) 198 | docker = shutil.which("docker") 199 | if docker: 200 | _DISCOVERED_CONTAINER_ENGINES.append(docker) 201 | return _DISCOVERED_CONTAINER_ENGINES[0] 202 | 203 | 204 | def container_build(cli, target): 205 | """Construct and execute a command to build the target container image.""" 206 | eng = container_engine(cli) 207 | tasks = [] 208 | 209 | # For docker cross-builds we need to use buildx 210 | if "docker" in eng and target.arch != host_arch(): 211 | args = [eng, "buildx"] 212 | 213 | # Docker's default builder only supports the host architecture. 214 | # Therefore, we need to create a new builder to support other 215 | # architectures, and we must ensure we start with a fresh builder 216 | # that does not contain any images from previous builds. 217 | tasks.append( 218 | lambda: run(cli, args + ["rm", target.flat_name()], check=False) 219 | ) 220 | tasks.append( 221 | lambda: run( 222 | cli, 223 | args + ["create", f"--name={target.flat_name()}"], 224 | check=True, 225 | ) 226 | ) 227 | 228 | tasks.append( 229 | lambda: run( 230 | cli, 231 | args 232 | + [ 233 | "build", 234 | f"--builder={target.flat_name()}", 235 | f"--platform=linux/{target.arch}", 236 | "--load", 237 | ] 238 | + create_common_container_engine_args(cli, target), 239 | check=True, 240 | ) 241 | ) 242 | 243 | tasks.append( 244 | lambda: run(cli, args + ["rm", target.flat_name()], check=True) 245 | ) 246 | else: 247 | args = [eng, "build"] 248 | if target.arch != host_arch() or FORCE_ARCH_FLAG: 249 | # We've noticed a few small quirks when using podman with the --arch 250 | # option. The main issue is that building the client image works 251 | # but then the toolbox image fails because it somehow doesn't see 252 | # the image we just built as usable. This doesn't happen when 253 | # --arch is not provided. So if the target arch and the host_arch 254 | # are the same, skip passing the extra argument. 255 | args += [f"--arch={target.arch}"] 256 | 257 | tasks.append( 258 | lambda: run( 259 | cli, 260 | args + create_common_container_engine_args(cli, target), 261 | check=True, 262 | ) 263 | ) 264 | 265 | for task in tasks: 266 | task() 267 | 268 | 269 | def create_common_container_engine_args(cli, target): 270 | args = [] 271 | pkgs_from = PACKAGES_FROM[target.pkg_source] 272 | if pkgs_from: 273 | args.append(f"--build-arg=INSTALL_PACKAGES_FROM={pkgs_from}") 274 | if target.pkg_source != DEFAULT: 275 | # consuming a recent samba with new specifics flag for mutex helper 276 | args.append( 277 | "--build-arg=SAMBA_SPECIFICS=" 278 | "daemon_cli_debug_output," 279 | "ctdb_leader_admin_command," 280 | "ctdb_rados_mutex_skip_reg" 281 | ) 282 | 283 | if cli.extra_build_arg: 284 | args.extend(cli.extra_build_arg) 285 | 286 | for tname in target.all_names(baseless=cli.without_repo_bases): 287 | args.append("-t") 288 | args.append(tname) 289 | 290 | args.append("-f") 291 | args.append(target_containerfile(target)) 292 | args.append(kind_source_dir(target.name)) 293 | return [str(a) for a in args] 294 | 295 | 296 | def container_push(cli, push_name): 297 | """Construct and execute a command to push a container image.""" 298 | args = [container_engine(cli), "push", push_name] 299 | run(cli, args, check=True) 300 | 301 | 302 | def container_id(cli, target): 303 | """Construct and run a command to fetch a hexidecimal id for a container 304 | image. 305 | """ 306 | args = [ 307 | container_engine(cli), 308 | "inspect", 309 | "-f", 310 | "{{.Id}}", 311 | target.image_name(), 312 | ] 313 | res = run(cli, args, capture_output=True, check=True) 314 | return res.stdout.decode("utf8").strip() 315 | 316 | 317 | def container_tag(cli, target, tag, *tags): 318 | """Add additional tags to the existing target image.""" 319 | if isinstance(target, str): 320 | src = target # permit target to be a string w/ the desired source 321 | else: 322 | src = target.image_name() 323 | base_args = [ 324 | container_engine(cli), 325 | "tag", 326 | src, 327 | ] 328 | if "docker" not in base_args[0]: 329 | # podman can do it in one command, docker (on github ci) can not 330 | args = base_args + [tag] + list(tags) 331 | run(cli, args, check=True) 332 | return 333 | for new_tag in [tag] + list(tags): 334 | run(cli, base_args + [new_tag], check=True) 335 | 336 | 337 | def kind_source_dir(kind): 338 | """Return the path to a kind's source directory.""" 339 | return pathlib.Path("images") / SOURCE_DIRS[check_kind(kind)] 340 | 341 | 342 | def target_containerfile(target): 343 | """Return the path to a containerfile given an image target.""" 344 | return str( 345 | kind_source_dir(target.name) / f"Containerfile.{target.distro}" 346 | ) 347 | 348 | 349 | def host_arch(): 350 | """Return the name of the host's native architecture.""" 351 | return check_arch(platform.machine().lower()) 352 | 353 | 354 | def default_arches(): 355 | """Return a list of the default architectures to use for building.""" 356 | return [host_arch()] 357 | 358 | 359 | class RepoConfig: 360 | def __init__(self, default_repo_base, distro_repo=None): 361 | self.default = default_repo_base 362 | self.distro_map = dict(distro_repo or []) 363 | 364 | def find_base(self, distro): 365 | return self.distro_map.get(distro, self.default) 366 | 367 | 368 | class TargetImage: 369 | def __init__( 370 | self, name, pkg_source, distro, arch, extra_tag="", *, repo_base="" 371 | ): 372 | self.name = name 373 | self.pkg_source = pkg_source 374 | self.distro = distro 375 | self.arch = arch 376 | self.extra_tag = extra_tag 377 | self.repo_base = repo_base 378 | self.additional_tags = [] 379 | 380 | def tag_name(self): 381 | tag_parts = [self.pkg_source, self.distro, self.arch] 382 | if self.extra_tag: 383 | tag_parts.append(self.extra_tag) 384 | tag = "-".join(tag_parts) 385 | return tag 386 | 387 | def image_name(self, *, tag=None, repo_base=None): 388 | if not tag: 389 | tag = self.tag_name() 390 | image_name = f"{self.name}:{tag}" 391 | repo_base = repo_base if repo_base is not None else self.repo_base 392 | if repo_base: 393 | repo_base = repo_base.rstrip("/") 394 | image_name = f"{repo_base}/{image_name}" 395 | return image_name 396 | 397 | def flat_name(self): 398 | return f"{self.name}.{self.tag_name()}" 399 | 400 | def __str__(self): 401 | return self.image_name() 402 | 403 | def all_names(self, baseless=False): 404 | yield self.image_name() 405 | for tag, _ in self.additional_tags: 406 | yield self.image_name(tag=tag) 407 | if self.repo_base and baseless: 408 | yield self.image_name(repo_base="") 409 | for tag, qual in self.additional_tags: 410 | if qual == QUAL_NONE: 411 | continue 412 | yield self.image_name(tag=tag, repo_base="") 413 | 414 | @classmethod 415 | def parse(cls, image_name): 416 | if "/" in image_name: 417 | base, rest = image_name.rsplit("/", 1) 418 | else: 419 | base = "" 420 | rest = image_name 421 | iname, tag = rest.split(":", 1) 422 | tparts = tag.split("-", 3) 423 | if len(tparts) < 3: 424 | raise ValueError(f"too few tag components: {tag!r}") 425 | return cls( 426 | iname, 427 | check_pkg_source(tparts[0]), 428 | check_distro(tparts[1]), 429 | check_arch(tparts[2]), 430 | extra_tag=(tparts[3] if len(tparts) > 3 else ""), 431 | repo_base=base, 432 | ) 433 | 434 | 435 | def generate_images(cli): 436 | """Given full image names or a matrix of kind/pkg_source/distro_base/arch 437 | values generate a list of target images to build/process. 438 | """ 439 | images = {} 440 | for img in cli.image or []: 441 | images[str(img)] = img 442 | rc = RepoConfig(cli.repo_base, cli.repo_base_for) 443 | for kind in cli.kind or []: 444 | for pkg_source in cli.package_source or DEFAULT_PKG_SOURCES: 445 | for distro_base in cli.distro_base or DEFAULT_DISTRO_BASES: 446 | for arch in cli.arch or default_arches(): 447 | timg = TargetImage( 448 | kind, 449 | pkg_source, 450 | distro_base, 451 | arch, 452 | extra_tag=(cli.extra_tag or ""), 453 | repo_base=rc.find_base(distro_base), 454 | ) 455 | images[str(timg)] = timg 456 | return list(images.values()) 457 | 458 | 459 | def add_special_tags(img, distro_qualified=True): 460 | """Certain images have special tags. Given an image, add general (non-FQIN) 461 | tags to that image. 462 | """ 463 | # Most of the policy (as opposed to mechanism) resides here where we decide 464 | # that certain images deserve some extra special tags. Mostly this serves 465 | # to keep us compatible with older tagging schemes from earlier versions of 466 | # the project. 467 | if img.distro in [FEDORA, OPENSUSE]: 468 | if img.arch == host_arch() and img.pkg_source == DEFAULT: 469 | img.additional_tags.append((LATEST, QUAL_NONE)) 470 | if img.arch == host_arch() and img.pkg_source == NIGHTLY: 471 | img.additional_tags.append((NIGHTLY, QUAL_NONE)) 472 | if not distro_qualified: 473 | return # skip creating "distro qualified" tags 474 | if img.arch == host_arch() and img.pkg_source == "default": 475 | img.additional_tags.append((f"{img.distro}-{LATEST}", QUAL_DISTRO)) 476 | if img.arch == host_arch() and img.pkg_source == "nightly": 477 | img.additional_tags.append((f"{img.distro}-{NIGHTLY}", QUAL_DISTRO)) 478 | 479 | 480 | def build(cli, target): 481 | """Command to build images.""" 482 | build_file = pathlib.Path(f"{cli.buildfile_prefix}{target.flat_name()}") 483 | common_src = "./images/common" 484 | common_dst = str(kind_source_dir(target.name) / ".common") 485 | logger.debug("Copying common tree: %r -> %r", common_src, common_dst) 486 | shutil.copytree(common_src, common_dst, dirs_exist_ok=True) 487 | container_build(cli, target) 488 | cid = container_id(cli, target) 489 | with open(build_file, "w") as fh: 490 | fh.write(f"{cid} {target.image_name()}\n") 491 | 492 | 493 | class QMatcher: 494 | """Push only tags that meet the specified criteria: 495 | all - all tags; 496 | unqualified - only unqualified tags (eg. latest); 497 | distro - only distribution base qualifed tags (eg. fedora-latest); 498 | fqin - only fully qualified tags (eg. default-centos-amd64); 499 | mixed - only fqin and unqualified tags; 500 | least-qualified (default) - exactly one tag, with the least 501 | number of qualifications 502 | """ 503 | 504 | def __init__(self, key): 505 | self.qualifications = [] 506 | self.count = 0 507 | self.max_matches = 0 508 | 509 | if not key or key == "least-qualified": 510 | self.qualifications = [QUAL_NONE, QUAL_DISTRO, QUAL_FQIN] 511 | self.max_matches = 1 512 | elif key == "all": 513 | pass 514 | elif key == "mixed": 515 | self.qualifications = [QUAL_NONE, QUAL_FQIN] 516 | else: 517 | try: 518 | mq = { 519 | "unqualified": QUAL_NONE, 520 | "distro": QUAL_DISTRO, 521 | "fqin": QUAL_FQIN, 522 | }[key] 523 | except KeyError: 524 | raise argparse.ArgumentTypeError( 525 | "value must be one of:" 526 | " all, least-qualified, unqualified, distro, fqin;" 527 | f" not {key}" 528 | ) 529 | self.qualifications = [mq] 530 | 531 | def __call__(self, qv): 532 | if self.max_matches and self.count >= self.max_matches: 533 | return False 534 | if not self.qualifications or qv in self.qualifications: 535 | self.count += 1 536 | return True 537 | return False 538 | 539 | 540 | def push(cli, target): 541 | """Command to push images.""" 542 | if cli.push_state == "rebuild": 543 | build(cli, target) 544 | if cli.push_state == "exists": 545 | try: 546 | container_id(cli, target) 547 | except subprocess.CalledProcessError: 548 | build(cli, target) 549 | 550 | to_push = [] 551 | push_name = target.image_name() 552 | for tag, qual in target.additional_tags: 553 | if tag in ("latest", "nightly"): 554 | to_push.append((target.image_name(tag=tag), qual)) 555 | if tag.endswith(("-latest", "-nightly")): 556 | to_push.append((target.image_name(tag=tag), qual)) 557 | to_push.append((push_name, QUAL_FQIN)) 558 | qmatcher = cli.push_selected_tags or QMatcher("") 559 | for push_name, tag_qual in to_push: 560 | if qmatcher(tag_qual): 561 | container_push(cli, push_name) 562 | 563 | 564 | def retag(cli, target): 565 | """Command to regenerate any missing unqualified tags.""" 566 | cid = container_id(cli, target) 567 | tags = [] 568 | if cli.repo_base and target.repo_base != cli.repo_base: 569 | # if repo base is given on the cli, and differs from the 570 | # target, regenerate tags with the new distro base. 571 | # retag list 572 | target.repo_base = cli.repo_base 573 | # Ensure the new FQIN is part of the new tags list 574 | tags.append(target.image_name()) 575 | tags += [target.image_name(tag=t) for t, _ in target.additional_tags] 576 | if tags: 577 | container_tag(cli, cid, *tags) 578 | else: 579 | logger.warning("no tags to add") 580 | 581 | 582 | def print_buildfile(cli, target): 583 | """Command to print build file names.""" 584 | build_file = pathlib.Path(f"{cli.buildfile_prefix}{target.flat_name()}") 585 | print(build_file) 586 | 587 | 588 | def print_image(_, target): 589 | """Command to print (fqin) image names.""" 590 | print(str(target)) 591 | 592 | 593 | def print_tags(cli, target): 594 | """Command to print fqin image and additinal tag names.""" 595 | for idx, name in enumerate( 596 | target.all_names(baseless=cli.without_repo_bases) 597 | ): 598 | prefix = "" if idx == 0 else " " 599 | print(f"{prefix}{name}") 600 | 601 | 602 | def main(): 603 | parser = argparse.ArgumentParser() 604 | parser.add_argument( 605 | "--verbose", 606 | dest="log_level", 607 | action="store_const", 608 | const=logging.INFO, 609 | default=logging.WARNING, 610 | help="Emit verbose output", 611 | ) 612 | parser.add_argument( 613 | "--debug", 614 | dest="log_level", 615 | action="store_const", 616 | const=logging.DEBUG, 617 | default=logging.WARNING, 618 | help="Emit debug level output", 619 | ) 620 | parser.add_argument( 621 | "--repo-base", 622 | "-R", 623 | help=( 624 | "Common container registry repository base" 625 | " (eg. quay.io/samba.org)" 626 | ), 627 | ) 628 | parser.add_argument( 629 | "--image", 630 | "-i", 631 | type=TargetImage.parse, 632 | action="append", 633 | help="Build precisely the named image (requires a FQIN)", 634 | ) 635 | parser.add_argument( 636 | "--kind", 637 | "-k", 638 | type=check_kind, 639 | action="append", 640 | help="The kind of container to build (server, ad-server, etc...)", 641 | ) 642 | parser.add_argument( 643 | "--distro-base", 644 | "-d", 645 | type=check_distro, 646 | action="append", 647 | help="The name of the base OS distribution to use.", 648 | ) 649 | parser.add_argument( 650 | "--repo-base-for", 651 | "-F", 652 | type=check_repo_base_for, 653 | action="append", 654 | help=( 655 | "Assign a custom repo base given a distro base" 656 | "(like: --repo-base-for=centos=wonky.io/smb)" 657 | ), 658 | ) 659 | parser.add_argument( 660 | "--arch", 661 | "-a", 662 | type=check_arch, 663 | action="append", 664 | help="The name of the CPU architecture to build for", 665 | ) 666 | parser.add_argument( 667 | "--package-source", 668 | "-p", 669 | type=check_pkg_source, 670 | action="append", 671 | help="Source of Samba packages to use", 672 | ) 673 | parser.add_argument( 674 | "--container-engine", 675 | help=( 676 | "Expliclty specify the path to the container engine" 677 | " (docker, podman, ...) to use" 678 | ), 679 | ) 680 | parser.add_argument( 681 | "--extra-tag", 682 | help="Specify an extra tag extension. Handy for developers.", 683 | ) 684 | parser.add_argument( 685 | "--dry-run", action="store_true", help="Do not run build commands" 686 | ) 687 | parser.add_argument( 688 | "--push-state", 689 | choices=("exists", "rebuild"), 690 | default="exists", 691 | help=( 692 | "Only push if a state is met:" 693 | "exists - image exists; rebuild - image must be rebuilt." 694 | ), 695 | ) 696 | parser.add_argument( 697 | "--push-selected-tags", 698 | type=QMatcher, 699 | help=QMatcher.__doc__, 700 | ) 701 | parser.add_argument( 702 | "--buildfile-prefix", 703 | default=".build.", 704 | help="Specify prefix for build status files", 705 | ) 706 | parser.add_argument( 707 | "--extra-build-arg", 708 | "-x", 709 | action="append", 710 | help="Extra argument to pass to container build command", 711 | ) 712 | parser.add_argument( 713 | "--without-repo-bases", 714 | "-w", 715 | action="store_true", 716 | help=( 717 | "If an image has a repo base, also generate image names" 718 | " without the repo base" 719 | ), 720 | ) 721 | parser.add_argument( 722 | "--distro-qualified", 723 | action=argparse.BooleanOptionalAction, 724 | default=True, 725 | help=( 726 | "Specify if image tags like fedora-nightly or centos-latest" 727 | " will be created." 728 | ), 729 | ) 730 | behaviors = parser.add_mutually_exclusive_group() 731 | behaviors.add_argument( 732 | "--push", 733 | action="store_const", 734 | dest="main_action", 735 | const=push, 736 | help="Push images", 737 | ) 738 | behaviors.add_argument( 739 | "--print", 740 | action="store_const", 741 | dest="main_action", 742 | const=print_image, 743 | help="Print the image names selected", 744 | ) 745 | behaviors.add_argument( 746 | "--print-tags", 747 | action="store_const", 748 | dest="main_action", 749 | const=print_tags, 750 | help="Print the image and additional tags selected", 751 | ) 752 | behaviors.add_argument( 753 | "--print-buildfile", 754 | action="store_const", 755 | dest="main_action", 756 | const=print_buildfile, 757 | help="Print the names of build status files", 758 | ) 759 | behaviors.add_argument( 760 | "--retag", 761 | action="store_const", 762 | dest="main_action", 763 | const=retag, 764 | help=( 765 | "Regenerate any short (unqualified) tags expected to exist" 766 | " for a given FQIN. Requires FQIN to already exist locally." 767 | ), 768 | ) 769 | cli = parser.parse_args() 770 | 771 | if os.environ.get("BUILD_IMAGE_DEBUG") in ("1", "yes"): 772 | cli.log_level = logging.DEBUG 773 | logging.basicConfig(level=cli.log_level) 774 | 775 | _action = cli.main_action if cli.main_action else build 776 | imgs = [] 777 | try: 778 | imgs = generate_images(cli) 779 | for img in imgs: 780 | add_special_tags(img, cli.distro_qualified) 781 | logger.info("Image %s, extra tags: %s", img, img.additional_tags) 782 | _action(cli, img) 783 | except subprocess.CalledProcessError as err: 784 | logger.error("Failed command: %s", _cmd_to_str(err.cmd)) 785 | sys.exit(err.returncode) 786 | if not imgs: 787 | logger.error("No images or image kinds supplied") 788 | sys.exit(2) 789 | 790 | 791 | if __name__ == "__main__": 792 | main() 793 | -------------------------------------------------------------------------------- /hack/install-tools.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # helper script to install build auxiliary tools in local directory 3 | # 4 | # usage: 5 | # install-tools.sh -- 6 | # 7 | # 8 | set -e 9 | 10 | _ensure_alt_bin() { 11 | mkdir -p "${ALT_BIN}" 12 | } 13 | 14 | _require_py() { 15 | if [ -z "$PY_CMD" ]; then 16 | echo "error: python3 command required, but not found" >&2 17 | echo "(set PY_CMD to specify python command)" >&2 18 | exit 5 19 | fi 20 | } 21 | 22 | _install_yamllint() { 23 | _require_py 24 | _ensure_alt_bin 25 | "${PY_CMD}" -m venv "${ALT_BIN}/.py" 26 | "${ALT_BIN}/.py/bin/pip" install "yamllint" 27 | installed_to="${ALT_BIN}/yamllint" 28 | ln -s "${ALT_BIN}/.py/bin/yamllint" "${installed_to}" 29 | } 30 | 31 | _install_gitlint() { 32 | _require_py 33 | _ensure_alt_bin 34 | "${PY_CMD}" -m venv "${ALT_BIN}/.py" 35 | "${ALT_BIN}/.py/bin/pip" install "gitlint==${GITLINT_VER}" 36 | installed_to="${ALT_BIN}/gitlint" 37 | ln -s "${ALT_BIN}/.py/bin/gitlint" "${installed_to}" 38 | } 39 | 40 | _install_shellcheck() { 41 | installed_to="${ALT_BIN}/shellcheck" 42 | local url="https://github.com/koalaman/shellcheck/releases/download/${SHELLCHECK_VER}/shellcheck-${SHELLCHECK_VER}.linux.x86_64.tar.xz" 43 | tmpdir="$(mktemp -d)" 44 | _ensure_alt_bin 45 | curl -Lo "${tmpdir}/shellcheck.tar.xz" "$url" 46 | mkdir "${tmpdir}/shellcheck" 47 | tar -xf "${tmpdir}/shellcheck.tar.xz" -C "${tmpdir}/shellcheck" 48 | mkdir -p ~/bin 49 | install -m0755 "${tmpdir}/shellcheck/shellcheck-${SHELLCHECK_VER}/shellcheck" "${installed_to}" 50 | rm -rf "${tmpdir}" 51 | } 52 | 53 | 54 | GITLINT_VER="0.19.1" 55 | SHELLCHECK_VER="v0.8.0" 56 | 57 | 58 | if [ -z "$PY_CMD" ]; then 59 | if ! PY_CMD="$(command -v python3)"; then 60 | echo "warning: failed to find python3 command" >&2 61 | fi 62 | fi 63 | 64 | ALT_BIN="${2:-.bin}" 65 | case "$1" in 66 | "--yamllint") 67 | if command -v "${ALT_BIN}/yamllint" 2>/dev/null; then 68 | exit 0 69 | fi 70 | _install_yamllint 1>&2 71 | echo "${installed_to}" 72 | ;; 73 | "--gitlint") 74 | if command -v "${ALT_BIN}/gitlint" 2>/dev/null; then 75 | exit 0 76 | fi 77 | _install_gitlint 1>&2 78 | echo "${installed_to}" 79 | ;; 80 | "--shellcheck") 81 | if command -v "${ALT_BIN}/shellcheck" 2>/dev/null; then 82 | exit 0 83 | fi 84 | _install_shellcheck 1>&2 85 | echo "${installed_to}" 86 | ;; 87 | *) 88 | echo "usage: $0 -- []" 89 | echo "" 90 | echo "available tools:" 91 | echo " --gitlint" 92 | echo " --yamllint" 93 | echo " --shellcheck" 94 | ;; 95 | esac 96 | -------------------------------------------------------------------------------- /hack/release-gen-download-section.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Requires `skopeo` and `jq` to be installed. 3 | 4 | set -e 5 | 6 | sk_digest() { 7 | skopeo inspect "docker://${1}" | jq -r .Digest 8 | } 9 | 10 | image_info() { 11 | curr_img="quay.io/samba.org/${1}:${2}" 12 | digest=$(sk_digest "${curr_img}") 13 | # strip preN from tag name 14 | final_tag=${2/%pre[0-9]*/} 15 | tag_img="quay.io/samba.org/${1}:${final_tag}" 16 | dst_img="quay.io/samba.org/${1}@${digest}" 17 | 18 | echo "### $1" 19 | echo "* By tag: $tag_img" 20 | echo "* By digest: $dst_img" 21 | echo "" 22 | } 23 | 24 | wip_tag=$1 25 | if [ -z "${wip_tag}" ] ; then 26 | echo "No tag provided!" >&2 27 | exit 1 28 | fi 29 | 30 | echo "## Downloads" 31 | echo "" 32 | echo "Images built for this release can be acquired from the quay.io image registry." 33 | echo "" 34 | for component in samba-server samba-ad-server samba-client samba-toolbox; do 35 | image_info "${component}" "${wip_tag}" 36 | done 37 | 38 | -------------------------------------------------------------------------------- /images/ad-server/Containerfile.centos: -------------------------------------------------------------------------------- 1 | FROM quay.io/centos/centos:stream9 2 | ARG INSTALL_PACKAGES_FROM=default 3 | ARG SAMBA_VERSION_SUFFIX="" 4 | ARG SAMBACC_VERSION_SUFFIX="" 5 | ARG SAMBA_SPECIFICS=daemon_cli_debug_output 6 | ARG INSTALL_CUSTOM_REPO= 7 | 8 | MAINTAINER John Mulligan 9 | 10 | LABEL org.opencontainers.image.title="Samba ADDC container" 11 | LABEL org.opencontainers.image.description="Samba ADDC container" 12 | LABEL org.opencontainers.image.vendor="Samba in Kubernetes" 13 | 14 | COPY install-packages.sh /usr/local/bin/install-packages.sh 15 | RUN /usr/local/bin/install-packages.sh \ 16 | "${INSTALL_PACKAGES_FROM}" \ 17 | "${SAMBA_VERSION_SUFFIX}" \ 18 | "${INSTALL_CUSTOM_REPO}" 19 | 20 | # If you want to install a custom version of sambacc into this image mount 21 | # a directory containing a sambacc RPM, or a sambacc wheel, or a .repo 22 | # file at /tmp/sambacc-dist-latest 23 | # If the directory is empty the script automatically falls back to using 24 | # the latest continuously built RPM from our sambacc COPR: 25 | # https://copr.fedorainfracloud.org/coprs/phlogistonjohn/sambacc 26 | COPY .common/install-sambacc-common.sh /usr/local/bin/install-sambacc-common.sh 27 | COPY install-sambacc.sh /usr/local/bin/install-sambacc.sh 28 | RUN /usr/local/bin/install-sambacc.sh \ 29 | "/tmp/sambacc-dist-latest" \ 30 | "${SAMBACC_VERSION_SUFFIX}" 31 | 32 | 33 | ENV SAMBACC_CONFIG="/etc/samba/container.json:/etc/samba/users.json" 34 | ENV SAMBA_CONTAINER_ID="demo" 35 | ENV SAMBA_SPECIFICS="$SAMBA_SPECIFICS" 36 | ENTRYPOINT ["samba-dc-container"] 37 | CMD ["run", "--setup=provision", "--setup=populate"] 38 | 39 | # vim:set syntax=dockerfile: 40 | -------------------------------------------------------------------------------- /images/ad-server/Containerfile.fedora: -------------------------------------------------------------------------------- 1 | FROM registry.fedoraproject.org/fedora:41 2 | ARG INSTALL_PACKAGES_FROM=default 3 | ARG SAMBA_VERSION_SUFFIX="" 4 | ARG SAMBACC_VERSION_SUFFIX="" 5 | ARG SAMBA_SPECIFICS=daemon_cli_debug_output 6 | ARG INSTALL_CUSTOM_REPO= 7 | 8 | MAINTAINER John Mulligan 9 | 10 | LABEL org.opencontainers.image.title="Samba ADDC container" 11 | LABEL org.opencontainers.image.description="Samba ADDC container" 12 | LABEL org.opencontainers.image.vendor="Samba in Kubernetes" 13 | 14 | COPY install-packages.sh /usr/local/bin/install-packages.sh 15 | RUN /usr/local/bin/install-packages.sh \ 16 | "${INSTALL_PACKAGES_FROM}" \ 17 | "${SAMBA_VERSION_SUFFIX}" \ 18 | "${INSTALL_CUSTOM_REPO}" 19 | 20 | # If you want to install a custom version of sambacc into this image mount 21 | # a directory containing a sambacc RPM, or a sambacc wheel, or a .repo 22 | # file at /tmp/sambacc-dist-latest 23 | # If the directory is empty the script automatically falls back to using 24 | # the latest continuously built RPM from our sambacc COPR: 25 | # https://copr.fedorainfracloud.org/coprs/phlogistonjohn/sambacc 26 | COPY .common/install-sambacc-common.sh /usr/local/bin/install-sambacc-common.sh 27 | COPY install-sambacc.sh /usr/local/bin/install-sambacc.sh 28 | RUN /usr/local/bin/install-sambacc.sh \ 29 | "/tmp/sambacc-dist-latest" \ 30 | "${SAMBACC_VERSION_SUFFIX}" 31 | 32 | 33 | ENV SAMBACC_CONFIG="/etc/samba/container.json:/etc/samba/users.json" 34 | ENV SAMBA_CONTAINER_ID="demo" 35 | ENV SAMBA_SPECIFICS="$SAMBA_SPECIFICS" 36 | ENTRYPOINT ["samba-dc-container"] 37 | CMD ["run", "--setup=provision", "--setup=populate"] 38 | 39 | # vim:set syntax=dockerfile: 40 | -------------------------------------------------------------------------------- /images/ad-server/Containerfile.opensuse: -------------------------------------------------------------------------------- 1 | # Defines the tag for OBS and build script builds: 2 | #!BuildTag: opensuse/samba-ad-server:latest 3 | #!BuildTag: opensuse/samba-ad-server:%%MINOR%% 4 | #!BuildTag: opensuse/samba-ad-server:%%PKG_VERSION%% 5 | #!BuildTag: opensuse/samba-ad-server:%%PKG_VERSION%%-%RELEASE% 6 | 7 | # OBS doesn't allow a fully qualified image registry name for the offline build 8 | FROM opensuse/tumbleweed 9 | ARG SAMBA_SPECIFICS=daemon_cli_debug_output 10 | 11 | MAINTAINER David Mulder 12 | 13 | # labelprefix=org.opensuse.samba-ad-server 14 | LABEL org.opencontainers.image.title="Samba ADDC container" 15 | LABEL org.opencontainers.image.description="Samba ADDC container" 16 | LABEL org.opencontainers.image.created="%BUILDTIME%" 17 | LABEL org.opencontainers.image.version="%%PKG_VERSION%%-%RELEASE%" 18 | LABEL org.opencontainers.image.vendor="Samba in Kubernetes" 19 | LABEL org.openbuildservice.disturl="%DISTURL%" 20 | LABEL org.opensuse.reference="registry.opensuse.org/opensuse/samba-ad-server:%%PKG_VERSION%%-%RELEASE%" 21 | # endlabelprefix 22 | 23 | RUN zypper --non-interactive install --no-recommends \ 24 | findutils \ 25 | python3-pip \ 26 | python3-jsonschema \ 27 | samba-python3 \ 28 | python3-pyxattr \ 29 | tdb-tools \ 30 | samba-ad-dc \ 31 | procps \ 32 | samba-client \ 33 | samba-winbind \ 34 | python3-dnspython \ 35 | krb5-server \ 36 | sambacc && \ 37 | zypper clean; 38 | RUN ln -sf /usr/share/sambacc/examples/addc.json /etc/samba/container.json 39 | RUN rm -rf /etc/samba/smb.conf 40 | RUN cp /usr/etc/nsswitch.conf /etc/nsswitch.conf 41 | 42 | 43 | ENV SAMBACC_CONFIG="/etc/samba/container.json:/etc/samba/users.json" 44 | ENV SAMBA_CONTAINER_ID="demo" 45 | ENV SAMBA_SPECIFICS="$SAMBA_SPECIFICS" 46 | ENTRYPOINT ["samba-dc-container"] 47 | CMD ["run", "--setup=provision", "--setup=populate"] 48 | 49 | # vim:set syntax=dockerfile: 50 | -------------------------------------------------------------------------------- /images/ad-server/install-packages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | 5 | get_custom_repo() { 6 | url="$1" 7 | fname="$(basename "$url")" 8 | dest="/etc/yum.repos.d/${fname}" 9 | dnf install --setopt=install_weak_deps=False -y /usr/bin/curl 10 | curl -L "$url" -o "$dest" 11 | } 12 | 13 | install_packages_from="$1" 14 | samba_version_suffix="$2" 15 | install_custom_repo="$3" 16 | # reserve package_selection. keep args consistent with server image script. 17 | # unused for ad image (for now) 18 | # package_selection="$4" 19 | 20 | # shellcheck disable=SC1091 21 | OS_BASE="$(. /etc/os-release && echo "${ID}")" 22 | 23 | case "${install_packages_from}" in 24 | samba-nightly) 25 | get_custom_repo "https://artifacts.ci.centos.org/samba/pkgs/master/${OS_BASE}/samba-nightly-master.repo" 26 | ;; 27 | custom-repo) 28 | get_custom_repo "${install_custom_repo}" 29 | ;; 30 | esac 31 | 32 | 33 | # Assorted packages that must be installed in the container image to 34 | # support the functioning of the container 35 | support_packages=(\ 36 | findutils \ 37 | python-pip \ 38 | python3-samba \ 39 | python3-pyxattr \ 40 | tdb-tools \ 41 | procps-ng \ 42 | /usr/bin/smbclient) 43 | # Packages belonging to the samba install. If a samba_version_suffix is given 44 | # all the samba_packages must share that version 45 | samba_packages=(samba-dc) 46 | 47 | # Assign version suffix to samba packages 48 | samba_versioned_packages=() 49 | for p in "${samba_packages[@]}"; do 50 | samba_versioned_packages+=("${p}${samba_version_suffix}") 51 | done 52 | 53 | dnf_cmd=(dnf) 54 | if [[ "${OS_BASE}" = centos ]]; then 55 | dnf install -y epel-next-release 56 | dnf_cmd+=(--enablerepo=crb) 57 | fi 58 | 59 | "${dnf_cmd[@]}" \ 60 | install --setopt=install_weak_deps=False -y \ 61 | "${support_packages[@]}" \ 62 | "${samba_versioned_packages[@]}" 63 | dnf clean all 64 | 65 | rm -rf /etc/samba/smb.conf 66 | -------------------------------------------------------------------------------- /images/ad-server/install-sambacc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | 5 | # shellcheck source=images/common/install-sambacc-common.sh 6 | . install-sambacc-common.sh 7 | export DEFAULT_JSON_FILE=addc.json 8 | install_sambacc "$@" 9 | -------------------------------------------------------------------------------- /images/client/Containerfile.centos: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Michael Adam 2 | 3 | FROM quay.io/centos/centos:stream9 4 | 5 | MAINTAINER Michael Adam 6 | 7 | LABEL org.opencontainers.image.title="Samba Client container" 8 | LABEL org.opencontainers.image.description="Samba Client container" 9 | LABEL org.opencontainers.image.vendor="Samba in Kubernetes" 10 | LABEL org.opencontainers.image.url="https://github.com/samba-in-kubernetes/samba-container" 11 | 12 | 13 | # https://github.com/samba-in-kubernetes/samba-container/issues/96#issuecomment-1387467396 14 | # 15 | # samba-common, when pulled in as a dependency for samba-client, has a preferred 16 | # requirement on systemd-standalone-tmpfiles(rather than systemd) but is meant 17 | # to conflict with systemd itself of same version or higher. We can avoid the 18 | # conflict by choosing to install systemd over systemd-standalone-tmpfiles. 19 | RUN dnf -y install samba-client systemd \ 20 | && dnf clean all 21 | -------------------------------------------------------------------------------- /images/client/Containerfile.fedora: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Michael Adam 2 | 3 | FROM registry.fedoraproject.org/fedora:41 4 | 5 | MAINTAINER Michael Adam 6 | 7 | LABEL org.opencontainers.image.title="Samba Client container" 8 | LABEL org.opencontainers.image.description="Samba Client container" 9 | LABEL org.opencontainers.image.vendor="Samba in Kubernetes" 10 | LABEL org.opencontainers.image.url="https://github.com/samba-in-kubernetes/samba-container" 11 | 12 | 13 | # https://github.com/samba-in-kubernetes/samba-container/issues/96#issuecomment-1387467396 14 | # 15 | # samba-common, when pulled in as a dependency for samba-client, has a preferred 16 | # requirement on systemd-standalone-tmpfiles(rather than systemd) but is meant 17 | # to conflict with systemd itself of same version or higher. We can avoid the 18 | # conflict by choosing to install systemd over systemd-standalone-tmpfiles. 19 | RUN dnf -y install samba-client systemd \ 20 | && dnf clean all 21 | -------------------------------------------------------------------------------- /images/client/Containerfile.opensuse: -------------------------------------------------------------------------------- 1 | # Defines the tag for OBS and build script builds: 2 | #!BuildTag: opensuse/samba-client:latest 3 | #!BuildTag: opensuse/samba-client:%%MINOR%% 4 | #!BuildTag: opensuse/samba-client:%%PKG_VERSION%% 5 | #!BuildTag: opensuse/samba-client:%%PKG_VERSION%%-%RELEASE% 6 | 7 | # OBS doesn't allow a fully qualified image registry name for the offline build 8 | FROM opensuse/tumbleweed 9 | MAINTAINER David Mulder 10 | 11 | # labelprefix=org.opensuse.samba-client 12 | LABEL org.opencontainers.image.title="Samba Client container" 13 | LABEL org.opencontainers.image.description="Samba Client container" 14 | LABEL org.opencontainers.image.created="%BUILDTIME%" 15 | LABEL org.opencontainers.image.version="%%PKG_VERSION%%-%RELEASE%" 16 | LABEL org.opencontainers.image.vendor="Samba in Kubernetes" 17 | LABEL org.openbuildservice.disturl="%DISTURL%" 18 | LABEL org.opensuse.reference="registry.opensuse.org/opensuse/samba-client:%%PKG_VERSION%%-%RELEASE%" 19 | # endlabelprefix 20 | 21 | RUN zypper --non-interactive install --no-recommends samba-client && zypper clean 22 | -------------------------------------------------------------------------------- /images/common/install-sambacc-common.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | install_sambacc() { 4 | local distdir="$1" 5 | local sambacc_version_suffix="$2" 6 | if ! [ -d "${distdir}" ]; then 7 | echo "warning: no directory: ${distdir}" >&2 8 | else 9 | mapfile -d '' artifacts < \ 10 | <(find "${distdir}" -type f -print0) 11 | fi 12 | 13 | local wheels=() 14 | local rpmfiles=() 15 | local rpmextras=() 16 | local repofiles=() 17 | for artifact in "${artifacts[@]}" ; do 18 | if [[ ${artifact} =~ sambacc.*\.whl$ ]]; then 19 | wheels+=("${artifact}") 20 | fi 21 | if [[ ${artifact} =~ python.?-sambacc-.*\.noarch\.rpm$ ]]; then 22 | rpmfiles+=("${artifact}") 23 | fi 24 | if [[ ${artifact} =~ python.?-sambacc+.*\.noarch\.rpm$ ]]; then 25 | rpmextras+=("${artifact}") 26 | fi 27 | if [[ ${artifact} =~ sambacc.*\.repo$ ]]; then 28 | repofiles+=("${artifact}") 29 | fi 30 | done 31 | 32 | 33 | local action="" 34 | echo "INFO: determining sambacc installation source." 35 | if [ "${#wheels[@]}" -gt 0 ]; then 36 | echo "INFO: wheel found" 37 | if [ "${#wheels[@]}" -gt 1 ]; then 38 | echo "ERROR: more than one wheel file found" 39 | exit 1 40 | elif [ "${#wheels[@]}" -eq 1 ]; then 41 | action=install-wheel 42 | fi 43 | fi 44 | if [ "${#rpmfiles[@]}" -gt 0 ]; then 45 | echo "INFO: rpm file found" 46 | if [ "${#rpmfiles[@]}" -gt 1 ]; then 47 | echo "ERROR: more than one sambacc rpm file found" 48 | exit 1 49 | elif [ "${#rpmfiles[@]}" -eq 1 ]; then 50 | action=install-rpm 51 | fi 52 | fi 53 | if [ "${#repofiles[@]}" -gt 0 ]; then 54 | echo "INFO: repo file found" 55 | if [ "${#repofiles[@]}" -gt 1 ]; then 56 | echo "ERROR: more than one repo file found" 57 | exit 1 58 | elif [ "${#repofiles[@]}" -eq 1 ]; then 59 | action=install-from-repo 60 | fi 61 | fi 62 | if [ -z "${action}" ]; then 63 | 64 | echo "INFO: no local sambacc installation source found. falling back to copr install." 65 | action=install-from-copr-repo 66 | fi 67 | 68 | echo "INFO: selected installation method: '${action}'" 69 | if [ -z "${DEFAULT_JSON_FILE}" ]; then 70 | echo "DEFAULT_JSON_FILE value unset" 71 | exit 1 72 | fi 73 | 74 | case $action in 75 | install-wheel) 76 | pip install "${wheels[0]}" 77 | container_json_file="/usr/local/share/sambacc/examples/${DEFAULT_JSON_FILE}" 78 | ;; 79 | install-rpm) 80 | dnf install -y "${rpmfiles[0]}" "${rpmextras[@]}" 81 | dnf clean all 82 | container_json_file="/usr/share/sambacc/examples/${DEFAULT_JSON_FILE}" 83 | ;; 84 | install-from-repo) 85 | local tgt="${repofiles[0]}" 86 | cp "${tgt}" /etc/yum.repos.d/"$(basename "${tgt}")" 87 | dnf install -y "python3-sambacc${sambacc_version_suffix}" 88 | dnf clean all 89 | container_json_file="/usr/share/sambacc/examples/${DEFAULT_JSON_FILE}" 90 | ;; 91 | install-from-copr-repo) 92 | # shellcheck disable=SC1091 93 | OS_BASE="$(. /etc/os-release && echo "${ID}")" 94 | dnf install -y 'dnf-command(copr)' 95 | 96 | copr_args=("phlogistonjohn/sambacc") 97 | if [ "$OS_BASE" = centos ]; then 98 | # centos needs a little help determining what repository 99 | # within the copr to use. By default it only wants 100 | # to add `epel-9-$arch`. 101 | copr_args+=("centos-stream+epel-next-9-$(uname -p)") 102 | fi 103 | dnf copr enable -y "${copr_args[@]}" 104 | dnf install -y "python3-sambacc${sambacc_version_suffix}" 105 | dnf clean all 106 | container_json_file="/usr/share/sambacc/examples/${DEFAULT_JSON_FILE}" 107 | ;; 108 | *) 109 | echo "no install package(s) found" 110 | exit 1 111 | ;; 112 | esac 113 | 114 | if [ "$container_json_file" ]; then 115 | ln -sf "$container_json_file" /etc/samba/container.json 116 | fi 117 | } 118 | -------------------------------------------------------------------------------- /images/server/Containerfile.centos: -------------------------------------------------------------------------------- 1 | FROM quay.io/centos/centos:stream9 2 | ARG INSTALL_PACKAGES_FROM=default 3 | ARG SAMBA_VERSION_SUFFIX="" 4 | ARG SAMBACC_VERSION_SUFFIX="" 5 | ARG SAMBA_SPECIFICS=daemon_cli_debug_output,ctdb_leader_admin_command 6 | ARG INSTALL_CUSTOM_REPO= 7 | ARG PACKAGE_SELECTION= 8 | 9 | MAINTAINER John Mulligan 10 | 11 | LABEL org.opencontainers.image.title="Samba container" 12 | LABEL org.opencontainers.image.description="Samba container" 13 | LABEL org.opencontainers.image.vendor="Samba in Kubernetes" 14 | LABEL org.opencontainers.image.url="https://github.com/samba-in-kubernetes/samba-container" 15 | 16 | 17 | COPY smb.conf /etc/samba/smb.conf 18 | COPY install-packages.sh /usr/local/bin/install-packages.sh 19 | RUN /usr/local/bin/install-packages.sh \ 20 | "${INSTALL_PACKAGES_FROM}" \ 21 | "${SAMBA_VERSION_SUFFIX}" \ 22 | "${INSTALL_CUSTOM_REPO}" \ 23 | "${PACKAGE_SELECTION}" 24 | 25 | # If you want to install a custom version of sambacc into this image mount 26 | # a directory containing a sambacc RPM, or a sambacc wheel, or a .repo 27 | # file at /tmp/sambacc-dist-latest 28 | # If the directory is empty the script automatically falls back to using 29 | # the latest continuously built RPM from our sambacc COPR: 30 | # https://copr.fedorainfracloud.org/coprs/phlogistonjohn/sambacc 31 | COPY .common/install-sambacc-common.sh /usr/local/bin/install-sambacc-common.sh 32 | COPY install-sambacc.sh /usr/local/bin/install-sambacc.sh 33 | RUN /usr/local/bin/install-sambacc.sh \ 34 | "/tmp/sambacc-dist-latest" \ 35 | "${SAMBACC_VERSION_SUFFIX}" 36 | 37 | 38 | VOLUME ["/share"] 39 | 40 | EXPOSE 445 41 | 42 | ENV SAMBACC_CONFIG="/etc/samba/container.json:/etc/samba/users.json" 43 | ENV SAMBA_CONTAINER_ID="demo" 44 | ENV SAMBA_SPECIFICS="$SAMBA_SPECIFICS" 45 | ENTRYPOINT ["samba-container"] 46 | CMD ["run", "smbd"] 47 | 48 | # vim:set syntax=dockerfile: 49 | -------------------------------------------------------------------------------- /images/server/Containerfile.fedora: -------------------------------------------------------------------------------- 1 | FROM registry.fedoraproject.org/fedora:41 2 | ARG INSTALL_PACKAGES_FROM=default 3 | ARG SAMBA_VERSION_SUFFIX="" 4 | ARG SAMBACC_VERSION_SUFFIX="" 5 | ARG SAMBA_SPECIFICS=daemon_cli_debug_output,ctdb_leader_admin_command 6 | ARG INSTALL_CUSTOM_REPO= 7 | ARG PACKAGE_SELECTION= 8 | 9 | MAINTAINER John Mulligan 10 | 11 | LABEL org.opencontainers.image.title="Samba container" 12 | LABEL org.opencontainers.image.description="Samba container" 13 | LABEL org.opencontainers.image.vendor="Samba in Kubernetes" 14 | LABEL org.opencontainers.image.url="https://github.com/samba-in-kubernetes/samba-container" 15 | 16 | COPY smb.conf /etc/samba/smb.conf 17 | COPY install-packages.sh /usr/local/bin/install-packages.sh 18 | RUN /usr/local/bin/install-packages.sh \ 19 | "${INSTALL_PACKAGES_FROM}" \ 20 | "${SAMBA_VERSION_SUFFIX}" \ 21 | "${INSTALL_CUSTOM_REPO}" \ 22 | "${PACKAGE_SELECTION}" 23 | 24 | # If you want to install a custom version of sambacc into this image mount 25 | # a directory containing a sambacc RPM, or a sambacc wheel, or a .repo 26 | # file at /tmp/sambacc-dist-latest 27 | # If the directory is empty the script automatically falls back to using 28 | # the latest continuously built RPM from our sambacc COPR: 29 | # https://copr.fedorainfracloud.org/coprs/phlogistonjohn/sambacc 30 | COPY .common/install-sambacc-common.sh /usr/local/bin/install-sambacc-common.sh 31 | COPY install-sambacc.sh /usr/local/bin/install-sambacc.sh 32 | RUN /usr/local/bin/install-sambacc.sh \ 33 | "/tmp/sambacc-dist-latest" \ 34 | "${SAMBACC_VERSION_SUFFIX}" 35 | 36 | 37 | VOLUME ["/share"] 38 | 39 | EXPOSE 445 40 | 41 | ENV SAMBACC_CONFIG="/etc/samba/container.json:/etc/samba/users.json" 42 | ENV SAMBA_CONTAINER_ID="demo" 43 | ENV SAMBA_SPECIFICS="$SAMBA_SPECIFICS" 44 | ENTRYPOINT ["samba-container"] 45 | CMD ["run", "smbd"] 46 | 47 | # vim:set syntax=dockerfile: 48 | -------------------------------------------------------------------------------- /images/server/Containerfile.opensuse: -------------------------------------------------------------------------------- 1 | # Defines the tag for OBS and build script builds: 2 | #!BuildTag: opensuse/samba-server:latest 3 | #!BuildTag: opensuse/samba-server:%%MINOR%% 4 | #!BuildTag: opensuse/samba-server:%%PKG_VERSION%% 5 | #!BuildTag: opensuse/samba-server:%%PKG_VERSION%%-%RELEASE% 6 | 7 | # OBS doesn't allow a fully qualified image registry name for the offline build 8 | FROM opensuse/tumbleweed 9 | ARG SAMBA_SPECIFICS=daemon_cli_debug_output,ctdb_leader_admin_command 10 | 11 | MAINTAINER David Mulder 12 | 13 | # labelprefix=org.opensuse.samba-server 14 | LABEL org.opencontainers.image.title="Samba container" 15 | LABEL org.opencontainers.image.description="Samba container" 16 | LABEL org.opencontainers.image.created="%BUILDTIME%" 17 | LABEL org.opencontainers.image.version="%%PKG_VERSION%%-%RELEASE%" 18 | LABEL org.opencontainers.image.vendor="Samba in Kubernetes" 19 | LABEL org.openbuildservice.disturl="%DISTURL%" 20 | LABEL org.opensuse.reference="registry.opensuse.org/opensuse/samba-server:%%PKG_VERSION%%-%RELEASE%" 21 | # endlabelprefix 22 | 23 | COPY smb.conf /etc/samba/smb.conf 24 | RUN zypper --non-interactive install --no-recommends \ 25 | findutils \ 26 | python3-pip \ 27 | python3-jsonschema \ 28 | samba-python3 \ 29 | python3-pyxattr \ 30 | samba \ 31 | samba-winbind \ 32 | tdb-tools \ 33 | ctdb \ 34 | glibc \ 35 | sambacc && \ 36 | zypper clean; 37 | RUN ln -sf /usr/share/sambacc/examples/minimal.json /etc/samba/container.json 38 | RUN cp /usr/etc/nsswitch.conf /etc/nsswitch.conf 39 | 40 | 41 | 42 | 43 | VOLUME ["/share"] 44 | 45 | EXPOSE 445 46 | 47 | ENV SAMBACC_CONFIG="/etc/samba/container.json:/etc/samba/users.json" 48 | ENV SAMBA_CONTAINER_ID="demo" 49 | ENV SAMBA_SPECIFICS="$SAMBA_SPECIFICS" 50 | ENTRYPOINT ["samba-container"] 51 | CMD ["run", "smbd"] 52 | 53 | # vim:set syntax=dockerfile: 54 | -------------------------------------------------------------------------------- /images/server/install-packages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | 5 | 6 | need_curl() { 7 | if command -v curl >/dev/null ; then 8 | return 0 9 | fi 10 | dnf install --setopt=install_weak_deps=False -y /usr/bin/curl 11 | } 12 | 13 | get_custom_repo() { 14 | url="$1" 15 | fname="$(basename "$url")" 16 | dest="/etc/yum.repos.d/${fname}" 17 | need_curl 18 | curl -L "$url" -o "$dest" 19 | } 20 | 21 | generate_repo_from_shaman() { 22 | url="$1" 23 | dest="/etc/yum.repos.d/$2" 24 | need_curl 25 | tmpfile=/tmp/shaman.json 26 | curl -L "$url" -o "${tmpfile}" && python3 < 8 | 9 | LABEL org.opencontainers.image.title="Samba Toolbox container" 10 | LABEL org.opencontainers.image.description="Samba Toolbox container" 11 | LABEL org.opencontainers.image.vendor="Samba in Kubernetes" 12 | LABEL org.opencontainers.image.url="https://github.com/samba-in-kubernetes/samba-container" 13 | 14 | RUN dnf install --enablerepo=crb -y \ 15 | samba-test \ 16 | tdb-tools \ 17 | && dnf clean all 18 | -------------------------------------------------------------------------------- /images/toolbox/Containerfile.fedora: -------------------------------------------------------------------------------- 1 | FROM quay.io/samba.org/samba-client:latest 2 | MAINTAINER Shachar Sharon 3 | 4 | LABEL org.opencontainers.image.title="Samba Toolbox container" 5 | LABEL org.opencontainers.image.description="Samba Toolbox container" 6 | LABEL org.opencontainers.image.vendor="Samba in Kubernetes" 7 | LABEL org.opencontainers.image.url="https://github.com/samba-in-kubernetes/samba-container" 8 | 9 | 10 | RUN dnf -y install samba-test \ 11 | tdb-tools \ 12 | && dnf clean all 13 | -------------------------------------------------------------------------------- /images/toolbox/Containerfile.opensuse: -------------------------------------------------------------------------------- 1 | # Defines the tag for OBS and build script builds: 2 | #!BuildTag: opensuse/samba-toolbox:latest 3 | #!BuildTag: opensuse/samba-toolbox:%%MINOR%% 4 | #!BuildTag: opensuse/samba-toolbox:%%PKG_VERSION%% 5 | #!BuildTag: opensuse/samba-toolbox:%%PKG_VERSION%%-%RELEASE% 6 | 7 | # OBS doesn't allow a fully qualified image registry name for the offline build 8 | FROM opensuse/tumbleweed 9 | MAINTAINER David Mulder 10 | 11 | # labelprefix=org.opensuse.samba-toolbox 12 | LABEL org.opencontainers.image.title="Samba Toolbox container" 13 | LABEL org.opencontainers.image.description="Samba Toolbox container" 14 | LABEL org.opencontainers.image.created="%BUILDTIME%" 15 | LABEL org.opencontainers.image.version="%%PKG_VERSION%%-%RELEASE%" 16 | LABEL org.opencontainers.image.vendor="Samba in Kubernetes" 17 | LABEL org.openbuildservice.disturl="%DISTURL%" 18 | LABEL org.opensuse.reference="registry.opensuse.org/opensuse/samba-toolbox:%%PKG_VERSION%%-%RELEASE%" 19 | # endlabelprefix 20 | 21 | RUN zypper --non-interactive install --no-recommends samba-client samba-test tdb-tools && zypper clean 22 | -------------------------------------------------------------------------------- /tests/common.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | SCRIPT_DIR="$(cd "$(dirname "${0}")" && pwd)" 4 | 5 | export AD_DEPLOYMENT_YAML="${SCRIPT_DIR}/files/samba-ad-server-deployment.yml" 6 | export AD_DEPLOYMENT_NAME="samba-ad-server" 7 | export MEMBER_POD_YAML="${SCRIPT_DIR}/files/samba-domain-member-pod.yml" 8 | export MEMBER_POD_NAME="samba-dm" 9 | export MEMBER_CM_NAME="samba-container-config" 10 | export MEMBER_SECRET_NAME="ad-join-secret" 11 | 12 | export KEEP=${KEEP:-0} 13 | 14 | _error() { 15 | echo "$@" 16 | exit 1 17 | } 18 | 19 | _errordbg() { 20 | local errmsg="$1" 21 | shift 22 | echo ERROR: "$errmsg" 23 | for resource in "$@"; do 24 | echo "---------" 25 | dcmd=(kubectl get -o yaml "${resource}") 26 | echo ">" "${dcmd[@]}" 27 | ! "${dcmd[@]}" 28 | echo "---------" 29 | dcmd=(kubectl describe "${resource}") 30 | echo ">" "${dcmd[@]}" 31 | ! "${dcmd[@]}" 32 | done 33 | echo "---------" 34 | _error "$errmsg" 35 | } 36 | -------------------------------------------------------------------------------- /tests/files/coredns-snippet.template: -------------------------------------------------------------------------------- 1 | domain1.sink.test:53 { 2 | errors 3 | cache 30 4 | forward . AD_SERVER_IP 5 | } 6 | -------------------------------------------------------------------------------- /tests/files/samba-ad-server-deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: samba-ad-server 5 | labels: 6 | app: samba-ad 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: samba-ad 12 | template: 13 | metadata: 14 | labels: 15 | app: samba-ad 16 | spec: 17 | containers: 18 | - name: samba 19 | # Pointing to locally built image, 20 | # change here to use a registry. 21 | image: samba-ad-server:$IMG_TAG 22 | # Need imagePullPolicy Never for working with local images. 23 | # Otherwise we get "ErrImagePull". 24 | imagePullPolicy: Never 25 | securityContext: 26 | capabilities: 27 | add: ["SYS_ADMIN"] 28 | ports: 29 | # https://wiki.samba.org/index.php/Samba_AD_DC_Port_Usage 30 | - containerPort: 53 31 | name: dns 32 | - containerPort: 135 33 | name: epm 34 | protocol: TCP 35 | - containerPort: 137 36 | name: netbios-ns 37 | protocol: UDP 38 | - containerPort: 138 39 | name: netbios-dgram 40 | protocol: UDP 41 | - containerPort: 139 42 | name: netbios-session 43 | protocol: TCP 44 | - containerPort: 389 45 | name: ldap 46 | - containerPort: 445 47 | name: smb 48 | protocol: TCP 49 | - containerPort: 464 50 | name: kerberos 51 | - containerPort: 636 52 | name: ldaps 53 | protocol: TCP 54 | - containerPort: 3268 55 | name: gc 56 | protocol: TCP 57 | - containerPort: 3269 58 | name: gc-ssl 59 | protocol: TCP 60 | # need 49152-65535 for dynamic RPC ports 61 | # but currently not possible to specify ranges 62 | -------------------------------------------------------------------------------- /tests/files/samba-domain-member-pod.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Configuration for the samba domain member pod. 3 | apiVersion: v1 4 | kind: ConfigMap 5 | metadata: 6 | name: samba-container-config 7 | data: 8 | config.json: | 9 | { 10 | "samba-container-config": "v0", 11 | "configs": { 12 | "sambadm1": { 13 | "shares": [ 14 | "share" 15 | ], 16 | "globals": [ 17 | "noprinting", 18 | "sambadm1" 19 | ], 20 | "instance_name": "SMBDM1" 21 | } 22 | }, 23 | "shares": { 24 | "share": { 25 | "options": { 26 | "path": "/share", 27 | "read only": "no" 28 | } 29 | } 30 | }, 31 | "_NOTE": "Change the security and workgroup keys to match your domain.", 32 | "globals": { 33 | "noprinting": { 34 | "options": { 35 | "load printers": "no", 36 | "printing": "bsd", 37 | "printcap name": "/dev/null", 38 | "disable spoolss": "yes" 39 | } 40 | }, 41 | "sambadm1": { 42 | "options": { 43 | "log level": "10", 44 | "security": "ads", 45 | "workgroup": "DOMAIN1", 46 | "realm": "DOMAIN1.SINK.TEST", 47 | "server min protocol": "SMB2", 48 | "idmap config * : backend": "autorid", 49 | "idmap config * : range": "2000-9999999" 50 | } 51 | } 52 | } 53 | } 54 | --- 55 | # Secret used to pass a AD join password to the winbind pod. 56 | apiVersion: v1 57 | kind: Secret 58 | metadata: 59 | name: ad-join-secret 60 | type: Opaque 61 | stringData: 62 | # Change the value below to match the username and password for a user that 63 | # can join systems your test AD Domain 64 | join.json: | 65 | {"username": "Administrator", "password": "Passw0rd"} 66 | --- 67 | # The pod itself. 68 | apiVersion: v1 69 | kind: Pod 70 | metadata: 71 | labels: 72 | app: samba-dm-example 73 | name: samba-dm 74 | spec: 75 | shareProcessNamespace: true 76 | containers: 77 | - image: $IMG_NAME 78 | # Need imagePullPolicy Never for working with local images. 79 | # Otherwise we get "ErrImagePull". 80 | imagePullPolicy: $IMG_PULL_POLICY 81 | name: smb 82 | command: 83 | - "samba-container" 84 | - "--debug-delay=1" 85 | - "run" 86 | - "smbd" 87 | env: 88 | - name: SAMBACC_CONFIG 89 | value: /etc/samba-container/config.json 90 | - name: SAMBA_CONTAINER_ID 91 | value: sambadm1 92 | - name: SAMBACC_VERSION 93 | value: "0.1" 94 | - name: HOSTNAME 95 | value: sambadm1 96 | ports: 97 | - containerPort: 445 98 | hostPort: 455 99 | protocol: TCP 100 | name: "smb" 101 | securityContext: 102 | allowPrivilegeEscalation: true 103 | volumeMounts: 104 | - mountPath: "/share" 105 | name: samba-sharedir 106 | - mountPath: "/etc/samba-container" 107 | name: samba-container-config 108 | - mountPath: "/var/lib/samba" 109 | name: samba-state-dir 110 | - mountPath: "/run/samba/winbindd" 111 | name: samba-sockets-dir 112 | - image: $IMG_NAME 113 | imagePullPolicy: $IMG_PULL_POLICY 114 | name: winbind 115 | command: 116 | - "samba-container" 117 | - "run" 118 | - "winbindd" 119 | env: 120 | - name: SAMBACC_VERSION 121 | value: "0.1" 122 | - name: SAMBACC_CONFIG 123 | value: /etc/samba-container/config.json 124 | - name: SAMBA_CONTAINER_ID 125 | value: sambadm1 126 | - name: HOSTNAME 127 | value: sambadm1 128 | securityContext: 129 | allowPrivilegeEscalation: true 130 | volumeMounts: 131 | - mountPath: "/etc/samba-container" 132 | name: samba-container-config 133 | - mountPath: "/var/lib/samba" 134 | name: samba-state-dir 135 | - mountPath: "/run/samba/winbindd" 136 | name: samba-sockets-dir 137 | initContainers: 138 | - image: $IMG_NAME 139 | imagePullPolicy: $IMG_PULL_POLICY 140 | name: init 141 | args: 142 | - "init" 143 | env: 144 | - name: SAMBACC_VERSION 145 | value: "0.1" 146 | - name: SAMBACC_CONFIG 147 | value: /etc/samba-container/config.json 148 | - name: SAMBA_CONTAINER_ID 149 | value: sambadm1 150 | - name: HOSTNAME 151 | value: sambadm1 152 | securityContext: 153 | allowPrivilegeEscalation: true 154 | volumeMounts: 155 | - mountPath: "/etc/samba-container" 156 | name: samba-container-config 157 | - mountPath: "/var/lib/samba" 158 | name: samba-state-dir 159 | - image: $IMG_NAME 160 | imagePullPolicy: $IMG_PULL_POLICY 161 | name: must-join 162 | args: 163 | - "must-join" 164 | - "--files" 165 | - "--join-file=/etc/join-data/join.json" 166 | env: 167 | - name: SAMBACC_VERSION 168 | value: "0.1" 169 | - name: SAMBACC_CONFIG 170 | value: /etc/samba-container/config.json 171 | - name: SAMBA_CONTAINER_ID 172 | value: sambadm1 173 | - name: HOSTNAME 174 | value: sambadm1 175 | securityContext: 176 | allowPrivilegeEscalation: true 177 | volumeMounts: 178 | - mountPath: "/etc/samba-container" 179 | name: samba-container-config 180 | - mountPath: "/var/lib/samba" 181 | name: samba-state-dir 182 | - mountPath: "/etc/join-data" 183 | name: samba-join-data 184 | readOnly: true 185 | volumes: 186 | - configMap: 187 | name: samba-container-config 188 | name: samba-container-config 189 | - secret: 190 | secretName: ad-join-secret 191 | items: 192 | - key: join.json 193 | path: join.json 194 | name: samba-join-data 195 | - emptyDir: 196 | medium: Memory 197 | name: samba-sockets-dir 198 | - emptyDir: {} 199 | name: samba-state-dir 200 | # Comment out the section below to skip using a PVC for the share 201 | # - persistentVolumeClaim: 202 | # claimName: mypvc 203 | # name: samba-sharedir 204 | # Uncomment the section below to use an empty dir for the share 205 | - emptyDir: 206 | medium: Memory 207 | name: samba-sharedir 208 | -------------------------------------------------------------------------------- /tests/test-deploy-ad-member.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | SCRIPT_DIR="$(cd "$(dirname "${0}")" && pwd)" 4 | IMG_TAG=${IMG_TAG:-"latest"} 5 | IMG_NAME="${SERVER_IMG:-samba-server}:${IMG_TAG}" 6 | IMG_PULL_POLICY="${IMG_PULL_POLICY:-Never}" 7 | 8 | source "${SCRIPT_DIR}/common.sh" 9 | 10 | echo "Creating ad member pod..." 11 | ERROR_MSG=$(IMG_NAME="${IMG_NAME}" IMG_PULL_POLICY="${IMG_PULL_POLICY}" envsubst < "${MEMBER_POD_YAML}" | kubectl create -f - 2>&1 1>/dev/null) 12 | if [ $? -ne 0 ] ; then 13 | if [[ "${ERROR_MSG}" =~ "AlreadyExists" ]] ; then 14 | echo "pod exists already. Continuing." 15 | else 16 | _error "Error creating member pod." 17 | fi 18 | fi 19 | 20 | kubectl get pod 21 | 22 | podname="$(kubectl get pod | grep "${MEMBER_POD_NAME}" | awk '{ print $1 }')" 23 | [ $? -eq 0 ] || _error "Error getting podname" 24 | 25 | echo "Samba ad member pod is $podname" 26 | 27 | echo "waiting for pod to be in Running state" 28 | tries=0 29 | podstatus="none" 30 | until [ $tries -ge 120 ] || echo "$podstatus" | grep -q 'Running'; do 31 | sleep 1 32 | echo -n "." 33 | tries=$(( tries + 1 )) 34 | podstatus="$(kubectl get pod "$podname" -o go-template='{{.status.phase}}')" 35 | done 36 | echo 37 | kubectl get pod 38 | echo 39 | echo "$podstatus" | grep -q 'Running' || \ 40 | _errordbg "Pod did not reach Running state" "pod/${podname}" 41 | 42 | echo "waiting for samba to become reachable" 43 | tries=0 44 | rc=1 45 | while [ $tries -lt 120 ] && [ $rc -ne 0 ]; do 46 | sleep 1 47 | tries=$(( tries + 1 )) 48 | kubectl exec "${podname}" -c "smb" -- smbclient -N -L 127.0.0.1 2>/dev/null 1>/dev/null 49 | rc=$? 50 | echo -n "." 51 | done 52 | echo 53 | [ $rc -eq 0 ] || _error "Error: samba ad did not become reachable" 54 | 55 | echo "member setup done" 56 | -------------------------------------------------------------------------------- /tests/test-deploy-ad-server.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | SCRIPT_DIR="$(cd "$(dirname "${0}")" && pwd)" 4 | IMG_TAG=${IMG_TAG:-"latest"} 5 | 6 | source "${SCRIPT_DIR}/common.sh" 7 | 8 | echo "Creating ad server deployment..." 9 | ERROR_MSG=$(IMG_TAG=${IMG_TAG} envsubst < "${AD_DEPLOYMENT_YAML}" | kubectl create -f - 2>&1 1>/dev/null) 10 | if [ $? -ne 0 ] ; then 11 | if [[ "${ERROR_MSG}" =~ "AlreadyExists" ]] ; then 12 | echo "Deployment exists already. Continuing." 13 | else 14 | _error "Error creating ad server deployment." 15 | fi 16 | fi 17 | 18 | kubectl get deployment 19 | 20 | replicaset="$(kubectl describe deployment "${AD_DEPLOYMENT_NAME}" | grep -s "NewReplicaSet:" | awk '{ print $2 }')" 21 | [ $? -eq 0 ] || _error "Error getting replicaset" 22 | 23 | podname="$(kubectl get pod | grep "$replicaset" | awk '{ print $1 }')" 24 | [ $? -eq 0 ] || _error "Error getting podname" 25 | 26 | echo "Samba ad pod is $podname" 27 | 28 | echo "waiting for pod to be in Running state" 29 | tries=0 30 | podstatus="none" 31 | until [ $tries -ge 120 ] || echo "$podstatus" | grep -q 'Running'; do 32 | sleep 1 33 | echo -n "." 34 | tries=$(( tries + 1 )) 35 | podstatus="$(kubectl get pod "$podname" -o go-template='{{.status.phase}}')" 36 | done 37 | echo 38 | kubectl get pod 39 | echo 40 | echo "$podstatus" | grep -q 'Running' || \ 41 | _errordbg "Pod did not reach Running state" "deployment/${AD_DEPLOYMENT_NAME}" "pod/${podname}" 42 | 43 | echo "waiting for samba to become reachable" 44 | tries=0 45 | rc=1 46 | while [ $tries -lt 120 ] && [ $rc -ne 0 ]; do 47 | sleep 1 48 | tries=$(( tries + 1 )) 49 | kubectl exec "${podname}" -- smbclient -N -L 127.0.0.1 2>/dev/null 1>/dev/null 50 | rc=$? 51 | echo -n "." 52 | done 53 | echo 54 | [ $rc -eq 0 ] || _error "Error: samba ad did not become reachable" 55 | 56 | 57 | echo "patching coredns zonefile" 58 | 59 | AD_POD_IP=$(kubectl get pod -o jsonpath='{ .items[*].status.podIP }') 60 | [ $? -eq 0 ] || _error "Error getting ad server pod IP" 61 | 62 | echo "AD pod IP: ${AD_POD_IP}" 63 | 64 | TMPFILE=$(mktemp) 65 | 66 | cat > "${TMPFILE}" <> "${TMPFILE}" 74 | 75 | echo >> "${TMPFILE}" 76 | 77 | # don't repeat an existing block for our domain 78 | FIRSTLINE="$(head -1 ./tests/files/coredns-snippet.template)" 79 | LASTLINE=" }" 80 | 81 | sed -i .backup -e "/$FIRSTLINE/,/$LASTLINE/d" "${TMPFILE}" 82 | 83 | sed -e "s/AD_SERVER_IP/${AD_POD_IP}/" \ 84 | < tests/files/coredns-snippet.template \ 85 | >> "${TMPFILE}" 86 | 87 | echo >> "${TMPFILE}" 88 | 89 | kubectl patch cm -n kube-system coredns -p "$(cat "${TMPFILE}")" 90 | [ $? -eq 0 ] || _error "Error patching coredns config map" 91 | 92 | echo "ad setup done" 93 | -------------------------------------------------------------------------------- /tests/test-remove-ad-member.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | SCRIPT_DIR="$(cd "$(dirname "${0}")" && pwd)" 4 | 5 | source "${SCRIPT_DIR}/common.sh" 6 | 7 | if [ "${KEEP}" -eq 1 ]; then 8 | echo "keeping ad member pod (KEEP=1)" 9 | exit 0 10 | fi 11 | 12 | echo "removing ad member pod..." 13 | kubectl delete pod "${MEMBER_POD_NAME}" 14 | [ $? -eq 0 ] || _error "Error deleting pod" 15 | echo 16 | 17 | kubectl delete cm "${MEMBER_CM_NAME}" 18 | [ $? -eq 0 ] || _error "Error deleting configmap" 19 | echo 20 | 21 | kubectl delete secret "${MEMBER_SECRET_NAME}" 22 | [ $? -eq 0 ] || _error "Error deleting secret" 23 | echo 24 | 25 | echo "ad member pod removed" 26 | -------------------------------------------------------------------------------- /tests/test-remove-ad-server.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | SCRIPT_DIR="$(cd "$(dirname "${0}")" && pwd)" 4 | 5 | source "${SCRIPT_DIR}/common.sh" 6 | 7 | if [ "${KEEP}" -eq 1 ]; then 8 | echo "keeping ad server deployment (KEEP=1)" 9 | exit 0 10 | fi 11 | 12 | echo "removing ad server deployment..." 13 | kubectl delete deployment "${AD_DEPLOYMENT_NAME}" 14 | [ $? -eq 0 ] || _error "Error deleting deployment" 15 | echo 16 | echo "ad server deployment removed" 17 | -------------------------------------------------------------------------------- /tests/test-samba-ad-server-kubernetes.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | SCRIPT_DIR="$(cd "$(dirname "${0}")" && pwd)" 4 | 5 | source "${SCRIPT_DIR}/common.sh" 6 | 7 | source "${SCRIPT_DIR}/test-deploy-ad-server.sh" 8 | 9 | kubectl exec "${podname}" -- samba-tool domain info 127.0.0.1 10 | [ $? -eq 0 ] || _error "Error listing domain info" 11 | echo 12 | 13 | source "${SCRIPT_DIR}/test-deploy-ad-member.sh" 14 | 15 | kubectl exec "${podname}" -c "smb" -- smbclient -N -L 127.0.0.1 16 | kubectl exec "${podname}" -c "winbind" -- wbinfo -t 17 | # note: testing `wbinfo -t` from the smb container again 18 | # to make sure samba can communicate to winbindd 19 | kubectl exec "${podname}" -c "smb" -- wbinfo -t 20 | 21 | source "${SCRIPT_DIR}/test-remove-ad-member.sh" 22 | 23 | source "${SCRIPT_DIR}/test-remove-ad-server.sh" 24 | 25 | echo 26 | echo "Success" 27 | exit 0 28 | -------------------------------------------------------------------------------- /tests/test-samba-container.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | 5 | echo "determining container command." 6 | if [ -z "${CONTAINER_CMD}" ]; then 7 | CONTAINER_CMD=$(command -v docker || echo ) 8 | fi 9 | if [ -z "${CONTAINER_CMD}" ]; then 10 | CONTAINER_CMD=$(command -v podman || echo ) 11 | fi 12 | if [ -z "${CONTAINER_CMD}" ]; then 13 | echo "Error determining container command." 14 | exit 1 15 | fi 16 | echo "container command: '${CONTAINER_CMD}'." 17 | echo "creating temporary directory." 18 | TMPDIR="$(mktemp -d)" 19 | rc=$? 20 | 21 | if [ $rc -ne 0 ]; then 22 | echo "Error creating temporary directory." 23 | exit 1 24 | fi 25 | echo "temporary directory: '${TMPDIR}'" 26 | echo "starting Samba container." 27 | CONTAINER_ID="$(${CONTAINER_CMD} run --network=none --name samba \ 28 | --volume="${TMPDIR}":/share:Z --rm -d "${LOCAL_TAG}")" 29 | rc=$? 30 | 31 | if [ $rc -ne 0 ]; then 32 | echo "Error running samba container" 33 | exit 1 34 | fi 35 | echo "Container started, ID: '${CONTAINER_ID}'" 36 | 37 | # give samba a second to come up 38 | sleep 1 39 | 40 | echo "Listing samba shares" 41 | ${CONTAINER_CMD} exec "${CONTAINER_ID}" smbclient -U% -L 127.0.0.1 42 | rc=$? 43 | 44 | if [ ${rc} -ne 0 ]; then 45 | echo "Error listing samba shares" 46 | exit 1 47 | fi 48 | 49 | 50 | echo "stopping samba container." 51 | 52 | ${CONTAINER_CMD} kill "${CONTAINER_ID}" 53 | rc=$? 54 | 55 | if [ $rc -ne 0 ]; then 56 | echo "Error stopping samba container" 57 | exit 1 58 | fi 59 | 60 | echo "samba container stopped." 61 | 62 | 63 | 64 | 65 | echo "removing temporary directory." 66 | rm -rf "${TMPDIR}" 67 | rc=$? 68 | 69 | 70 | if [ $rc -eq 0 ]; then 71 | echo "Success" 72 | fi 73 | 74 | exit $rc 75 | --------------------------------------------------------------------------------