diff --git a/.codecov.yml b/.codecov.yml index 3f912306d..580be65ec 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -2,8 +2,9 @@ coverage: status: project: default: - threshold: 0.1 + threshold: 1 + informational: true patch: default: - # minimum coverage at 0, should never fail, but will still report target: 0 + informational: true diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..c587c555b --- /dev/null +++ b/.dockerignore @@ -0,0 +1,17 @@ +**/.venv* +**/.virtualenv +**/target +**/docs +**/out +**/.log +**/.idea/ +**/.bsp +**/*cache* +**/.git +**/Dockerfile +**/*.dockerignore +**/.github +**/_template +img/ +**/.env +modules/portal/node_modules/ diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index d94ba7ac2..bec832b8b 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,28 +1,16 @@ --- -name: Bug report +name: Bug Report about: Create a report to help us improve +title: '' +labels: status/needs-label +assignees: '' --- **Describe the bug** -A clear and concise description of what the bug is. +Please provide as much detail as you can. Here are some important details: -**VinylDNS Version** - -**To Reproduce** -Steps to reproduce the behavior: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**Stack trace or error log output** - -**Additional context** -Add any other context about the problem here. +1. A description of the bug (expected behavior vs actual behavior) +2. The VinylDNS version which contains the bug +3. Any steps to reproduce (if we can't reproduce it, we can't fix it!) +4. Any other helpful information (stack trace, log messages, screenshots, etc) diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 066b2d920..01fa5a072 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,17 +1,10 @@ --- name: Feature request about: Suggest an idea for this project +title: '' +labels: status/needs-label +assignees: '' --- -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. +**Describe what you'd like to see added or improved in VinylDNS** diff --git a/.github/ISSUE_TEMPLATE/maintenance-request.md b/.github/ISSUE_TEMPLATE/maintenance-request.md deleted file mode 100644 index fca91f282..000000000 --- a/.github/ISSUE_TEMPLATE/maintenance-request.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -name: Maintenance request -about: Suggest an upgrade, refactoring, code move, new library - ---- - -**Motivation** -What is the reason to perform the maintenance. What benefits will come about - -**Scope of change** -What part(s) of the system are likely to change. For example, REST endpoints, repositories, core, functional tests, etc. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 89a58987c..000000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,143 +0,0 @@ -# Much copied from sbt-github-actions, modified to support running e2e tests -name: Continuous Integration - -on: - pull_request: - branches: ['*'] - push: - branches: ['master'] - -env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - -jobs: - build: - name: Build and Test - if: "!contains(github.event.head_commit.message, 'ci skip')" - strategy: - matrix: - os: [ubuntu-latest] - scala: [2.12.10] - java: [adopt@1.11] - runs-on: ${{ matrix.os }} - steps: - - name: Checkout current branch (full) - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - name: Setup Java and Scala - uses: olafurpg/setup-scala@v10 - env: - ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true' - with: - java-version: ${{ matrix.java }} - - - name: Cache ivy2 - uses: actions/cache@v1 - with: - path: ~/.ivy2/cache - key: ${{ runner.os }}-sbt-ivy-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - - - name: Cache coursier (generic) - uses: actions/cache@v1 - with: - path: ~/.coursier/cache/v1 - key: ${{ runner.os }}-generic-sbt-coursier-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - - - name: Cache coursier (linux) - if: contains(runner.os, 'linux') - uses: actions/cache@v1 - with: - path: ~/.cache/coursier/v1 - key: ${{ runner.os }}-sbt-coursier-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - - - name: Cache coursier (macOS) - if: contains(runner.os, 'macos') - uses: actions/cache@v1 - with: - path: ~/Library/Caches/Coursier/v1 - key: ${{ runner.os }}-sbt-coursier-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - - - name: Cache coursier (windows) - if: contains(runner.os, 'windows') - uses: actions/cache@v1 - with: - path: ~/AppData/Local/Coursier/Cache/v1 - key: ${{ runner.os }}-sbt-coursier-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - - - name: Cache sbt - uses: actions/cache@v1 - with: - path: ~/.sbt - key: ${{ runner.os }}-sbt-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - - - run: sbt ++${{ matrix.scala }} validate verify - - - name: Codecov - uses: codecov/codecov-action@v1 - with: - fail_ci_if_error: true # optional (default = false) - - func: - name: Func Test - if: "!contains(github.event.head_commit.message, 'ci skip')" - strategy: - matrix: - os: [ubuntu-latest] - scala: [2.12.10] - java: [adopt@1.11] - runs-on: ${{ matrix.os }} - steps: - - name: Checkout current branch (full) - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - name: Setup Java and Scala - uses: olafurpg/setup-scala@v10 - env: - ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true' - with: - java-version: ${{ matrix.java }} - - - name: Cache ivy2 - uses: actions/cache@v1 - with: - path: ~/.ivy2/cache - key: ${{ runner.os }}-sbt-ivy-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - - - name: Cache coursier (generic) - uses: actions/cache@v1 - with: - path: ~/.coursier/cache/v1 - key: ${{ runner.os }}-generic-sbt-coursier-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - - - name: Cache coursier (linux) - if: contains(runner.os, 'linux') - uses: actions/cache@v1 - with: - path: ~/.cache/coursier/v1 - key: ${{ runner.os }}-sbt-coursier-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - - - name: Cache coursier (macOS) - if: contains(runner.os, 'macos') - uses: actions/cache@v1 - with: - path: ~/Library/Caches/Coursier/v1 - key: ${{ runner.os }}-sbt-coursier-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - - - name: Cache coursier (windows) - if: contains(runner.os, 'windows') - uses: actions/cache@v1 - with: - path: ~/AppData/Local/Coursier/Cache/v1 - key: ${{ runner.os }}-sbt-coursier-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - - - name: Cache sbt - uses: actions/cache@v1 - with: - path: ~/.sbt - key: ${{ runner.os }}-sbt-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - - name: Func tests - run: ./bin/func-test-portal.sh && ./bin/func-test-api-travis.sh diff --git a/.github/workflows/clean.yml b/.github/workflows/clean.yml deleted file mode 100644 index d4e115d0f..000000000 --- a/.github/workflows/clean.yml +++ /dev/null @@ -1,55 +0,0 @@ -# This file was automatically generated by sbt-github-actions using the -# githubWorkflowGenerate task. Kept it here - -name: Clean - -on: push - -jobs: - delete-artifacts: - name: Delete Artifacts - runs-on: ubuntu-latest - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - name: Delete artifacts - run: | - # Customize those three lines with your repository and credentials: - REPO=${GITHUB_API_URL}/repos/${{ github.repository }} - - # A shortcut to call GitHub API. - ghapi() { curl --silent --location --user _:$GITHUB_TOKEN "$@"; } - - # A temporary file which receives HTTP response headers. - TMPFILE=/tmp/tmp.$$ - - # An associative array, key: artifact name, value: number of artifacts of that name. - declare -A ARTCOUNT - - # Process all artifacts on this repository, loop on returned "pages". - URL=$REPO/actions/artifacts - while [[ -n "$URL" ]]; do - - # Get current page, get response headers in a temporary file. - JSON=$(ghapi --dump-header $TMPFILE "$URL") - - # Get URL of next page. Will be empty if we are at the last page. - URL=$(grep '^Link:' "$TMPFILE" | tr ',' '\n' | grep 'rel="next"' | head -1 | sed -e 's/.*.*//') - rm -f $TMPFILE - - # Number of artifacts on this page: - COUNT=$(( $(jq <<<$JSON -r '.artifacts | length') )) - - # Loop on all artifacts on this page. - for ((i=0; $i < $COUNT; i++)); do - - # Get name of artifact and count instances of this name. - name=$(jq <<<$JSON -r ".artifacts[$i].name?") - ARTCOUNT[$name]=$(( $(( ${ARTCOUNT[$name]} )) + 1)) - - id=$(jq <<<$JSON -r ".artifacts[$i].id?") - size=$(( $(jq <<<$JSON -r ".artifacts[$i].size_in_bytes?") )) - printf "Deleting '%s' #%d, %'d bytes\n" $name ${ARTCOUNT[$name]} $size - ghapi -X DELETE $REPO/actions/artifacts/$id - done - done diff --git a/.github/workflows/codecov_review.yml b/.github/workflows/codecov_review.yml deleted file mode 100644 index 37e6e02f7..000000000 --- a/.github/workflows/codecov_review.yml +++ /dev/null @@ -1,12 +0,0 @@ -name: Codecov Review - -on: - workflow_dispatch: - -jobs: - review: - runs-on: ubuntu-latest - - steps: - - name: Output Environment - run: env diff --git a/.github/workflows/publish-site.yml b/.github/workflows/publish-site.yml index 3e3089032..1fd48df43 100644 --- a/.github/workflows/publish-site.yml +++ b/.github/workflows/publish-site.yml @@ -1,85 +1,27 @@ -# Generates the microsite on push to master -# Relies on the SBT_MICROSITES_PUBLISH_TOKEN secret to be setup -# as a Github secret name: Microsite +concurrency: + cancel-in-progress: true + group: "publish-site" + +defaults: + run: + shell: bash on: - push: - branches: - - master + workflow_dispatch: + branches: [ 'master', 'main' ] jobs: site: name: Publish Site - strategy: - matrix: - os: [ubuntu-latest] - scala: [2.12.10] - java: [adopt@1.11] - runs-on: ${{ matrix.os }} + runs-on: ubuntu-latest steps: - name: Checkout current branch (full) uses: actions/checkout@v2 with: fetch-depth: 0 - - name: Setup Java and Scala - uses: olafurpg/setup-scala@v10 - env: - ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true' - with: - java-version: ${{ matrix.java }} - - - name: Cache ivy2 - uses: actions/cache@v1 - with: - path: ~/.ivy2/cache - key: ${{ runner.os }}-sbt-ivy-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - - - name: Cache coursier (generic) - uses: actions/cache@v1 - with: - path: ~/.coursier/cache/v1 - key: ${{ runner.os }}-generic-sbt-coursier-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - - - name: Cache coursier (linux) - if: contains(runner.os, 'linux') - uses: actions/cache@v1 - with: - path: ~/.cache/coursier/v1 - key: ${{ runner.os }}-sbt-coursier-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - - - name: Cache coursier (macOS) - if: contains(runner.os, 'macos') - uses: actions/cache@v1 - with: - path: ~/Library/Caches/Coursier/v1 - key: ${{ runner.os }}-sbt-coursier-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - - - name: Cache coursier (windows) - if: contains(runner.os, 'windows') - uses: actions/cache@v1 - with: - path: ~/AppData/Local/Coursier/Cache/v1 - key: ${{ runner.os }}-sbt-coursier-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - - - name: Cache sbt - uses: actions/cache@v1 - with: - path: ~/.sbt - key: ${{ runner.os }}-sbt-cache-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - - - name: Set up Ruby - uses: actions/setup-ruby@v1 - with: - ruby-version: 2.6 - - - name: Install dependencies - run: > - sudo apt install libxslt-dev && - gem install sass jekyll:4.0.0 - - - run: sbt ++${{ matrix.scala }} ";project docs; publishMicrosite"; + - run: "build/publish_docs.sh" env: SBT_MICROSITES_PUBLISH_TOKEN: ${{ secrets.VINYLDNS_MICROSITE }} ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true' diff --git a/.github/workflows/release-vnext.yml b/.github/workflows/release-vnext.yml new file mode 100755 index 000000000..74204446c --- /dev/null +++ b/.github/workflows/release-vnext.yml @@ -0,0 +1,90 @@ +name: VinylDNS Release vNext +concurrency: + cancel-in-progress: true + group: "release-vnext" + +defaults: + run: + shell: bash + +on: + push: + branches: [ 'master','main' ] + workflow_dispatch: + +env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +jobs: + + verify: + name: Verify Release + if: "!contains(github.event.head_commit.message, 'ci skip')" + runs-on: ubuntu-latest + + steps: + - name: Checkout current branch + if: github.event_name != 'push' # We only need to verify if this is manually triggered + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Build and Test + if: github.event_name != 'push' # We only need to verify if this is manually triggered + run: cd build/ && ./assemble_api.sh && ./run_all_tests.sh + + docker-release-api: + name: Release API vNext Image + needs: [ verify ] + runs-on: ubuntu-latest + + steps: + - name: Checkout current branch (full) + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Login to Docker Hub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_USER }} + password: ${{ secrets.DOCKER_TOKEN }} + + - name: Import Content Trust Key + run: docker trust key load <(echo "${SIGNING_KEY}") --name vinyldns_svc + env: + SIGNING_KEY: ${{ secrets.SIGNING_KEY }} + DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE }} + + - name: Publish API Docker Image + run: make -C build/docker/api publish-vnext + env: + DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE }} + + docker-release-portal: + name: Release Portal vNext Image + needs: [ verify ] + runs-on: ubuntu-latest + + steps: + - name: Checkout current branch (full) + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Login to Docker Hub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_USER }} + password: ${{ secrets.DOCKER_TOKEN }} + + - name: Import Content Trust Key + run: docker trust key load <(echo "${SIGNING_KEY}") --name vinyldns_svc + env: + SIGNING_KEY: ${{ secrets.SIGNING_KEY }} + DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE }} + + - name: Publish Portal Docker Image + run: make -C build/docker/portal publish-vnext + env: + DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..d1ce26c22 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,144 @@ +name: VinylDNS Official Release +concurrency: + cancel-in-progress: true + group: "release" + +defaults: + run: + shell: bash + +on: + workflow_dispatch: + inputs: + verify-first: + description: 'Verify First?' + required: true + default: 'true' + create-gh-release: + description: 'Create a GitHub Release?' + required: true + default: 'true' + publish-images: + description: 'Publish Docker Images?' + required: true + default: 'true' + +env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +jobs: + verify: + name: Verify Release + runs-on: ubuntu-latest + + steps: + - name: Checkout current branch + if: github.event.inputs.verify-first == 'true' + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Run Tests + id: verify + if: github.event.inputs.verify-first == 'true' + run: cd build/ && ./assemble_api.sh && ./run_all_tests.sh + + create-gh-release: + name: Create GitHub Release + needs: verify + runs-on: ubuntu-latest + if: github.event.inputs.create-gh-release == 'true' + permissions: + contents: write + + steps: + - name: Checkout current branch + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Build Artifacts + id: build + run: cd build/ && ./assemble_api.sh && ./assemble_portal.sh + + - name: Get Version + id: get-version + run: echo "::set-output name=vinyldns_version::$(awk -F'"' '{print $2}' ./version.sbt)" + + - name: Create GitHub Release + id: create_release + uses: softprops/action-gh-release@1e07f4398721186383de40550babbdf2b84acfc5 # v0.1.14 + with: + tag_name: v${{ steps.get-version.outputs.vinyldns_version }} + generate_release_notes: true + files: artifacts/* + + docker-release-api: + name: Release API Docker Image + needs: [ verify, create-gh-release ] + runs-on: ubuntu-latest + if: github.event.inputs.publish-images == 'true' + + steps: + - name: Get Version + id: get-version + run: echo "::set-output name=vinyldns_version::$(curl -s https://api.github.com/repos/vinyldns/vinyldns/releases | jq -rc '.[0].tag_name')" + + - name: Checkout current branch (full) + uses: actions/checkout@v2 + with: + ref: ${{ steps.get-version.outputs.vinyldns_version }} + fetch-depth: 0 + + - name: Login to Docker Hub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_USER }} + password: ${{ secrets.DOCKER_TOKEN }} + + - name: Import Content Trust Key + run: docker trust key load <(echo "${SIGNING_KEY}") --name vinyldns_svc + env: + SIGNING_KEY: ${{ secrets.SIGNING_KEY }} + DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE }} + + # This will publish the latest release + - name: Publish API Docker Image + run: make -C build/docker/api publish + env: + DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE }} + + docker-release-portal: + name: Release Portal Docker Image + needs: [ verify, create-gh-release ] + runs-on: ubuntu-latest + if: github.event.inputs.publish-images == 'true' + + steps: + - name: Get Version + id: get-version + run: echo "::set-output name=vinyldns_version::$(curl -s https://api.github.com/repos/vinyldns/vinyldns/releases | jq -rc '.[0].tag_name')" + + - name: Checkout current branch (full) + uses: actions/checkout@v2 + with: + ref: ${{ steps.get-version.outputs.vinyldns_version }} + fetch-depth: 0 + + - name: Login to Docker Hub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_USER }} + password: ${{ secrets.DOCKER_TOKEN }} + + - name: Import Content Trust Key + run: docker trust key load <(echo "${SIGNING_KEY}") --name vinyldns_svc + env: + SIGNING_KEY: ${{ secrets.SIGNING_KEY }} + DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE }} + + # This will publish the latest release + - name: Publish Portal Docker Image + run: make -C build/docker/portal publish + env: + DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE: ${{ secrets.DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE }} diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml new file mode 100644 index 000000000..76e9bf8e1 --- /dev/null +++ b/.github/workflows/verify.yml @@ -0,0 +1,35 @@ +name: Verify and Test + +defaults: + run: + shell: bash + +on: + pull_request: + branches: [ '*' ] + push: + branches: [ 'master','main' ] + +env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +jobs: + build: + name: Run Tests + runs-on: ubuntu-latest + if: "!contains(github.event.head_commit.message, 'ci skip')" + + steps: + - name: Checkout current branch (full) + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Build and Test + run: cd build/ && ./assemble_api.sh && ./run_all_tests.sh + + - name: Codecov + uses: codecov/codecov-action@v2 + with: + token: ${{ secrets.CODECOV_TOKEN }} + fail_ci_if_error: false diff --git a/.gitignore b/.gitignore index 12421c8c6..40aaed248 100644 --- a/.gitignore +++ b/.gitignore @@ -31,4 +31,8 @@ tmp.out .vscode project/metals.sbt .bsp -docker/data +quickstart/data +**/.virtualenv +**/.venv* +**/*cache* +**/artifacts/ diff --git a/AUTHORS.md b/AUTHORS.md index 0e4424a1e..6e42640fd 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -1,23 +1,12 @@ # Authors -This project would not be possible without the generous contributions of many people. -Thank you! If you have contributed in any way, but do not see your name here, please open a PR to add yourself (in alphabetical order by last name)! - -## Maintainers -- Paul Cleary -- Ryan Emerle -- Nima Eskandary - -## Tool Maintainers -- Mike Ball: vinyldns-cli, vinyldns-terraform -- Nathan Pierce: vinyldns-ruby - -## DNS SMEs -- Joe Crowe -- David Back -- Hong Ye +This project would not be possible without the generous contributions of many people. Thank you! If you have contributed +in any way, but do not see your name here, please open a PR to add yourself (in alphabetical order by last name)! ## Contributors + +- David Back +- Mike Ball - Tommy Barker - Robert Barrimond - Charles Bitter @@ -25,11 +14,14 @@ Thank you! If you have contributed in any way, but do not see your name here, pl - Maulon Byron - Shirlette Chambers - Varsha Chandrashekar +- Paul Cleary - Peter Cline - Kemar Cockburn - Luke Cori +- Joe Crowe - Jearvon Dharrie - Andrew Dunn +- Ryan Emerle - David Grizzanti - Alejandro Guirao - Daniel Jin @@ -37,16 +29,19 @@ Thank you! If you have contributed in any way, but do not see your name here, pl - Krista Khare - Patrick Lee - Sheree Liu +- Michael Ly - Deepak Mohanakrishnan - Jon Moore - Palash Nigam - Joshulyne Park +- Nathan Pierce - Michael Pilquist - Sriram Ramakrishnan - Khalid Reid - Timo Schmid - Trent Schmidt - Ghafar Shah +- Rebecca Star - Jess Stodola - Juan Valencia - Anastasia Vishnyakova @@ -54,3 +49,5 @@ Thank you! If you have contributed in any way, but do not see your name here, pl - Fei Wan - Andrew Wang - Peter Willis +- Britney Wright +- Hong Ye diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 519e24176..3e600ece6 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,8 +1,11 @@ -# VinylDNS Code of Conduct +# Contributor Covenant Code of Conduct ## Our Pledge -In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making +participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, +disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, +religion, or sexual identity and orientation. ## Our Standards @@ -24,23 +27,36 @@ Examples of unacceptable behavior by participants include: ## Our Responsibilities -Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take +appropriate and fair corrective action in response to any instances of unacceptable behavior. -Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, +issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any +contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope -This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the +project or its community. Examples of representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed representative at an online or offline +event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at vinyldns-core@googlegroups.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team +at [Comcast_Open_Source_Services@comcast.com](mailto:Comcast_Open_Source_Services@comcast.com). All complaints will be +reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. +The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of +specific enforcement policies may be posted separately. -Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent +repercussions as determined by other members of the project's leadership. ## Attribution -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available +at [http://contributor-covenant.org/version/1/4][version] [homepage]: http://contributor-covenant.org + [version]: http://contributor-covenant.org/version/1/4/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3e3f59238..7a190d95e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,7 +1,9 @@ # Contributing to VinylDNS + The following are a set of guidelines for contributing to VinylDNS and its associated repositories. ## Table of Contents + * [Code of Conduct](#code-of-conduct) * [Issues](#issues) * [Working on an Issue](#working-on-an-issue) @@ -18,112 +20,139 @@ The following are a set of guidelines for contributing to VinylDNS and its assoc * [Contributor License Agreement](#contributor-license-agreement) * [Modifying your Pull Request](#modifying-your-pull-requests) * [Pull Request Approval](#pull-request-approval) -* [Release Management](#release-management) - + ## Code of Conduct -This project and everyone participating in it are governed by the [VinylDNS Code Of Conduct](CODE_OF_CONDUCT.md). By -participating, you agree to this Code. Please report any violations to the code of conduct to vinyldns-core@googlegroups.com. + +This project and everyone participating in it are governed by the [VinylDNS Code Of Conduct](https://github.com/vinyldns/vinyldns/blob/master/CODE_OF_CONDUCT.md). By +participating, you agree to this Code. ## Issues -Work on VinylDNS is tracked by [Github Issues](https://guides.github.com/features/issues/). To contribute to VinylDNS, +Work on VinylDNS is tracked by [GitHub Issues](https://guides.github.com/features/issues/). To contribute to VinylDNS, you can join the discussion on an issue, submit a Pull Request to resolve the issue, or make an issue of your own. VinylDNS issues are generally labeled as bug reports, feature requests, or maintenance requests. ### Working on an Issue -If you would like to contribute to VinylDNS, you can look through `good first issue` and `help wanted` issues. We keep a list -of these issues around to encourage participation in building the platform. In the issue list, you can chose "Labels" and -choose a specific label to narrow down the issues to review. -* **Beginner issues**: only require a few lines of code to complete, rather isolated to one or two files. A good way -to get through changing and testing your code, and meet everyone! -* **Help wanted issues**: these are more involved than beginner issues, are items that tend to come near the top of our -backlog but not necessarily in the current development stream. +If you would like to contribute to VinylDNS, you can look through `good first issue` and `help wanted` issues. We keep a +list of these issues around to encourage participation in building the platform. In the issue list, you can chose " +Labels" and choose a specific label to narrow down the issues to review. -Besides those issues, you can sort the issue list by number of comments to find one that may be of interest. You do +- **Beginner issues**: only require a few lines of code to complete, rather isolated to one or two files. A good way to + get through changing and testing your code, and meet everyone! +- **Help wanted issues**: these are more involved than beginner issues, are items that tend to come near the top of our + backlog but not necessarily in the current development stream. + +Besides those issues, you can sort the issue list by number of comments to find one that may be of interest. You do _not_ have to limit yourself to _only_ `good first issue` or `help wanted` issues. -When resolving an issue, you generally will do so by making a [Pull Request](#pull-requests), and adding a link to the issue. +When resolving an issue, you generally will do so by making a [Pull Request](#pull-requests), and adding a link to the +issue. -Before choosing an issue, see if anyone is assigned or has indicated they are working on it (either in comment or via Pull Request). -If that is the case, then instead of making a Pull Request of your own, you can help out by reviewing their Pull Request. +Before choosing an issue, see if anyone is assigned or has indicated they are working on it (either in comment or via +Pull Request). If that is the case, then instead of making a Pull Request of your own, you can help out by reviewing +their Pull Request. ### Submitting an Issue -When submitting an issue you will notice there are three issue templates to choose from. Before making any issue, please -go search the issue list (open and closed issues) and check to see if a similar issue has been made. If so, we ask that you do not duplicate an -issue, but feel free to comment on the existing issue with additional details. -* **Bug report**: If you find a bug in the project you can report it with this template and the VinylDNS team will take a -look at it. Please be as detailed as possible as it will help us recreate the bug and figure out what exactly is going on. -If you are unsure whether what you found is a bug, we encourage you to first pop in our [dev gitter](https://gitter.im/vinyldns/vinyldns), and we can -help determine if what you're seeing is unexpected behavior, and if it is we will direct to make the bug report. -* **Feature request**: Use this template if you have something you wish to be added to the project. Please be detailed -when describing why you are requesting the feature, what you want it to do, and alternative solutions you have considered. -* **Maintenance request**: This template is for suggesting upgrades to the existing code base. This could include -code refactoring, new libraries, additional testing, among other things. Please be detailed when describing the -reason for the maintenance, and what benefits will come out of it. Please describe the scope of the change, and -what parts of the system will be impacted. +When submitting an issue you will notice there are three issue templates to choose from. Before making any issue, please +go search the issue list (open and closed issues) and check to see if a similar issue has been made. If so, we ask that +you do not duplicate an issue, but feel free to comment on the existing issue with additional details. + +- **Bug report**: If you find a bug in the project you can report it with this template and the VinylDNS team will take + a look at it. Please be as detailed as possible as it will help us recreate the bug and figure out what exactly is + going on. If you are unsure whether what you found is a bug, we encourage you to first pop in + our [discussion board](https://github.com/vinyldns/vinyldns/discussions), and we can help determine if what you're + seeing is unexpected behavior, and if it is we will direct to make the bug report. +- **Feature request**: Use this template if you have something you wish to be added to the project. Please be detailed + when describing why you are requesting the feature, what you want it to do, and alternative solutions you have + considered. ### Discussion Process -Some issues may require discussion with the community before proceeding to implementation. This can happen if the issue is a larger change, for example a big refactoring or new feature. The VinylDNS maintainers may label an issue for **Discussion** in order to solicit more detail before proceeding. If the issue is straightforward and/or well documented, it can be implemented immediately by the submitter. If the submitter is unable to make the changes required to address the issue, the VinylDNS maintainers will prioritize the work in our backlog. +Some issues may require discussion with the community before proceeding to implementation. This can happen if the issue +is a larger change, for example a big refactoring or new feature. The VinylDNS maintainers may label an issue for ** +Discussion** in order to solicit more detail before proceeding. If the issue is straightforward and/or well documented, +it can be implemented immediately by the submitter. If the submitter is unable to make the changes required to address +the issue, the VinylDNS maintainers will prioritize the work in our backlog. ## Pull Requests -Contributions to VinylDNS are generally made via [Github Pull Requests](https://help.github.com/articles/about-pull-requests/). -Most Pull Requests are related to an [issue](#issues), and will have a link to the issue in the Pull Request. + +Contributions to VinylDNS are generally made +via [Github Pull Requests](https://help.github.com/articles/about-pull-requests/). Most Pull Requests are related to +an [issue](#issues), and will have a link to the issue in the Pull Request. ### General Flow -We follow the standard *GitHub Flow* for taking code contributions. The following is the process typically followed: + +We follow the standard *GitHub Flow* for taking code contributions. The following is the process typically followed: 1. Create a fork of the repository that you want to contribute code to 1. Clone your forked repository to your local machine 1. In your local machine, add a remote to the "main" repository, we call this "upstream" by running -`git remote add upstream https://github.com/vinyldns/vinyldns.git`. Note: you can also use `ssh` instead of `https` -1. Create a local branch for your work `git checkout -b your-user-name/user-branch-name`. Add whatever your GitHub -user name is before whatever you want your branch to be. + `git remote add upstream https://github.com/vinyldns/vinyldns.git`. Note: you can also use `ssh` instead of `https` +1. Create a local branch for your work `git checkout -b your-user-name/user-branch-name`. Add whatever your GitHub user + name is before whatever you want your branch to be. 1. Begin working on your local branch -1. Be sure to add necessary unit, integration, and functional tests, see the [Testing](DEVELOPER_GUIDE.md#testing) section of the Developer Guide. -1. Make sure you run all builds before posting a Pull Request! It's faster to run everything locally rather than waiting for -the build server to complete its job. See [DEVELOPER_GUIDE.md](DEVELOPER_GUIDE.md) for information on local development. -1. When you are ready to contribute your code, run `git push origin your-user-name/user-branch-name` to push your changes -to your _own fork_ -1. Go to the [VinylDNS main repository](https://github.com/vinyldns/vinyldns.git) (or whatever repo you are contributing to) -and you will see your change waiting and a link to "Create a Pull Request". Click the link to create a Pull Request. -1. Be as detailed as possible in the description of your Pull Request. Describe what you changed, why you changed it, and -give a detailed list of changes and impacted files. If your Pull Request is related to an existing issue, be sure to link the -issue in the Pull Request itself, in addition to the Pull Request description. -1. You will receive comments on your Pull Request. Use the Pull Request as a dialog on your changes. +1. Be sure to add necessary unit, integration, and functional tests, see + the [Testing](https://github.com/vinyldns/vinyldns/blob/master/DEVELOPER_GUIDE.md#testing) + section of the Developer Guide. +1. Make sure you run all builds before posting a Pull Request! It's faster to run everything locally rather than waiting + for the build server to complete its job. + See [DEVELOPER_GUIDE.md](https://github.com/vinyldns/vinyldns/blob/master/DEVELOPER_GUIDE.md) for information on + local development. +1. When you are ready to contribute your code, run `git push origin your-user-name/user-branch-name` to push your + changes to your _own fork_ +1. Go to the [VinylDNS main repository](https://github.com/vinyldns/vinyldns.git) (or whatever repo you are contributing + to) + and you will see your change waiting and a link to "Create a Pull Request". Click the link to create a Pull Request. +1. Be as detailed as possible in the description of your Pull Request. Describe what you changed, why you changed it, + and give a detailed list of changes and impacted files. If your Pull Request is related to an existing issue, be sure + to link the issue in the Pull Request itself, in addition to the Pull Request description. +1. You will receive comments on your Pull Request. Use the Pull Request as a dialog on your changes. ### Pull Request Requirements #### Commit Messages + * Limit the first line to 72 characters or fewer. * Use the present tense ("Add validation" not "Added validation"). * Use the imperative mood ("Move database call" not "Moves database call"). -* Reference issues and other pull requests liberally after the first line. Use [GitHub Auto Linking](https://help.github.com/articles/autolinked-references-and-urls/) -to link your Pull Request to other issues. +* Reference issues and other pull requests liberally after the first line. + Use [GitHub Auto Linking](https://help.github.com/articles/autolinked-references-and-urls/) + to link your Pull Request to other issues. * Use markdown syntax as much as you want #### Testing -When making changes to the VinylDNS codebase, be sure to add necessary unit, integration, and functional tests. -For specifics on our tests, see the [Testing](DEVELOPER_GUIDE.md#testing) section of the Developer Guide. + +When making changes to the VinylDNS codebase, be sure to add necessary unit, integration, and functional tests. For +specifics on our tests, see the [Testing](https://github.com/vinyldns/vinyldns/blob/master/DEVELOPER_GUIDE.md#testing) +section of the Developer Guide. #### Documentation Edits -Documentation for the VinylDNS project lives in files such as this one in the root of the project directory, as well -as in `modules/docs/src/main/tut` for the docs you see on [vinyldns.io](https://vinyldns.io). Many changes, such as those that impact -an API endpoint, config, portal usage, etc, will also need corresponding documentation edited to prevent it from going stale. The VinylDNS [gh-pages branch README](https://github.com/vinyldns/vinyldns/tree/gh-pages#vinyldns-documentation-site) has information on how to run and edit the documentation page. + +Documentation for the VinylDNS project lives in files such as this one in the root of the project directory, as well as +in `modules/docs/src/main/mdoc` for the docs you see on [vinyldns.io](https://vinyldns.io). Many changes, such as those +that impact an API endpoint, config, portal usage, etc, will also need corresponding documentation edited to prevent it +from going stale. The +VinylDNS [gh-pages branch README](https://github.com/vinyldns/vinyldns/tree/gh-pages#vinyldns-documentation-site) has +information on how to run and edit the documentation page. #### Style Guides -* For Scala code we use [Scalastyle](https://www.scalastyle.org/). The configs are `scalastyle-config.xml` and -`scalastyle-test-config.xml` for source code and test code respectively - * We have it set to fail builds if the styling rules are not followed. For example, one of our rules is that all lines must be <= 120 characters, and a build will fail if that is violated. -* For our python code that we use for functional testing, we generally try to follow [PEP 8](https://www.python.org/dev/peps/pep-0008/) + +* For Scala code we use [Scalastyle](http://www.scalastyle.org/). The configs are `scalastyle-config.xml` and + `scalastyle-test-config.xml` for source code and test code respectively + * We have it set to fail builds if the styling rules are not followed. For example, one of our rules is that all + lines must be <= 120 characters, and a build will fail if that is violated. +* For our python code that we use for functional testing, we generally try to + follow [PEP 8](https://www.python.org/dev/peps/pep-0008/) #### License Header Checks -VinylDNS is configured with [sbt-header](https://github.com/sbt/sbt-header). All existing scala files have the appropriate -header. To add or check for headers, follow these steps: + +VinylDNS is configured with [sbt-header](https://github.com/sbt/sbt-header). All existing scala files have the +appropriate header. To add or check for headers, follow these steps: ##### API + You can check for headers in the API in `sbt` with: ``` @@ -137,6 +166,7 @@ If you add a new file, you can add the appropriate header in `sbt` with: ``` ##### Portal + You can check for headers in the Portal in `sbt` with: ``` @@ -150,36 +180,34 @@ If you add a new file, you can add the appropriate header in `sbt` with: ``` #### Contributor License Agreement + Before Comcast merges your code into the project you must sign the [Comcast Contributor License Agreement (CLA)](https://gist.github.com/ComcastOSS/a7b8933dd8e368535378cda25c92d19a). If you haven't previously signed a Comcast CLA, you'll automatically be asked to when you open a pull request. -Alternatively, we can send you a PDF that you can sign and scan back to us. Please create a new GitHub issue to request a PDF version of the CLA. +Alternatively, we can send you a PDF that you can sign and scan back to us. Please create a new GitHub issue to request +a PDF version of the CLA. ### Modifying your Pull Requests -Often times, you will need to make revisions to your Pull Requests that you submit. This is part of the standard process of code -review. There are different ways that you can make revisions, but the following process is pretty standard. -1. Sync with upstream first. `git checkout master && git fetch upstream && git rebase upstream master && git push origin master` +Often times, you will need to make revisions to your Pull Requests that you submit. This is part of the standard process +of code review. There are different ways that you can make revisions, but the following process is pretty standard. + +1. Sync with upstream + first. `git checkout master && git fetch upstream && git rebase upstream master && git push origin master` 1. Checkout your branch on your local `git checkout your-user-name/user-branch-name` -1. Sync your branch with latest `git rebase master`. Note: If you have merge conflicts, you will have to resolve them +1. Sync your branch with latest `git rebase master`. Note: If you have merge conflicts, you will have to resolve them 1. Revise your Pull Request, making changes recommended in the comments / code review 1. Stage and commit these changes on top of your existing commits -1. When all tests pass, `git push origin your-user-name/user-branch-name` to revise your commit. _Note: If you rebased or altered the commit history, you will have to force push with a `-f` flag._ GitHub automatically -recognizes the update and will re-run verification on your Pull Request! +1. When all tests pass, `git push origin your-user-name/user-branch-name` to revise your commit. _Note: If you rebased + or altered the commit history, you will have to force push with a `-f` flag._ GitHub automatically recognizes the + update and will re-run verification on your Pull Request! ### Pull Request Approval + A pull request must satisfy our [pull request requirements](#pull-request-requirements) -Afterwards, if a Pull Request is approved, a maintainer of the project will merge it. -If you are a maintainer, you can merge your Pull Request once you have the approval of at least 2 other maintainers. - -> Note: The first time you make a Pull Request, add yourself to the authors list [here](AUTHORS.md) as part of the Pull Request - -## Release Management -As an overview, we release on a regular schedule roughly once per month. - -* **current release** - For example, 0.8.0. This constitutes the current work that is in-flight -* **next release** - For example, 0.8.1. These are the issues pegged for the _next_ release to be worked on -* **maintenance release** - We will have maintenance releases once we bump MINOR. For example, we will have `0.8.x` once we move to `0.9.0-SNAPSHOT` +Afterwards, if a Pull Request is approved, a maintainer of the project will merge it. If you are a maintainer, you can +merge your Pull Request once you have the approval of at least 2 other maintainers. +> Note: The first time you make a Pull Request, add yourself to the authors list [here](https://github.com/vinyldns/vinyldns/blob/master/AUTHORS.md) as part of the Pull Request diff --git a/DEVELOPER_GUIDE.md b/DEVELOPER_GUIDE.md index 6ef1c08c5..daf7739d1 100644 --- a/DEVELOPER_GUIDE.md +++ b/DEVELOPER_GUIDE.md @@ -1,236 +1,310 @@ # Developer Guide ## Table of Contents -- [Developer Requirements](#developer-requirements) + +- [Developer Requirements (Local)](#developer-requirements-local) +- [Developer Requirements (Docker)](#developer-requirements-docker) - [Project Layout](#project-layout) + * [Core](#core) + * [API](#api) + * [Portal](#portal) + * [Documentation](#documentation) - [Running VinylDNS Locally](#running-vinyldns-locally) + * [Starting the API Server](#starting-the-api-server) + * [Starting the Portal](#starting-the-portal) - [Testing](#testing) -- [Validating VinylDNS](#validating-vinyldns) + * [Unit Tests](#unit-tests) + * [Integration Tests](#integration-tests) + + [Running both](#running-both) + * [Functional Tests](#functional-tests) + + [Running Functional Tests](#running-functional-tests) + - [API Functional Tests](#api-functional-tests) + + [Setup](#setup) + - [Functional Test Context](#functional-test-context) + - [Partitioning](#partitioning) + - [Really Important Test Context Rules!](#really-important-test-context-rules) + - [Managing Test Zone Files](#managing-test-zone-files) -## Developer Requirements +## Developer Requirements (Local) + +- Java 8+ - Scala 2.12 -- sbt 1+ -- Java 8 (at least u162) -- Python 2.7 -- virtualenv -- Docker -- curl -- npm -- grunt +- sbt 1.4+ -Make sure that you have the requirements installed before proceeding. + +- curl +- docker +- docker-compose +- GNU Make 3.82+ +- grunt +- npm +- Python 3.5+ + +## Developer Requirements (Docker) + +Since almost everything can be run with Docker and GNU Make, if you don't want to setup a local development environment, +then you simply need: + +- `Docker` v19.03+ _(earlier versions may work fine)_ +- `Docker Compose` v2.0+ _(earlier versions may work fine)_ +- `GNU Make` v3.82+ +- `Bash` 3.2+ + - Basic utilities: `awk`, `sed`, `curl`, `grep`, etc may be needed for scripts ## Project Layout -[SYSTEM_DESIGN.md](SYSTEM_DESIGN.md) provides a high-level architectural overview of VinylDNS and interoperability of its components. -The main codebase is a multi-module Scala project with multiple sub-modules. To start working with the project, -from the root directory run `sbt`. Most of the code can be found in the `modules` directory. -The following modules are present: +[SYSTEM_DESIGN.md](SYSTEM_DESIGN.md) provides a high-level architectural overview of VinylDNS and interoperability of +its components. -* `root` - this is the parent project, if you run tasks here, it will run against all sub-modules -* [`core`](#core): core modules that are used by both the API and portal, such as cryptography implementations. -* [`api`](#api): the API is the main engine for all of VinylDNS. This is the most active area of the codebase, as everything else typically just funnels through -the API. -* [`portal`](#portal): The portal is a user interface wrapper around the API. Most of the business rules, logic, and processing can be found in the API. The -_only_ features in the portal not found in the API are creation of users and user authentication. -* [`docs`](#documentation): documentation for VinylDNS. +The main codebase is a multi-module Scala project with multiple sub-modules. To start working with the project, from the +root directory run `sbt`. Most of the code can be found in the `modules` directory. The following modules are present: + +- `root` - this is the parent project, if you run tasks here, it will run against all sub-modules +- [`core`](#core): core modules that are used by both the API and portal, such as cryptography implementations. +- [`api`](#api): the API is the main engine for all of VinylDNS. This is the most active area of the codebase, as + everything else typically just funnels through the API. +- [`portal`](#portal): The portal is a user interface wrapper around the API. Most of the business rules, logic, and + processing can be found in the API. The + _only_ features in the portal not found in the API are creation of users and user authentication. +- [`docs`](#documentation): documentation for VinylDNS. ### Core + Code that is used across multiple modules in the VinylDNS ecosystem live in `core`. #### Code Layout -* `src/main` - the main source code -* `src/test` - unit tests + +- `src/main` - the main source code +- `src/test` - unit tests ### API -The API is the RESTful API for interacting with VinylDNS. The following technologies are used: -* [Akka HTTP](https://doc.akka.io/docs/akka-http/current/) - Used primarily for REST and HTTP calls. -* [FS2](https://functional-streams-for-scala.github.io/fs2/) - Used for backend change processing off of message queues. -FS2 has back-pressure built in, and gives us tools like throttling and concurrency. -* [Cats Effect](https://typelevel.org/cats-effect/) - We are currently migrating away from `Future` as our primary type -and towards cats effect IO. Hopefully, one day, all the things will be using IO. -* [Cats](https://typelevel.org/cats) - Used for functional programming. -* [PureConfig](https://pureconfig.github.io/) - For loading configuration values. We are currently migrating to -use PureConfig everywhere. Not all the places use it yet. +The API is the RESTful API for interacting with VinylDNS. The following technologies are used: + +- [Akka HTTP](https://doc.akka.io/docs/akka-http/current/) - Used primarily for REST and HTTP calls. +- [FS2](https://functional-streams-for-scala.github.io/fs2/) - Used for backend change processing off of message queues. + FS2 has back-pressure built in, and gives us tools like throttling and concurrency. +- [Cats Effect](https://typelevel.org/cats-effect/) - A replacement of `Future` with the `IO` monad +- [Cats](https://typelevel.org/cats) - Used for functional programming. +- [PureConfig](https://pureconfig.github.io/) - For loading configuration values. The API has the following dependencies: -* MySQL - the SQL database that houses zone data -* DynamoDB - where all of the other data is stored -* SQS - for managing concurrent updates and enabling high-availability -* Bind9 - for testing integration with a real DNS system + +- MySQL - the SQL database that houses the data +- SQS - for managing concurrent updates and enabling high-availability +- Bind9 - for testing integration with a real DNS system #### Code Layout + The API code can be found in `modules/api`. -* `functional_test` - contains the python black box / regression tests -* `src/it` - integration tests -* `src/main` - the main source code -* `src/test` - unit tests -* `src/universal` - items that are packaged in the Docker image for the VinylDNS API +- `src/it` - integration tests +- `src/main` - the main source code +- `src/test` - unit tests +- `src/universal` - items that are packaged in the Docker image for the VinylDNS API The package structure for the source code follows: -* `vinyldns.api.domain` - contains the core front-end logic. This includes things like the application services, -repository interfaces, domain model, validations, and business rules. -* `vinyldns.api.engine` - the back-end processing engine. This is where we process commands including record changes, -zone changes, and zone syncs. -* `vinyldns.api.protobuf` - marshalling and unmarshalling to and from protobuf to types in our system -* `vinyldns.api.repository` - repository implementations live here -* `vinyldns.api.route` - HTTP endpoints +- `vinyldns.api.domain` - contains the core front-end logic. This includes things like the application services, + repository interfaces, domain model, validations, and business rules. +- `vinyldns.api.engine` - the back-end processing engine. This is where we process commands including record changes, + zone changes, and zone syncs. +- `vinyldns.api.protobuf` - marshalling and unmarshalling to and from protobuf to types in our system +- `vinyldns.api.repository` - repository implementations live here +- `vinyldns.api.route` - HTTP endpoints ### Portal -The project is built using: -* [Play Framework](https://www.playframework.com/documentation/2.6.x/Home) -* [AngularJS](https://angularjs.org/) -The portal is _mostly_ a shim around the API. Most actions in the user interface are translated into API calls. +The project is built using: + +- [Play Framework](https://www.playframework.com/documentation/2.6.x/Home) +- [AngularJS](https://angularjs.org/) + +The portal is _mostly_ a shim around the API. Most actions in the user interface are translated into API calls. The features that the Portal provides that are not in the API include: -* Authentication against LDAP -* Creation of users - when a user logs in for the first time, VinylDNS automatically creates a user and new credentials for them in the -database with their LDAP information. + +- Authentication against LDAP +- Creation of users - when a user logs in for the first time, VinylDNS automatically creates a user and new credentials + for them in the database with their LDAP information. #### Code Layout + The portal code can be found in `modules/portal`. -* `app` - source code for portal back-end - * `models` - data structures that are used by the portal - * `views` - HTML templates for each web page - * `controllers` - logic for updating data -* `conf` - configurations and endpoint routes -* `public` - source code for portal front-end - * `css` - stylesheets - * `images` - images, including icons, used in the portal - * `js` - scripts - * `mocks` - mock JSON used in Grunt tests - * `templates` - modal templates -* `test` - unit tests for portal back-end +- `app` - source code for portal back-end + - `models` - data structures that are used by the portal + - `views` - HTML templates for each web page + - `controllers` - logic for updating data +- `conf` - configurations and endpoint routes +- `public` - source code for portal front-end + - `css` - stylesheets + - `images` - images, including icons, used in the portal + - `js` - scripts + - `mocks` - mock JSON used in Grunt tests + - `templates` - modal templates +- `test` - unit tests for portal back-end ### Documentation -Code used to build the microsite content for the API, operator and portal guides at https://www.vinyldns.io/. Some settings for the microsite -are also configured in `build.sbt` of the project root. + +Code used to build the microsite content for the API, operator and portal guides at https://www.vinyldns.io/. Some +settings for the microsite are also configured in `build.sbt` of the project root. #### Code Layout -* `src/main/resources` - Microsite resources and configurations -* `src/main/tut` - Content for microsite web pages + +- `src/main/resources` - Microsite resources and configurations +- `src/main/mdoc` - Content for microsite web pages ## Running VinylDNS Locally -VinylDNS can be started in the background by running the [quickstart instructions](README.md#quickstart) located in the README. However, VinylDNS -can also be run in the foreground. + +VinylDNS can be started in the background by running the [quickstart instructions](README.md#quickstart) located in the +README. However, VinylDNS can also be run in the foreground. ### Starting the API Server -To start the API for integration, functional, or portal testing. Start up sbt by running `sbt` from the root directory. -* `dockerComposeUp` to spin up the dependencies on your machine from the root project. -* `project api` to change the sbt project to the API -* `reStart` to start up the API server -* Wait until you see the message `VINYLDNS SERVER STARTED SUCCESSFULLY` before working with the server -* To stop the VinylDNS server, run `reStop` from the api project -* To stop the dependent Docker containers, change to the root project `project root`, then run `dockerComposeStop` from the API project -See the [API Configuration Guide](https://www.vinyldns.io/operator/config-api) for information regarding API configuration. +Before starting the API service, you can start the dependencies for local development: + +```shell +quickstart/quickstart-vinyldns.sh --deps-only +``` + +This will start a container running in the background with necessary prerequisites. + +Once the prerequisites are running, you can start up sbt by running `sbt` from the root directory. + +- `project api` to change the sbt project to the API +- `reStart` to start up the API server + - To enable interactive debugging, you can run `set Revolver.enableDebugging(port = 5020, suspend = true)` before running `reStart` +- Wait until you see the message `VINYLDNS SERVER STARTED SUCCESSFULLY` before working with the server +- To stop the VinylDNS server, run `reStop` from the api project +- To stop the dependent Docker containers: `utils/clean-vinyldns-containers.sh` + +See the [API Configuration Guide](https://www.vinyldns.io/operator/config-api) for information regarding API +configuration. ### Starting the Portal -To run the portal locally, you _first_ have to start up the VinylDNS API Server (see instructions above). Once -that is done, in the same `sbt` session or a different one, go to `project portal` and then execute `;preparePortal; run`. -See the [Portal Configuration Guide](https://www.vinyldns.io/operator/config-portal) for information regarding portal configuration. - -### Loading test data -Normally the portal can be used for all VinylDNS requests. Test users are locked down to only have access to test zones, -which the portal connection modal has not been updated to incorporate. To connect to a zone with testuser, you will need to use an alternative -client and set `isTest=true` on the zone being connected to. - -Use the vinyldns-js client (Note, you need Node installed): +To run the portal locally, you _first_ have to start up the VinylDNS API Server. This can be done by following the +instructions for [Staring the API Server](#starting-the-api-server) or by using the QuickStart: +```shell +quickstart/quickstart-vinyldns.sh --api-only ``` -git clone https://github.com/vinyldns/vinyldns-js.git -cd vinyldns-js -npm install -export VINYLDNS_API_SERVER=http://localhost:9000 -export VINYLDNS_ACCESS_KEY_ID=testUserAccessKey -export VINYLDNS_SECRET_ACCESS_KEY=testUserSecretKey -npm run repl -> var groupId; -> vinyl.createGroup({"name": "test-group", "email":"test@test.com", members: [{id: "testuser"}], admins: [{id: "testuser"}]}).then(res => {groupId = res.id}).catch(err => {console.log(err)}); -> vinyl.createZone ({name: "ok.", isTest: true, adminGroupId: groupId, email: "test@test.com"}).then(res => { console.log(res) }).catch(err => { console.log(err) }) -You should now be able to see the zone in the portal at localhost:9001 when logged in as username=testuser password=testpassword -``` +Once that is done, in the same `sbt` session or a different one, go to `project portal` and then +execute `;preparePortal; run`. + +See the [Portal Configuration Guide](https://www.vinyldns.io/operator/config-portal) for information regarding portal +configuration. ## Testing + ### Unit Tests -1. First, start up your Scala build tool: `sbt`. Running *clean* immediately after starting is recommended. -1. (Optionally) Go to the project you want to work on, for example `project api` for the API; `project portal` for the portal. -1. Run _all_ unit tests by just running `test`. -1. Run an individual unit test by running `testOnly *MySpec`. -1. If you are working on a unit test and production code at the same time, use `~` (eg. `~testOnly *MySpec`) to automatically background compile for you! + +1. First, start up your Scala build tool: `build/sbt.sh` (or `sbt` if running outside of Docker). +2. (Optionally) Go to the project you want to work on, for example `project api` for the API; `project portal` for the + portal. +3. Run _all_ unit tests by just running `test`. +4. Run a single unit test suite by running `testOnly *MySpec`. +5. Run a single unit by filtering the test name using the `-z` argument `testOnly *MySpec -- -z "some text from test"`. + - [More information on commandline arguments](https://www.scalatest.org/user_guide/using_the_runner) +6. If you are working on a unit test and production code at the same time, use `~` (e.g., `~testOnly *MySpec`) to + automatically background compile for you! ### Integration Tests -Integration tests are used to test integration with _real_ dependent services. We use Docker to spin up those -backend services for integration test development. -1. Type `dockerComposeUp` to start up dependent background services +Integration tests are used to test integration with dependent services. We use Docker to spin up those backend services +for integration test development. + +1. Type `quickstart/quickstart-vinyldns.sh --reset --deps-only` to start up dependent background services +1. Run sbt (`build/sbt.sh` or `sbt` locally) 1. Go to the target module in sbt, example: `project api` 1. Run all integration tests by typing `it:test`. 1. Run an individual integration test by typing `it:testOnly *MyIntegrationSpec` 1. You can background compile as well if working on a single spec by using `~it:testOnly *MyIntegrationSpec` -1. You must stop (`dockerComposeStop`) and start (`dockerComposeUp`) the dependent services from the root project (`project root`) before you rerun the tests. -1. For the mysql module, you may need to wait up to 30 seconds after starting the services before running the tests for setup to complete. +1. You must restart the dependent services (`quickstart/quickstart-vinyldns.sh --reset --deps-only`) before you rerun + the tests. +1. For the mysql module, you may need to wait up to 30 seconds after starting the services before running the tests for + setup to complete. #### Running both -You can run all unit and integration tests for the api and portal by running `sbt verify` +You can run all unit and integration tests for the api and portal by running `build/verify.sh` ### Functional Tests -When adding new features, you will often need to write new functional tests that black box / regression test the -API. We have over 350 (and growing) automated regression tests. The API functional tests are written in Python -and live under `modules/api/functional_test`. -#### Running functional tests -To run functional tests, make sure that you have started the API server (directions above). -Then in another terminal session: +When adding new features, you will often need to write new functional tests that black box / regression test the API. -1. `cd modules/api/functional_test` -1. `./run.py live_tests -v` +- The API functional tests are written in Python and live under `modules/api/src/test/functional`. +- The Portal functional tests are written in JavaScript and live under `modules/portal/test`. -You can run a specific test by name by running `./run.py live_tests -v -k ` +#### Running Functional Tests -You run specific tests for a portion of the project, say recordsets, by running `./run.py live_tests/recordsets -v` +To run functional tests you can simply execute the following commands: -#### Our Setup -We use [pytest](https://docs.pytest.org/en/latest/) for python tests. It is helpful that you browse the documentation -so that you are familiar with pytest and how our functional tests operate. +```shell +build/func-test-api.sh +build/func-test-portal.sh +``` -We also use [PyHamcrest](https://pyhamcrest.readthedocs.io/en/release-1.8/) for matchers in order to write easy -to read tests. Please browse that documentation as well so that you are familiar with the different matchers -for PyHamcrest. There aren't a lot, so it should be quick. +These command will run the API functional tests and portal functional tests respectively. +##### API Functional Tests -In the `modules/api/functional_test` directory are a few important files for you to be familiar with: +To run functional tests you can simply execute `build/func-test-api.sh`, but if you'd like finer-grained control, you +can work with the `Makefile` in `test/api/functional`: -* vinyl_client.py - this provides the interface to the VinylDNS API. It handles signing the request for you, as well -as building and executing the requests, and giving you back valid responses. For all new API endpoints, there should -be a corresponding function in the vinyl_client -* utils.py - provides general use functions that can be used anywhere in your tests. Feel free to contribute new -functions here when you see repetition in the code +```shell +# Build and then run the function test container +make -C test/api/functional build run +``` -Functional tests run on every build, and are designed to work _in every environment_. That means locally, in Docker, -and in production environments. +During iterative test development, you can use `make run-local` which will bind-mount the current functional tests in +the container, allowing for easier test development. -In the `modules/api/functional_test/live_tests` directory, we have directories / modules for different areas of the application. +Additionally, you can pass `--interactive` to `make run` or `make run-local` to drop to a shell inside the container. +From there you can run tests with the `/functional_test/run.sh` command. This allows for finer-grained control over the +test execution process as well as easier inspection of logs. -* membership - for managing groups and users -* recordsets - for managing record sets -* zones - for managing zones -* internal - for internal endpoints (not intended for public consumption) -* batch - for managing batch updates +You can run a specific test by name by running `make run -- -k `. Any arguments after +`make run --` will be passed to the test runner [`test/api/functional/run.sh`](test/api/functional/run.sh). + +Finally, you can execute `make run-deps-bg` to all of the dependencies for the functional test, but not run the tests. +This is useful if, for example, you want to use an interactive debugger on your local machine, but host all of the +VinylDNS API dependencies in Docker. + +#### Setup + +We use [pytest](https://docs.pytest.org/en/latest/) for python tests. It is helpful that you browse the documentation so +that you are familiar with pytest and how our functional tests operate. + +We also use [PyHamcrest](https://pyhamcrest.readthedocs.io/en/release-1.8/) for matchers in order to write easy to read +tests. Please browse that documentation as well so that you are familiar with the different matchers for PyHamcrest. +There aren't a lot, so it should be quick. + +In the `modules/api/src/test/functional` directory are a few important files for you to be familiar with: + +- `vinyl_python.py` - this provides the interface to the VinylDNS API. It handles signing the request for you, as well + as building and executing the requests, and giving you back valid responses. For all new API endpoints, there should + be a corresponding function in the vinyl_client +- `utils.py` - provides general use functions that can be used anywhere in your tests. Feel free to contribute new + functions here when you see repetition in the code + +In the `modules/api/src/test/functional/tests` directory, we have directories / modules for different areas of the +application. + +- `batch` - for managing batch updates +- `internal` - for internal endpoints (not intended for public consumption) +- `membership` - for managing groups and users +- `recordsets` - for managing record sets +- `zones` - for managing zones ##### Functional Test Context -Our func tests use pytest contexts. There is a main test context that lives in `shared_zone_test_context.py` -that creates and tears down a shared test context used by many functional tests. The -beauty of pytest is that it will ensure that the test context is stood up exactly once, then all individual tests -that use the context are called using that same context. + +Our functional tests use `pytest` contexts. There is a main test context that lives in `shared_zone_test_context.py` +that creates and tears down a shared test context used by many functional tests. The beauty of pytest is that it will +ensure that the test context is stood up exactly once, then all individual tests that use the context are called using +that same context. The shared test context sets up several things that can be reused: @@ -243,30 +317,33 @@ The shared test context sets up several things that can be reused: 1. A classless IPv4 reverse zone 1. A parent zone that has child zones - used for testing NS record management and zone delegations +##### Partitioning + +Each of the test zones are configured in a `partition`. By default, there are four partitions. These partitions are +effectively copies of the zones so that parallel tests can run without interfering with one another. + +For instance, there are four zones for the `ok` zone: `ok1`, `ok2`, `ok3`, and `ok4`. The functional tests will handle +distributing which zone is being used by which of the parallel test runners. + +As such, you should **never** hardcode the name of the zone. Always get the zone from the `shared_zone_test_context`. +For instance, to get the `ok` zone, you would write: + +```python +zone = shared_zone_test_context.ok_zone +zone_name = shared_zone_test_context.ok_zone["name"] +zone_id = shared_zone_test_context.ok_zone["id"] +``` + ##### Really Important Test Context Rules! -1. Try to use the `shared_zone_test_context` whenever possible! This reduces the time -it takes to run functional tests (which is in minutes). -1. Limit changes to users, groups, and zones in the shared test context, as doing so could impact downstream tests +1. Try to use the `shared_zone_test_context` whenever possible! This reduces the time it takes to run functional + tests (which is in minutes). +1. Be mindful of changes to users, groups, and zones in the shared test context, as doing so could impact downstream + tests 1. If you do modify any entities in the shared zone context, roll those back when your function completes! ##### Managing Test Zone Files -When functional tests are run, we spin up several Docker containers. One of the Docker containers is a Bind9 DNS -server. If you need to add or modify the test DNS zone files, you can find them in -`docker/bind9/zones` -## Validating VinylDNS -VinylDNS comes with a build script `./build.sh` that validates VinylDNS compiles, verifies that unit tests pass, and then runs functional tests. -Note: This takes a while to run, and typically is only necessary if you want to simulate the same process that runs on the build servers. - -When functional tests run, you will see a lot of output intermingled together across the various containers. You can view only the output -of the functional tests at `target/vinyldns-functest.log`. If you want to see the Docker log output from any one container, you can view -them after the tests complete at: - -* `target/vinyldns-api.log` - the API server logs -* `target/vinyldns-bind9.log` - the Bind9 DNS server logs -* `target/vinyldns-elasticmq.log` - the ElasticMQ (SQS) server logs -* `target/vinyldns-functest.log` - the output of running the functional tests -* `target/vinyldns-mysql.log` - the MySQL server logs - -When the func tests complete, the entire Docker setup will be automatically torn down. +When functional tests are run, we spin up several Docker containers. One of the Docker containers is a Bind9 DNS server. +If you need to add or modify the test DNS zone files, you can find them in +`quickstart/bind9/zones` diff --git a/MAINTAINERS.md b/MAINTAINERS.md index 8ea97b296..6a0e5ebc6 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -1,170 +1,39 @@ # Maintainers ## Table of Contents + * [Docker Content Trust](#docker-content-trust) - * [Docker Hub Account](#docker-hub-account) - * [Delegating Image Signing](#delegating-image-signing) - * [Setting up Notary](#setting-up-notary) - * [Generating a Personal Delegation Key](#generating-a-personal-delegation-key) - * [Adding a Delegation Key To a Repository](#adding-a-delegation-key-to-a-repository) - * [Pushing a Signed Image with your Delegation Key](#pushing-a-signed-image-with-your-delegation-key) -* [Sonatype Credentials](#sonatype-credentials) * [Release Process](#release-process) ## Docker Content Trust -Official VinylDNS Docker images are signed when being pushed to Docker Hub. Docs for Docker Content Trust can be found -at https://docs.docker.com/engine/security/trust/content_trust/. +Official VinylDNS Docker images are signed when being pushed to Docker Hub. Docs for Docker Content Trust can be found +at . -Content trust is enabled through the `DOCKER_CONTENT_TRUST` environment variable, which must be set to 1. It is recommended that -in your `~/.bashrc`, you have `export DOCKER_CONTENT_TRUST=1` by default, and if you ever want to turn it off for a -Docker command, add the `--disable-content-trust` flag to the command, e.g. `docker pull --disable-content-trust ...`. +Content trust is enabled through the `DOCKER_CONTENT_TRUST` environment variable, which must be set to `1`. It is +recommended that in your `~/.bashrc`, you have `export DOCKER_CONTENT_TRUST=1` by default, and if you ever want to turn +it off for a Docker command, add the `--disable-content-trust` flag to the command, +e.g. `docker pull --disable-content-trust ...`. -There are multiple Docker repositories on Docker Hub under -the [vinyldns organization](https://hub.docker.com/u/vinyldns/dashboard/). Namely: +There are multiple Docker repositories on Docker Hub under +the [vinyldns organization](https://hub.docker.com/u/vinyldns/dashboard/). Namely: -* vinyldns/api: images for vinyldns core api engine +* vinyldns/api: images for vinyldns core api engine * vinyldns/portal: images for vinyldns web client -* vinyldns/bind9: images for local DNS server used for testing -* vinyldns/test-bind9: contains the setup to run functional tests -* vinyldns/test: has the actual functional tests pinned to a version of VinylDNS The offline root key and repository keys are managed by the core maintainer team. The keys managed are: * root key: also known as the offline key, used to create the separate repository signing keys * api key: used to sign tagged images in vinyldns/api * portal key: used to sign tagged images in vinyldns/portal -* bind9 key: used to sign tagged images in the vinyldns/bind9 -* test-bind9 key: used to sign tagged images in the vinyldns/test-bind9 -* test key: used to sign tagged images in the vinyldns/test - -These keys are named in a .key format, e.g. 5526ecd15bd413e08718e66c440d17a28968d5cd2922b59a17510da802ca6572.key, -do not change the names of the keys. - -Docker expects these keys to be saved in `~/.docker/trust/private`. Each key is encrypted with a passphrase, that you -must have available when pushing an image. - -### Docker Hub Account - -If you don't have one already, make an account on Docker Hub. Get added as a Collaborator to vinyldns/api, vinyldns/portal, -and vinyldns/bind9 - -### Delegating Image Signing -Someone with our keys can sign images when pushing, but instead of sharing those keys we can utilize -notary to delegate image signing permissions in a safer way. Notary will have you make a public-private key pair and -upload your public key. This way you only need your private key, and a developer's permissions can easily be revoked. - -#### Setting up Notary -If you do not already have notary: - -1. Download the latest release for your machine at https://github.com/theupdateframework/notary/releases, -for example, on a mac download the precompiled binary `notary-Darwin-amd64` -1. Rename the binary to notary, and choose a location where it will live, -e.g. `cd ~/Downloads/; mv notary-Darwin-amd64 notary; mv notary ~/Documents/notary; cd ~/Documents` -1. Make it executable, e.g. `chmod +x notary` -1. Add notary to your path, e.g. `vim ~/.bashrc`, add `export PATH="$PATH":` -1. Create a `~/.notary/config.json` with - -``` -{ - "trust_dir" : "~/.docker/trust", - "remote_server": { - "url": "https://notary.docker.io" - } - } -``` - -You can test notary with `notary -s https://notary.docker.io -d ~/.docker/trust list docker.io/vinyldns/api`, in which -you should see tagged images for the VinylDNS API - -> Note: you'll pretty much always use the `-s https://notary.docker.io -d ~/.docker/trust` args when running notary, -it will be easier for you to alias a command like `notarydefault` to `notary -s https://notary.docker.io -d ~/.docker/trust` -in your `.bashrc` - -#### Generating a Personal Delegation Key -1. `cd` to a directory where you will save your delegation keys and certs -1. Generate your private key: `openssl genrsa -out delegation.key 2048` -1. Generate your public key: `openssl req -new -sha256 -key delegation.key -out delegation.csr`, all fields are optional, -but when it gets to your email it makes sense to add that -1. Self-sign your public key (valid for one year): -`openssl x509 -req -sha256 -days 365 -in delegation.csr -signkey delegation.key -out delegation.crt` -1. Change the `delegation.crt` to some unique name, like `my-name-vinyldns-delegation.crt` -1. Give your `my-name-vinyldns-delegation.crt` to someone that has the root keys and passphrases so -they can upload your delegation key to the repository - -#### Adding a Delegation Key to a Repository -This expects you to have the root keys and passphrases for the Docker repositories - -1. List current keys: `notary -s https://notary.docker.io -d ~/.docker/trust delegation list docker.io/vinyldns/api` -1. Add team member's public key: `notary delegation add docker.io/vinyldns/api targets/releases --all-paths` -1. Push key: `notary publish docker.io/vinyldns/api` -1. Repeat above steps for `docker.io/vinyldns/portal` - -Add their key ID to the table below, it can be viewed with `notary -s https://notary.docker.io -d ~/.docker/trust delegation list docker.io/vinyldns/api`. -It will be the one that didn't show up when you ran step one of this section - -| Name | Key ID | -|----------------|------------------------------------------------------------------ -| Nima Eskandary | 66027c822d68133da859f6639983d6d3d9643226b3f7259fc6420964993b499a, cdca33de91c54f801d89240d18b5037e274461ba1c88c10451070c97e9f665b4 | -| Rebecca Star | 04285e24d3b9a8b614b34da229669de1f75c9faa471057e8b4a7d60aac0d5bf5 | -| Michael Ly |dd3a5938fc927de087ad4b59d6ac8f62b6502d05b2cc9b0623276cbac7dbf05b | - -#### Pushing a Signed Image with your Delegation Key -1. Run `notary key import --role user` -1. You will have to create a passphrase for this key that encrypts it at rest. Use a password generator to make a -strong password and save it somewhere safe, like apple keychain or some other password manager -1. From now on `docker push` will be try to sign images with the delegation key if it was configured for that Docker -repository - -## Sonatype Credentials - -The core module is pushed to oss.sonatype.org under io.vinyldns - -To be able to push to sonatype you will need the pgp key used to sign the module. We use a [blackbox](https://github.com/StackExchange/blackbox/) -repo to share this key and its corresponding passphrase. Follow these steps to set it up properly on your local - -1. Ensure you have a gpg key setup on your machine by running `gpg -K`, if you do not then run `gpg --gen-key` to create one, -note you will have to generate a strong passphrase and save it in some password manager -1. Make sure you have blackbox, on mac this would be `brew install blackbox` -1. Clone our blackbox repo, get the git url from another maintainer -1. Run `blackbox_addadmin ` -1. Commit your changes to the blackbox repo and push to master -1. Have an existing admin pull the repo and run `gpg --keyring keyrings/live/pubring.kbx --export | gpg --import`, and `blackbox_update_all_files` -1. Have the existing admin commit and push those changes to master -1. Back to you - pull the changes, and now you should be able to read those files -1. Run `blackbox_edit_start vinyldns-sonatype-key.asc.gpg` to temporarily decrypt the sonatype signing key -1. Run `gpg --import vinyldns-sonatype-key.asc` to import the sonatype signing key to your keyring -1. Run `blackbox_edit_end vinyldns-sonatype-key.asc.gpg` to re-encrypt the sonatype signing key -1. Run `blackbox_cat vinyldns-sonatype.txt.gpg` to view the passphrase for that key - you will need this passphrase handy when releasing -1. Create a file `~/.sbt/1.0/vinyldns-gpg-credentials` with the content - - ``` - realm=GnuPG Key ID - host=gpg - user=vinyldns@gmail.com - password=ignored-must-use-pinentry - ``` - -1. Add credenial configuration to global sbt setting in `~/.sbt/1.0/credential.sbt` with the content - - ``` - credentials += Credentials(Path.userHome / ".sbt" / "1.0" / "vinyldns-gpg-credentials") - ``` ## Release Process -We are using sbt-release to run our release steps and auto-bump the version in `version.sbt`. The `bin/release.sh` -script will first run functional tests, then kick off `sbt release`, which also runs unit and integration tests before -running the release +The release process is automated by GitHub Actions. -1. Follow [Docker Content Trust](#docker-content-trust) to setup a notary delegation for yourself -1. Follow [Sonatype Credentials](#sonatype-credentials) to setup the sonatype pgp signing key on your local -1. Make sure you're logged in to Docker with `docker login` -1. Run `bin/release.sh` _Note: the arg "skip-tests" will skip unit, integration and functional testing before a release_ -1. You will be asked to confirm the version which originally comes from `version.sbt`. _NOTE: if the version ends with -`SNAPSHOT`, then the docker latest tag won't be applied and the core module will only be published to the sonatype -staging repo. -1. When it comes to the sonatype stage, you will need the passphrase handy for the signing key, [Sonatype Credentials](#sonatype-credentials) -1. Assuming things were successful, make a pr since sbt release auto-bumped `version.sbt` and made a commit for you -1. Run `./build/docker-release.sh --branch [TAG CREATED FROM PREVIOUS STEP, e.g. v0.9.3] --clean --push` -1. You will need to have your keys ready so you can sign each image as it is published. +To start, create a release in GitHub with the same tag as the version found in `version.sbt`. + +The release will perform the following actions: + +1. Published Docker images to `hub.docker.com` +2. Attached artifacts created by the build to the GitHub release diff --git a/README.md b/README.md index 13103f6eb..69296c958 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,9 @@ -[![Join the chat at https://gitter.im/vinyldns](https://badges.gitter.im/vinyldns/vinyldns.svg)](https://gitter.im/vinyldns) -![Build](https://github.com/vinyldns/vinyldns/workflows/Continuous%20Integration/badge.svg) -[![CodeCov ](https://codecov.io/gh/vinyldns/vinyldns/branch/master/graph/badge.svg)](https://codecov.io/gh/vinyldns/vinyldns) -[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/2682/badge)](https://bestpractices.coreinfrastructure.org/projects/2682) -[![License](https://img.shields.io/github/license/vinyldns/vinyldns)](https://github.com/vinyldns/vinyldns/blob/master/LICENSE) -[![conduct](https://img.shields.io/badge/%E2%9D%A4-code%20of%20conduct-blue.svg)](https://github.com/vinyldns/vinyldns/blob/master/CODE_OF_CONDUCT.md) +[![VinylDNS Release](https://img.shields.io/github/v/release/vinyldns/vinyldns?label=latest%20release&logo=github)](https://github.com/vinyldns/vinyldns/releases/latest) +[![VinylDNS API Docker Image](https://img.shields.io/docker/v/vinyldns/api?color=brightgreen&label=API%20Image&logo=docker&logoColor=white&cacheSeconds=300)](https://hub.docker.com/r/vinyldns/api/tags?page=1&ordering=last_updated) +[![VinylDNS Portal Docker Image](https://img.shields.io/docker/v/vinyldns/portal?color=brightgreen&label=Portal%20Image&logo=docker&logoColor=white&cacheSeconds=300)](https://hub.docker.com/r/vinyldns/portal/tags?page=1&ordering=last_updated)

- + VinylDNS # VinylDNS -VinylDNS is a vendor agnostic front-end for enabling self-service DNS and streamlining DNS operations. -VinylDNS manages millions of DNS records supporting thousands of engineers in production at [Comcast](http://www.comcast.com). -The platform provides fine-grained access controls, auditing of all changes, a self-service user interface, -secure RESTful API, and integration with infrastructure automation tools like Ansible and Terraform. -It is designed to integrate with your existing DNS infrastructure, and provides extensibility to fit your installation. + +VinylDNS is a vendor-agnostic front-end for enabling self-service DNS and streamlining DNS operations. VinylDNS manages +millions of DNS records supporting thousands of engineers in production at [Comcast](http://www.comcast.com). The +platform provides fine-grained access controls, auditing of all changes, a self-service user interface, secure RESTful +API, and integration with infrastructure automation tools like Ansible and Terraform. It is designed to integrate with +your existing DNS infrastructure, and provides extensibility to fit your installation. VinylDNS helps secure DNS management via: -* AWS Sig4 signing of all messages to ensure that the message that was sent was not altered in transit -* Throttling of DNS updates to rate limit concurrent updates against your DNS systems -* Encrypting user secrets and TSIG keys at rest and in-transit -* Recording every change made to DNS records and zones + +- AWS Sig4 signing of all messages to ensure that the message that was sent was not altered in transit +- Throttling of DNS updates to rate limit concurrent updates against your DNS systems +- Encrypting user secrets and TSIG keys at rest and in-transit +- Recording every change made to DNS records and zones Integration is simple with first-class language support including: -* java -* ruby -* python -* go-lang -* javascript + +- Java +- Python +- Go +- JavaScript ## Table of Contents -- [Quickstart](#quickstart) -- [Code of Conduct](#code-of-conduct) -- [Developer Guide](#developer-guide) -- [Contributing](#contributing) -- [Roadmap](#roadmap) -- [Contact](#contact) -- [Maintainers and Contributors](#maintainers-and-contributors) -- [Credits](#credits) + +* [Quickstart](#quickstart) + - [Quickstart Optimization](#quickstart-optimization) +* [Things to Try in the Portal](#things-to-try-in-the-portal) + + [Verifying Your Changes](#verifying-your-changes) + + [Other things to note](#other-things-to-note) +* [Code of Conduct](#code-of-conduct) +* [Developer Guide](#developer-guide) +* [Contributing](#contributing) +* [Maintainers and Contributors](#maintainers-and-contributors) +* [Credits](#credits) ## Quickstart -Docker images for VinylDNS live on Docker Hub at . -To start up a local instance of VinylDNS on your machine with docker: -1. Ensure that you have [docker](https://docs.docker.com/install/) and [docker-compose](https://docs.docker.com/compose/install/) +Docker images for VinylDNS live on Docker Hub at . To start up a local instance of +VinylDNS on your machine with docker: + +1. Ensure that you have [docker](https://docs.docker.com/install/) + and [docker-compose](https://docs.docker.com/compose/install/) 1. Clone the repo: `git clone https://github.com/vinyldns/vinyldns.git` 1. Navigate to repo: `cd vinyldns` -1. Run `./bin/docker-up-vinyldns.sh`. This will start up the api at `localhost:9000` and the portal at `localhost:9001` -1. See [Developer Guide](DEVELOPER_GUIDE.md#loading-test-data) for how to load a test DNS zone -1. To stop the local setup, run `./bin/remove-vinyl-containers.sh`. +1. Run `./quickstart/quickstart-vinyldns.sh`. This will start up the api at `localhost:9000` and the portal + at `localhost:9001` +1. See [Things to Try in the Portal](#things-to-try-in-the-portal) for getting familiar with the Portal +1. To stop the local setup, run `./utils/clean-vinyldns-containers.sh`. -There exist several clients at that can be used to make API requests, using the endpoint `http://localhost:9000` +There exist several clients at that can be used to make API requests, using the +endpoint `http://localhost:9000`. + +#### Quickstart Optimization + +If you are experimenting with Quickstart, you may encounter a delay each time you run it. This is because the API and +Portal are rebuilt every time you launch Quickstart. If you'd like to cache the builds of the API and Portal, you may +want to first run: + +| Script | Description | +|----------------------------|------------------------------------------------------------------------------| +| `build/assemble_api.sh` | This will create the API `jar` file which will then be used by Quickstart | +| `build/assemble_portal.sh` | This will create the Portal `zip` file which will then be used by Quickstart | + +Once these scripts are run, the artifacts are placed into the `artifacts/` directory and will be reused for each +Quickstart launch. If you'd like to regenerate the artifacts, simply delete them and rerun the scripts above. + +## Things to Try in the Portal -## Things to try in the portal 1. View the portal at in a web browser -1. Login with the credentials ***professor*** and ***professor*** -1. Navigate to the `groups` tab: -1. Click on the **New Group** button and create a new group, the group id is the uuid in the url after you view the group -1. View zones you connected to in the `zones` tab: . For a quick test, create a new zone named "ok" with an email of "test@test.com" and choose a group you created from the previous step. (Note, see [Developer Guide](DEVELOPER_GUIDE.md#loading-test-data) for creating a zone) -1. You will see that some records are preloaded in the zoned already, this is because these records are preloaded in the local docker DNS server -and VinylDNS automatically syncs records with the backend DNS server upon zone connection -1. From here, you can create DNS record sets in the **Manage Records** tab, and manage zone settings and ***ACL rules*** -in the **Manage Zone** tab -1. To try creating a DNS record, click on the **Create Record Set** button under Records, `Record Type = A, Record Name = my-test-a, -TTL = 300, IP Addressess = 1.1.1.1` -1. Click on the **Refresh** button under Records, you should see your new record created +2. Login with the credentials `professor` and `professor` +3. Navigate to the `groups` tab: +4. Click on the **New Group** button and create a new group, the group id is the uuid in the url after you view the + group +5. Connect a zone by going to the `zones` tab: . + 1. Click the `-> Connect` button + 2. For `Zone Name` enter `ok` with an email of `test@test.com` + 3. For `Admin Group`, choose a group you created from the previous step + 4. Leave everything else as-is and click the `Connect` button at the bottom of the form +6. A new zone `ok` should appear in your `My Zones` tab _(you may need to refresh your browser)_ +7. You will see that some records are preloaded in the zone already, this is because these records are preloaded in the + local docker DNS server and VinylDNS automatically syncs records with the backend DNS server upon zone connection +8. From here, you can create DNS record sets in the **Manage Records** tab, and manage zone settings and ***ACL rules*** + in the **Manage Zone** tab +9. To try creating a DNS record, click on the **Create Record Set** button under + Records, `Record Type = A, Record Name = my-test-a, TTL = 300, IP Addressess = 1.1.1.1` +10. Click on the **Refresh** button under Records, you should see your new record created -## Other things to note -1. Upon connecting to a zone for the first time, a zone sync is executed to provide VinylDNS a copy of the records in the zone -1. Changes made via VinylDNS are made against the DNS backend, you do not need to sync the zone further to push those changes out -1. If changes to the zone are made outside of VinylDNS, then the zone will have to be re-synced to give VinylDNS a copy of those records -1. If you wish to modify the url used in the creation process from `http://localhost:9000`, to say `http://vinyldns.yourdomain.com:9000`, you can modify the `bin/.env` file before execution. -1. A similar `docker/.env.quickstart` can be modified to change the default ports for the Portal and API. You must also modify their config files with the new port: https://www.vinyldns.io/operator/config-portal & https://www.vinyldns.io/operator/config-api +### Verifying Your Changes + +VinylDNS will synchronize with the DNS backend. For the Quickstart this should be running on port `19001` on `localhost` +. + +To verify your changes, you can use a DNS resolution utility like `dig` + +```bash +$ dig @127.0.0.1 -p 19001 +short my-test-a.ok +1.1.1.1 +``` + +This tells `dig` to use `127.0.0.1` as the resolver on port `19001`. The `+short` just makes the output a bit less +verbose. Finally, the record we're looking up is `my-test-a.ok`. You can see the returned output of `1.1.1.1` matches +the record data we entered. + +### Other things to note + +1. Upon connecting to a zone for the first time, a zone sync is executed to provide VinylDNS a copy of the records in + the zone +1. Changes made via VinylDNS are made against the DNS backend, you do not need to sync the zone further to push those + changes out +1. If changes to the zone are made outside of VinylDNS, then the zone will have to be re-synced to give VinylDNS a copy + of those records +1. If you wish to modify the url used in the creation process from `http://localhost:9000`, to + say `http://vinyldns.yourdomain.com:9000`, you can modify the `quickstart/.env` file before execution. +1. Further configuration can be ac https://www.vinyldns.io/operator/config-portal + & https://www.vinyldns.io/operator/config-api ## Code of Conduct -This project and everyone participating in it are governed by the [VinylDNS Code Of Conduct](CODE_OF_CONDUCT.md). By -participating, you agree to this Code. Please report any violations to the code of conduct to vinyldns-core@googlegroups.com. + +This project, and everyone participating in it, are governed by the [VinylDNS Code Of Conduct](CODE_OF_CONDUCT.md). By +participating, you agree to this Code. ## Developer Guide + See [DEVELOPER_GUIDE.md](DEVELOPER_GUIDE.md) for instructions on setting up VinylDNS locally. ## Contributing + See the [Contributing Guide](CONTRIBUTING.md). -## Roadmap -See [ROADMAP.md](ROADMAP.md) for the future plans for VinylDNS. - -## Contact -- [Gitter](https://gitter.im/vinyldns) -- If you have any security concerns please contact the maintainers directly vinyldns-core@googlegroups.com - ## Maintainers and Contributors + The current maintainers (people who can merge pull requests) are: -- Paul Cleary -- Ryan Emerle -- Sriram Ramakrishnan -- Jim Wakemen + +- Ryan Emerle ([@remerle](https://github.com/remerle)) +- Sriram Ramakrishnan ([@sramakr](https://github.com/sramakr)) +- Jim Wakemen ([@jwakemen](https://github.com/jwakemen)) See [AUTHORS.md](AUTHORS.md) for the full list of contributors to VinylDNS. -See [MAINTAINERS.md](MAINTAINERS.md) for documentation specific to maintainers +See [MAINTAINERS.md](MAINTAINERS.md) for documentation specific to maintainers ## Credits -VinylDNS would not be possible without the help of many other pieces of open source software. Thank you open source world! -Initial development of DynamoDBHelper done by [Roland Kuhn](https://github.com/rkuhn) from https://github.com/akka/akka-persistence-dynamodb/blob/8d7495821faef754d97759f0d3d35ed18fc17cc7/src/main/scala/akka/persistence/dynamodb/journal/DynamoDBHelper.scala +VinylDNS would not be possible without the help of many other pieces of open source software. Thank you open source +world! -Given the Apache 2.0 license of VinylDNS, we specifically want to call out the following libraries and their corresponding licenses shown below. -- [logback-classic](https://github.com/qos-ch/logback) - [Eclipse Public License 1.0](https://www.eclipse.org/legal/epl-v10.html) -- [logback-core](https://github.com/qos-ch/logback) - [Eclipse Public License 1.0](https://www.eclipse.org/legal/epl-v10.html) -- [h2 database](http://h2database.com) - [Mozilla Public License, version 2.0](https://www.mozilla.org/MPL/2.0/) -- [pureconfig](https://github.com/pureconfig/pureconfig) - [Mozilla Public License, version 2.0](https://www.mozilla.org/MPL/2.0/) -- [pureconfig-macros](https://github.com/pureconfig/pureconfig) - [Mozilla Public License, version 2.0](https://www.mozilla.org/MPL/2.0/) -- [junit](https://junit.org/junit4/) - [Eclipse Public License 1.0](https://www.eclipse.org/legal/epl-v10.html) +Given the Apache 2.0 license of VinylDNS, we specifically want to call out the following libraries and their +corresponding licenses shown below. + +- [logback-classic](https://github.com/qos-ch/logback) + - [Eclipse Public License 1.0](https://www.eclipse.org/legal/epl-v10.html) +- [logback-core](https://github.com/qos-ch/logback) + - [Eclipse Public License 1.0](https://www.eclipse.org/legal/epl-v10.html) +- [h2 database](http://h2database.com) + - [Mozilla Public License, version 2.0](https://www.mozilla.org/MPL/2.0/) +- [pureconfig](https://github.com/pureconfig/pureconfig) + - [Mozilla Public License, version 2.0](https://www.mozilla.org/MPL/2.0/) +- [pureconfig-macros](https://github.com/pureconfig/pureconfig) + - [Mozilla Public License, version 2.0](https://www.mozilla.org/MPL/2.0/) +- [junit](https://junit.org/junit4/) + - [Eclipse Public License 1.0](https://www.eclipse.org/legal/epl-v10.html) diff --git a/ROADMAP.md b/ROADMAP.md deleted file mode 100644 index 11ae562f7..000000000 --- a/ROADMAP.md +++ /dev/null @@ -1,44 +0,0 @@ -# Roadmap -What is a Roadmap in opensource? VinylDNS would like to communicate _direction_ in terms of the features and needs -expressed by the VinylDNS community. In open source, demand is driven by the community through -Github issues. As more members join the discussion, we anticipate the "plan" to change. This document will be updated regularly to reflect the changes in prioritization. - -This document is organized by priority / planned release timeframes. Reading top-down should give you a sense of the order in which new features are planned to be delivered. - -## Completed - -- **Batch Change** - users can now submit multiple changes across zones at the same time. Included in batch change are: - - **Manual Review** - the ability to manually review certain DNS changes - - **Scheduled Changes** - the ability to schedule certain DNS changes to occur at a point in time in the future (requires manual processing right now) - - **Bulk import** - allows users to bulk load DNS changes from a CSV file -- **Global ACL Rules** - allows override on Shared / Record ownership -- **Global record search** - allows users to search for records across zones -- **Backend Providers** - allow connectivity to DNS backends _other_ than DDNS, e.g. AWS Route 53 - -## Next up? - -We are currently reviewing our roadmap. Some of the features we have discussed are below. If you have features you would like to contribute, drop us a line! - -## Zone Management -Presently VinylDNS _connects to existing zones_ for management. Zone Management will allow users -to create and manage zones in the authoritative systems themselves. The following high-level features are planned: - -1. Server Groups - allow VinylDNS admins to setup Server Groups. A Server Group consists of the primary, -secondary, and other information for a specific DNS backend. Server Groups are _vendor_ specific, plugins will be -be created for specific DNS vendors -1. Quotas - restrictions defined for a specific Server Group. These include items like `maxRecordSetsPerZone`, `concurrentUpdates`and more. -1. Zone Creation - allow the creation of a sub-domain from an existing Zone. Users choose the Server Group where -the zone will live, VinylDNS creates the delegation as well as access controls for the new zone. -1. Zone Maintenance - support the modification of zone properties, like default SOA record settings. - -## Other -There are several other features that we would like to support. We will be opening up these for RFC shortly. These include: - -1. DNS SEC - There is no first-class support for DNS SEC. That feature set is being defined. -1. Record meta data - VinylDNS will allow the "tagging" of DNS records with arbitrary key-value pairs -1. DNS Global Service Load Balancing (GSLB) - Support for common DNS GSLB use cases and integration with various GSLB vendors -1. A new user interface -1. Additional automation tools -1. VinylDNS admin user experience - pull alot of things from Config into the Portal UI for simpler administration -1. Split views / zone views - diff --git a/SYSTEM_DESIGN.md b/SYSTEM_DESIGN.md index 8654c7526..1eedc2bdd 100644 --- a/SYSTEM_DESIGN.md +++ b/SYSTEM_DESIGN.md @@ -1,56 +1,57 @@ # System Design ## Table of Contents + - [Components](#components) - [Process Flow](#process-flow) - [Integration](#integration) ## Components -The following diagram illustrates the major components in the VinylDNS ecosystem and the external systems they interact with. +The following diagram illustrates the major components in the VinylDNS ecosystem and the external systems they interact +with. -![VinylDNS Architecture Diagram](img/VinylDNS_overview.png) +![VinylDNS Architecture Diagram](img/vinyldns_overview.png) -* API - RESTful endpoints to allow interaction with VinylDNS - -* Database - stores information that the VinylDNS application needs - -* DNS servers - communicates DNS changes and resolves DNS records - -* Message queue - temporarily stores DNS requests for processing - -* LDAP Service - application protocol used to authenticate user access to the VinylDNS portal - -* Portal - graphical user interface to interact with the VinylDNS API - -* Tooling - external libraries and utilities used to interact with the VinylDNS API +| Component | Description | +|------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Portal | Web user interface to interact with the VinylDNS API | +| API | RESTful endpoints to allow interaction with VinylDNS | +| API Worker Nodes | These are API components with `processing-disabled` set to `false` (see [documentation](https://www.vinyldns.io/operator/config-api.html#processing-disabled)) | +| Message queue | Queue for DNS commands to enable flow control to the DNS backends (see [documentation](https://www.vinyldns.io/operator/pre.html#message-queues)) | +| Database | Stores information about users, membership, and DNS records | +| DNS Backend(s) | The DNS backend servers which VinylDNS will query and update. | +| LDAP Service | The optional LDAP service that VinylDNS can be configured to communicate with (see [documentation](https://www.vinyldns.io/operator/setup-ldap.html#setup-ldap)) | ## Process Flow 1. LDAP service authenticates user credentials and grants access to the portal. 1. If the user is accessing the portal for the first time, VinylDNS credentials are generated and stored. 1. User navigates portal or uses integration tooling to generate a signed API request. -1. When the API receives a request, it loads the credentials for the calling user from the database and validates the request signature to ensure that the request was not modified in transit. +1. When the API receives a request, it loads the credentials for the calling user from the database and validates the + request signature to ensure that the request was not modified in transit. 1. The request is then validated to ensure that: - - the request data is correct + - the request data is correct - the request passes all validation checks - the user has access to make the change 1. Assuming the request is in good order, the request is put on a message queue for handling. -1. One of the VinylDNS API server instances pulls the message from the queue for processing. For record changes, a DDNS message is issued to the DNS backend server. -1. When the message completes processing, it is removed from the message queue. The changes are applied to the VinylDNS database along with an audit record for the request. +1. One of the VinylDNS API server instances pulls the message from the queue for processing. For record changes, a DDNS + message is issued to the DNS backend server. +1. When the message completes processing, it is removed from the message queue. The changes are applied to the VinylDNS + database along with an audit record for the request. ## Integration -Integrating with VinylDNS is simple since each API endpoint is effectively a distinct DNS operation (eg. create record, update record, delete record, etc.). The only requirement for sending a request is generating the correct AWS SIG4 signature without content length and providing the corresponding HTTP headers so that VinylDNS can verify it. See [API Authentication](https://www.vinyldns.io/api/auth-mechanism.html) for more details. +Integrating with VinylDNS is simple since each API endpoint is effectively a distinct DNS operation (eg. create record, +update record, delete record, etc.). The only requirement for sending a request is generating the correct AWS SIG4 +signature without content length and providing the corresponding HTTP headers so that VinylDNS can verify it. +See [API Authentication](https://www.vinyldns.io/api/auth-mechanism.html) for more details. The current tooling available to perform VinylDNS API requests include: * [go-vinyldns](https://github.com/vinyldns/go-vinyldns) - Golang client package - -* [vinyldns-cli](https://github.com/vinyldns/vinyldns-cli) - command line utility written in Golang - +* [terraform-provider-vinyldns](https://github.com/vinyldns/terraform-provider-vinyldns) - A [Terraform](https://terraform.io/) provider for VinylDNS +* [vinyldns-cli](https://github.com/vinyldns/vinyldns-cli) - Command line utility written in Golang * [vinyldns-java](https://github.com/vinyldns/vinyldns-java) - Java client - +* [vinyldns-js](https://github.com/vinyldns/vinyldns-js) - JavaScript client * [vinyldns-python](https://github.com/vinyldns/vinyldns-python) - Python client library - -* [vinyldns-ruby](https://github.com/vinyldns/vinyldns-ruby) - Ruby gem diff --git a/bin/.env b/bin/.env deleted file mode 100644 index b6d3b2ffc..000000000 --- a/bin/.env +++ /dev/null @@ -1,2 +0,0 @@ -VINYLDNS_API_URL=http://localhost:9000 -VINYLDNS_PORTAL_URL=http://localhost:9001 diff --git a/bin/build.sh b/bin/build.sh deleted file mode 100755 index eec65e38c..000000000 --- a/bin/build.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env bash -DIR=$( cd $(dirname $0) ; pwd -P ) - -echo "Verifying code..." -#${DIR}/verify.sh - -#step_result=$? -step_result=0 -if [ ${step_result} != 0 ] -then - echo "Failed to verify build!!!" - exit ${step_result} -fi - -echo "Func testing the api..." -${DIR}/func-test-api.sh - -step_result=$? -if [ ${step_result} != 0 ] -then - echo "Failed API func tests!!!" - exit ${step_result} -fi - -echo "Func testing the portal..." -${DIR}/func-test-portal.sh -step_result=$? -if [ ${step_result} != 0 ] -then - echo "Failed Portal func tests!!!" - exit ${step_result} -fi - -exit 0 diff --git a/bin/docker-publish-api.sh b/bin/docker-publish-api.sh deleted file mode 100755 index 80d1282d3..000000000 --- a/bin/docker-publish-api.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash -DIR=$( cd $(dirname $0) ; pwd -P ) - -cd $DIR/../ - -echo "Publishing docker image..." -sbt clean docker:publish -publish_result=$? -cd $DIR -exit ${publish_result} diff --git a/bin/docker-up-api-server.sh b/bin/docker-up-api-server.sh deleted file mode 100755 index 8b1efb865..000000000 --- a/bin/docker-up-api-server.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/bash -###################################################################### -# Copies the contents of `docker` into target/scala-2.12 -# to start up dependent services via docker compose. Once -# dependent services are started up, the fat jar built by sbt assembly -# is loaded into a docker container. The api will be available -# by default on port 9000 -###################################################################### - - -DIR=$( cd $(dirname $0) ; pwd -P ) - -set -a # Required in order to source docker/.env -# Source customizable env files -source "$DIR"/.env -source "$DIR"/../docker/.env - -WORK_DIR="$DIR"/../target/scala-2.12 -mkdir -p "$WORK_DIR" - -echo "Copy all Docker to the target directory so we can start up properly and the Docker context is small..." -cp -af "$DIR"/../docker "$WORK_DIR"/ - -echo "Copy the vinyldns.jar to the API Docker folder so it is in context..." -if [[ ! -f "$DIR"/../modules/api/target/scala-2.12/vinyldns.jar ]]; then - echo "vinyldns.jar not found, building..." - cd "$DIR"/../ - sbt api/clean api/assembly - cd "$DIR" -fi -cp -f "$DIR"/../modules/api/target/scala-2.12/vinyldns.jar "$WORK_DIR"/docker/api - -echo "Starting API server and all dependencies in the background..." -docker-compose -f "$WORK_DIR"/docker/docker-compose-func-test.yml --project-directory "$WORK_DIR"/docker up --build -d api - -echo "Waiting for API to be ready at ${VINYLDNS_API_URL} ..." -DATA="" -RETRY=40 -while [ "$RETRY" -gt 0 ] -do - DATA=$(curl -I -s "${VINYLDNS_API_URL}/ping" -o /dev/null -w "%{http_code}") - if [ $? -eq 0 ] - then - echo "Succeeded in connecting to VinylDNS API!" - break - else - echo "Retrying" >&2 - - let RETRY-=1 - sleep 1 - - if [ "$RETRY" -eq 0 ] - then - echo "Exceeded retries waiting for VinylDNS API to be ready, failing" - exit 1 - fi - fi -done diff --git a/bin/docker-up-dns-server.sh b/bin/docker-up-dns-server.sh deleted file mode 100755 index 864a47d0a..000000000 --- a/bin/docker-up-dns-server.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -DIR=$( cd $(dirname $0) ; pwd -P ) - -echo "Starting ONLY the bind9 server. To start an api server use the api server script" -docker-compose -f $DIR/../docker/docker-compose-func-test.yml --project-directory $DIR/../docker up -d bind9 diff --git a/bin/docker-up-vinyldns.sh b/bin/docker-up-vinyldns.sh deleted file mode 100755 index cf31c427d..000000000 --- a/bin/docker-up-vinyldns.sh +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/env bash -##################################################################################################### -# Starts up the api, portal, and dependent services via -# docker-compose. The api will be available on localhost:9000 and the -# portal will be on localhost:9001 -# -# Relevant overrides can be found at ./.env and ../docker/.env -# -# Options: -# -t, --timeout seconds: overwrite ping timeout, default of 60 -# -a, --api-only: only starts up vinyldns-api and its dependencies, excludes vinyldns-portal -# -c, --clean: re-pull vinyldns/api and vinyldns/portal images from docker hub -# -v, --version tag: overwrite vinyldns/api and vinyldns/portal docker tags -##################################################################################################### - -function wait_for_url { - echo "pinging ${URL} ..." - DATA="" - RETRY="$TIMEOUT" - while [ "$RETRY" -gt 0 ] - do - DATA=$(curl -I -s "${URL}" -o /dev/null -w "%{http_code}") - if [ $? -eq 0 ] - then - echo "Succeeded in connecting to ${URL}!" - break - else - echo "Retrying" >&2 - - let RETRY-=1 - sleep 1 - - if [ "$RETRY" -eq 0 ] - then - echo "Exceeded retries waiting for ${URL} to be ready, failing" - exit 1 - fi - fi - done -} - -function usage { - printf "usage: docker-up-vinyldns.sh [OPTIONS]\n\n" - printf "starts up a local VinylDNS installation using docker compose\n\n" - printf "options:\n" - printf "\t-t, --timeout seconds: overwrite ping timeout of 60\n" - printf "\t-a, --api-only: do not start up vinyldns-portal\n" - printf "\t-c, --clean: re-pull vinyldns/api and vinyldns/portal images from docker hub\n" - printf "\t-v, --version tag: overwrite vinyldns/api and vinyldns/portal docker tags\n" -} - -function clean_images { - if (( $CLEAN == 1 )); then - echo "cleaning docker images..." - docker rmi vinyldns/api:$VINYLDNS_VERSION - docker rmi vinyldns/portal:$VINYLDNS_VERSION - fi -} - -function wait_for_api { - echo "Waiting for api..." - URL="$VINYLDNS_API_URL" - wait_for_url -} - -function wait_for_portal { - # check if portal was skipped - if [ "$SERVICE" != "api" ]; then - echo "Waiting for portal..." - URL="$VINYLDNS_PORTAL_URL" - wait_for_url - fi -} - -# initial var setup -DIR=$( cd $(dirname $0) ; pwd -P ) -TIMEOUT=60 -DOCKER_COMPOSE_CONFIG="${DIR}/../docker/docker-compose-quick-start.yml" -# empty service starts up all docker services in compose file -SERVICE="" -# when CLEAN is set to 1, existing docker images are deleted so they are re-pulled -CLEAN=0 -# default to latest for docker versions -export VINYLDNS_VERSION=latest - -# source env before parsing args so vars can be overwritten -set -a # Required in order to source docker/.env -# Source customizable env files -source "$DIR"/.env -source "$DIR"/../docker/.env - -# parse args -while [ "$1" != "" ]; do - case "$1" in - -t | --timeout ) TIMEOUT="$2"; shift;; - -a | --api-only ) SERVICE="api";; - -c | --clean ) CLEAN=1;; - -v | --version ) export VINYLDNS_VERSION=$2; shift;; - * ) usage; exit;; - esac - shift -done - -clean_images - -echo "timeout is set to ${TIMEOUT}" -echo "vinyldns version is set to '${VINYLDNS_VERSION}'" - -echo "Starting vinyldns and all dependencies in the background..." -docker-compose -f "$DOCKER_COMPOSE_CONFIG" up -d ${SERVICE} - -wait_for_api -wait_for_portal diff --git a/bin/func-test-api-testbind9.sh b/bin/func-test-api-testbind9.sh deleted file mode 100755 index 1ad4d7466..000000000 --- a/bin/func-test-api-testbind9.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/bash -###################################################################### -# Copies the contents of `docker` into target/scala-2.12 -# to start up dependent services via docker compose. Once -# dependent services are started up, the fat jar built by sbt assembly -# is loaded into a docker container. Finally, the func tests run inside -# another docker container -# At the end, we grab all the logs and place them in the target -# directory -###################################################################### - -DIR=$( cd $(dirname $0) ; pwd -P ) -WORK_DIR=$DIR/../target/scala-2.12 -mkdir -p $WORK_DIR - -echo "Cleaning up unused networks..." -docker network prune -f - -echo "Copy all docker to the target directory so we can start up properly and the docker context is small..." -cp -af $DIR/../docker $WORK_DIR/ - -echo "Copy over the functional tests as well as those that are run in a container..." -mkdir -p $WORK_DIR/functest -rsync -av --exclude='.virtualenv' $DIR/../modules/api/functional_test $WORK_DIR/docker/functest - -echo "Copy the vinyldns.jar to the api docker folder so it is in context..." -if [[ ! -f $DIR/../modules/api/target/scala-2.12/vinyldns.jar ]]; then - echo "vinyldns jar not found, building..." - cd $DIR/../ - sbt api/clean api/assembly - cd $DIR -fi -cp -f $DIR/../modules/api/target/scala-2.12/vinyldns.jar $WORK_DIR/docker/api - -echo "Starting docker environment and running func tests..." - -# If PAR_CPU is unset; default to auto -if [ -z "${PAR_CPU}" ]; then - export PAR_CPU=auto -fi - -docker-compose -f $WORK_DIR/docker/docker-compose-func-test-testbind9.yml --project-directory $WORK_DIR/docker --log-level ERROR up --build --exit-code-from functest -test_result=$? - -echo "Grabbing the logs..." - -docker logs vinyldns-api > $DIR/../target/vinyldns-api.log 2>/dev/null -docker logs vinyldns-bind9 > $DIR/../target/vinyldns-bind9.log 2>/dev/null -docker logs vinyldns-mysql > $DIR/../target/vinyldns-mysql.log 2>/dev/null -docker logs vinyldns-elasticmq > $DIR/../target/vinyldns-elasticmq.log 2>/dev/null -docker logs vinyldns-functest > $DIR/../target/vinyldns-functest.log 2>/dev/null - -echo "Cleaning up docker containers..." -$DIR/./remove-vinyl-containers.sh - -echo "Func tests returned result: ${test_result}" -exit ${test_result} diff --git a/bin/func-test-api-travis.sh b/bin/func-test-api-travis.sh deleted file mode 100755 index f8794c90d..000000000 --- a/bin/func-test-api-travis.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/bash -###################################################################### -# Copies the contents of `docker` into target/scala-2.12 -# to start up dependent services via docker compose. Once -# dependent services are started up, the fat jar built by sbt assembly -# is loaded into a docker container. Finally, the func tests run inside -# another docker container -# At the end, we grab all the logs and place them in the target -# directory -###################################################################### - -DIR=$( cd $(dirname $0) ; pwd -P ) -WORK_DIR=$DIR/../target/scala-2.12 -mkdir -p $WORK_DIR - -echo "Cleaning up unused networks..." -docker network prune -f - -echo "Copy all docker to the target directory so we can start up properly and the docker context is small..." -cp -af $DIR/../docker $WORK_DIR/ - -echo "Copy over the functional tests as well as those that are run in a container..." -mkdir -p $WORK_DIR/functest -rsync -av --exclude='.virtualenv' $DIR/../modules/api/functional_test $WORK_DIR/docker/functest - -echo "Copy the vinyldns.jar to the api docker folder so it is in context..." -if [[ ! -f $DIR/../modules/api/target/scala-2.12/vinyldns.jar ]]; then - echo "vinyldns jar not found, building..." - cd $DIR/../ - sbt build-api - cd $DIR -fi -cp -f $DIR/../modules/api/target/scala-2.12/vinyldns.jar $WORK_DIR/docker/api - -echo "Starting docker environment and running func tests..." - -if [ -z "${PAR_CPU}" ]; then - export PAR_CPU=2 -fi - -docker-compose -f $WORK_DIR/docker/docker-compose-func-test.yml --project-directory $WORK_DIR/docker up --build --exit-code-from functest -test_result=$? - -echo "Grabbing the logs..." -docker logs vinyldns-functest -docker logs vinyldns-api > $DIR/../target/vinyldns-api.log 2>/dev/null -docker logs vinyldns-bind9 > $DIR/../target/vinyldns-bind9.log 2>/dev/null -docker logs vinyldns-mysql > $DIR/../target/vinyldns-mysql.log 2>/dev/null -docker logs vinyldns-elasticmq > $DIR/../target/vinyldns-elasticmq.log 2>/dev/null -docker logs vinyldns-dynamodb > $DIR/../target/vinyldns-dynamodb.log 2>/dev/null -docker logs vinyldns-functest > $DIR/../target/vinyldns-functest.log 2>/dev/null - -echo "Cleaning up docker containers..." -$DIR/./remove-vinyl-containers.sh - -echo "Func tests returned result: ${test_result}" -exit ${test_result} diff --git a/bin/func-test-api.sh b/bin/func-test-api.sh deleted file mode 100755 index 473618148..000000000 --- a/bin/func-test-api.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/bash -###################################################################### -# Copies the contents of `docker` into target/scala-2.12 -# to start up dependent services via docker compose. Once -# dependent services are started up, the fat jar built by sbt assembly -# is loaded into a docker container. Finally, the func tests run inside -# another docker container -# At the end, we grab all the logs and place them in the target -# directory -###################################################################### - -DIR=$( cd $(dirname $0) ; pwd -P ) -WORK_DIR=$DIR/../target/scala-2.12 -mkdir -p $WORK_DIR - -echo "Cleaning up unused networks..." -docker network prune -f - -echo "Copy all docker to the target directory so we can start up properly and the docker context is small..." -cp -af $DIR/../docker $WORK_DIR/ - -echo "Copy over the functional tests as well as those that are run in a container..." -mkdir -p $WORK_DIR/functest -rsync -av --exclude='.virtualenv' $DIR/../modules/api/functional_test $WORK_DIR/docker/functest - -echo "Copy the vinyldns.jar to the api docker folder so it is in context..." -if [[ ! -f $DIR/../modules/api/target/scala-2.12/vinyldns.jar ]]; then - echo "vinyldns jar not found, building..." - cd $DIR/../ - sbt api/clean api/assembly - cd $DIR -fi -cp -f $DIR/../modules/api/target/scala-2.12/vinyldns.jar $WORK_DIR/docker/api - -echo "Starting docker environment and running func tests..." - -# If PAR_CPU is unset; default to auto -if [ -z "${PAR_CPU}" ]; then - export PAR_CPU=auto -fi - -docker-compose -f $WORK_DIR/docker/docker-compose-func-test.yml --project-directory $WORK_DIR/docker --log-level ERROR up --build --exit-code-from functest -test_result=$? - -echo "Grabbing the logs..." - -docker logs vinyldns-api > $DIR/../target/vinyldns-api.log 2>/dev/null -docker logs vinyldns-bind9 > $DIR/../target/vinyldns-bind9.log 2>/dev/null -docker logs vinyldns-mysql > $DIR/../target/vinyldns-mysql.log 2>/dev/null -docker logs vinyldns-elasticmq > $DIR/../target/vinyldns-elasticmq.log 2>/dev/null -docker logs vinyldns-functest > $DIR/../target/vinyldns-functest.log 2>/dev/null - -echo "Cleaning up docker containers..." -$DIR/./remove-vinyl-containers.sh - -echo "Func tests returned result: ${test_result}" -exit ${test_result} diff --git a/bin/func-test-portal.sh b/bin/func-test-portal.sh deleted file mode 100755 index 816828a2f..000000000 --- a/bin/func-test-portal.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/bash -###################################################################### -# Runs e2e tests against the portal -###################################################################### - -DIR=$( cd $(dirname $0) ; pwd -P ) -WORK_DIR=$DIR/../modules/portal - -function check_for() { - which $1 >/dev/null 2>&1 - EXIT_CODE=$? - if [ ${EXIT_CODE} != 0 ] - then - echo "$1 is not installed" - exit ${EXIT_CODE} - fi -} - -cd $WORK_DIR -check_for python -check_for npm - -# if the program exits before this has been captured then there must have been an error -EXIT_CODE=1 - -# javascript code generate -npm install -grunt default - -TEST_SUITES=('grunt unit') - -for TEST in "${TEST_SUITES[@]}" -do - echo "##### Running test: [$TEST]" - $TEST - EXIT_CODE=$? - echo "##### Test [$TEST] ended with status [$EXIT_CODE]" - if [ ${EXIT_CODE} != 0 ] - then - cd - - exit ${EXIT_CODE} - fi -done - -cd - -exit 0 diff --git a/bin/generate-aes-256-hex-key.sh b/bin/generate-aes-256-hex-key.sh deleted file mode 100755 index ea8f4a74b..000000000 --- a/bin/generate-aes-256-hex-key.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -# Generate 256-bit AES key. -# -# Usage: -# $ ./generate-aes-256-hex-key.sh [passphrase] -# * passphrase: Optional passphrase used to generate secret key. A pseudo-random passphrase will be used if -# one is not provided. - -if [[ ! -z "$1" ]] -then - echo "Using user-provided passphrase." -fi - -PASSPHRASE=${1:-$(openssl rand 32)} - -KEY=$(openssl enc -aes-256-cbc -k "$PASSPHRASE" -P -md sha1 | awk -F'=' 'NR == 2 {print $2}') -echo "Your 256-bit AES hex key: $KEY" diff --git a/bin/release.sh b/bin/release.sh deleted file mode 100755 index 7fb5ba096..000000000 --- a/bin/release.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env bash - -printf "\nnote: follow the guides in MAINTAINERS.md to setup notary delegation (Docker) and get sonatype key (Maven) \n" - -DIR=$( cd $(dirname $0) ; pwd -P ) - -# gpg sbt plugin fails if this is not set -export GPG_TTY=$(tty) - -## -# running tests -## -if [ "$1" != "skip-tests" ]; then - # Checking for uncommitted changes - printf "\nchecking for uncommitted changes... \n" - if ! (cd "$DIR" && git add . && git diff-index --quiet HEAD --) - then - printf "\nerror: attempting to release with uncommitted changes\n" - exit 1 - fi - # If we are not in the main repository then fail fast - REMOTE_REPO=$(git config --get remote.origin.url) - echo "REMOTE REPO IS $REMOTE_REPO" - if [[ "$REMOTE_REPO" != *-vinyldns/vinyldns.git ]]; then - printf "\nCannot run a release from this repository as it is not the main repository: $REMOTE_REPO \n" - exit 1 - fi - - # If we are not on the master branch,then fail fast - BRANCH=$(git rev-parse --abbrev-ref HEAD) - if [[ "$BRANCH" != "master" ]]; then - printf "\nCannot run a release from this branch: $BRANCH is not master \n" - exit 1; - fi - - printf "\nrunning api func tests... \n" - "$DIR"/remove-vinyl-containers.sh - if ! "$DIR"/func-test-api.sh - then - printf "\nerror: bin/func-test-api.sh failed \n" - exit 1 - fi - "$DIR"/remove-vinyl-containers.sh - - printf "\nrunning portal func tests... \n" - if ! "$DIR"/func-test-portal.sh - then - printf "\nerror: bin/func-test-portal.sh failed \n" - exit 1 - fi - - printf "\nrunning verify... \n" - if ! "$DIR"/verify.sh - then - printf "\nerror: bin/verify.sh failed \n" - exit 1 - fi -fi - -## -# run release -## -cd "$DIR"/../ && sbt release && cd $DIR - -printf "\nrelease finished \n" diff --git a/bin/remove-vinyl-containers.sh b/bin/remove-vinyl-containers.sh deleted file mode 100755 index 5f5780564..000000000 --- a/bin/remove-vinyl-containers.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash -# -# The local vinyldns setup used for testing relies on the -# following docker images: -# mysql:5.7 -# s12v/elasticmq:0.13.8 -# vinyldns/bind9 -# vinyldns/api -# vinyldns/portal -# rroemhild/test-openldap -# localstack/localstack -# -# This script with kill and remove containers associated -# with these names and/or tags -# -# Note: this will not remove the actual images from your -# machine, just the running containers - -IDS=$(docker ps -a | grep -e 'mysql:5.7' -e 's12v/elasticmq:0.13.8' -e 'vinyldns' -e 'flaviovs/mock-smtp' -e 'localstack/localstack' -e 'rroemhild/test-openldap' | awk '{print $1}') - -echo "killing..." -echo $(echo "$IDS" | xargs -I {} docker kill {}) -echo - -echo "removing..." -echo $(echo "$IDS" | xargs -I {} docker rm -v {}) -echo - -echo "pruning network..." -docker network prune -f diff --git a/bin/update-support-user.sh b/bin/update-support-user.sh deleted file mode 100755 index ad8e841b3..000000000 --- a/bin/update-support-user.sh +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/env bash - -usage () { - echo -e "Description: Updates a user in VinylDNS to a support user, or removes the user as a support user.\n" - echo -e "Usage: update-support-user.sh [OPTIONS] \n" - echo -e "Required Parameters:" - echo -e "username\tThe VinylDNS user for which to change the support flag" - echo -e "enableSupport\t'true' to set the user as a support user; 'false' to remove support privileges\n" - echo -e "OPTIONS:" - echo -e "Must define as an environment variables the following (or pass them in on the command line)\n" - echo -e "DB_USER (user name for accessing the VinylDNS database)" - echo -e "DB_PASS (user password for accessing the VinylDNS database)" - echo -e "DB_HOST (host name for the mysql server of the VinylDNS database)" - echo -e "DB_NAME (name of the VinylDNS database, defaults to vinyldns)" - echo -e "DB_PORT (port of the VinylDNS database, defaults to 19002)\n" - echo -e " -u|--user \tDatabase user name for accessing the VinylDNS database" - echo -e " -p|--password\tDatabase user password for accessing the VinylDNS database" - echo -e " -h|--host\tDatabase host name for the mysql server" - echo -e " -n|--name\tName of the VinylDNS database, defaults to vinyldns" - echo -e " -c|--port\tPort of the VinylDNS database, defaults to 19002" -} - -DIR=$( cd "$(dirname "$0")" || exit ; pwd -P ) -VINYL_ROOT=$DIR/.. -WORK_DIR=${VINYL_ROOT}/docker - -DB_USER=$DB_USER -DB_PASS=$DB_PASS -DB_HOST=$DB_HOST -DB_NAME=${DB_NAME:-vinyldns} -DB_PORT=${DB_PORT:-19002} - -while [ "$1" != "" ]; do - case "$1" in - -u | --user ) DB_USER="$2"; shift;; - -p | --password ) DB_PASS="$2"; shift;; - -h | --host ) DB_HOST="$2"; shift;; - -n | --name ) DB_NAME="$2"; shift;; - -c | --port ) DB_PORT="$2"; shift;; - * ) break;; - esac - shift -done - -VINYL_USER="$1" -MAKE_SUPPORT="$2" - -ERROR= -if [[ -z "$DB_USER" ]] -then - echo "No DB_USER environment variable found" - ERROR="1" -fi - -if [[ -z "$DB_PASS" ]] -then - echo "No DB_PASS environment variable found" - ERROR="1" -fi - -if [[ -z "$DB_HOST" ]] -then - echo "No DB_HOST environment variable found" - ERROR="1" -fi - -if [[ -z "$DB_NAME" ]] -then - echo "No DB_NAME environment variable found" - ERROR="1" -fi - - -if [[ -z "$VINYL_USER" ]] -then - echo "Parameter 'username' not specified" - ERROR="1" -fi - -if [[ -z "$MAKE_SUPPORT" ]] -then - echo "Parameter 'enableSupport' not specified" - ERROR="1" -fi - -if [[ -n "$ERROR" ]] -then - usage - exit 1 -fi - -# Copy the proto definition to the Docker context and build -cp "${VINYL_ROOT}/modules/core/src/main/protobuf/VinylDNSProto.proto" "${WORK_DIR}/admin" -docker build -t vinyldns/admin "${WORK_DIR}/admin" -rm "${WORK_DIR}/admin/VinylDNSProto.proto" - -docker run -it --rm \ - -e "DB_USER=$DB_USER" \ - -e "DB_PASS=$DB_PASS" \ - -e "DB_HOST=$DB_HOST" \ - -e "DB_NAME=$DB_NAME" \ - -e "DB_PORT=$DB_PORT" \ - vinyldns/admin:latest /app/update-support-user.py "$VINYL_USER" "$MAKE_SUPPORT" diff --git a/bin/verify.sh b/bin/verify.sh deleted file mode 100755 index fa4628faa..000000000 --- a/bin/verify.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -echo 'Running tests...' - -echo 'Stopping any docker containers...' -./bin/remove-vinyl-containers.sh - -echo 'Starting up docker for integration testing and running unit and integration tests on all modules...' -sbt ";validate;verify" -verify_result=$? - -echo 'Stopping any docker containers...' -./bin/remove-vinyl-containers.sh - -if [ ${verify_result} -eq 0 ] -then - echo 'Verify successful!' - exit 0 -else - echo 'Verify failed!' - exit 1 -fi diff --git a/build.sbt b/build.sbt index 05365a08c..270d9bb0b 100644 --- a/build.sbt +++ b/build.sbt @@ -1,18 +1,14 @@ -import Resolvers._ -import Dependencies._ import CompilerOptions._ -import com.typesafe.sbt.packager.docker._ -import scoverage.ScoverageKeys.{coverageFailOnMinimum, coverageMinimum} -import org.scalafmt.sbt.ScalafmtPlugin._ +import Dependencies._ import microsites._ -import ReleaseTransformations._ -import sbtrelease.Version +import org.scalafmt.sbt.ScalafmtPlugin._ +import scoverage.ScoverageKeys.{coverageFailOnMinimum, coverageMinimum} +import scala.language.postfixOps +import scala.sys.env import scala.util.Try -resolvers ++= additionalResolvers - -lazy val IntegrationTest = config("it") extend Test +lazy val IntegrationTest = config("it").extend(Test) // settings that should be inherited by all projects lazy val sharedSettings = Seq( @@ -21,23 +17,24 @@ lazy val sharedSettings = Seq( organizationName := "Comcast Cable Communications Management, LLC", startYear := Some(2018), licenses += ("Apache-2.0", new URL("https://www.apache.org/licenses/LICENSE-2.0.txt")), + maintainer := "VinylDNS Maintainers", scalacOptions ++= scalacOptionsByV(scalaVersion.value), - scalacOptions in Test -= "-Ywarn-dead-code", - scalacOptions in (Compile, doc) += "-no-link-warnings", + scalacOptions in(Compile, doc) += "-no-link-warnings", // Use wart remover to eliminate code badness - wartremoverErrors ++= Seq( - Wart.EitherProjectionPartial, - Wart.IsInstanceOf, - Wart.JavaConversions, - Wart.Return, - Wart.LeakingSealed, - Wart.ExplicitImplicitTypes - ), - + wartremoverErrors := ( + if (getPropertyFlagOrDefault("build.lintOnCompile", true)) + Seq( + Wart.EitherProjectionPartial, + Wart.IsInstanceOf, + Wart.JavaConversions, + Wart.Return, + Wart.LeakingSealed, + Wart.ExplicitImplicitTypes + ) + else Seq.empty + ), // scala format - scalafmtOnCompile := getPropertyFlagOrDefault("build.scalafmtOnCompile", true), - scalafmtOnCompile in IntegrationTest := getPropertyFlagOrDefault("build.scalafmtOnCompile", true), - + scalafmtOnCompile := getPropertyFlagOrDefault("build.scalafmtOnCompile", false), // coverage options coverageMinimum := 85, coverageFailOnMinimum := true, @@ -67,121 +64,26 @@ lazy val apiSettings = Seq( ) lazy val apiAssemblySettings = Seq( - assemblyJarName in assembly := "vinyldns.jar", + assemblyOutputPath in assembly := file("artifacts/vinyldns-api.jar"), test in assembly := {}, mainClass in assembly := Some("vinyldns.api.Boot"), mainClass in reStart := Some("vinyldns.api.Boot"), - // there are some odd things from dnsjava including update.java and dig.java that we don't use assemblyMergeStrategy in assembly := { - case "update.class"| "dig.class" => MergeStrategy.discard - case PathList("scala", "tools", "nsc", "doc", "html", "resource", "lib", "index.js") => MergeStrategy.discard - case PathList("scala", "tools", "nsc", "doc", "html", "resource", "lib", "template.js") => MergeStrategy.discard + case PathList("scala", "tools", "nsc", "doc", "html", "resource", "lib", "index.js") => + MergeStrategy.discard + case PathList("scala", "tools", "nsc", "doc", "html", "resource", "lib", "template.js") => + MergeStrategy.discard case x => val oldStrategy = (assemblyMergeStrategy in assembly).value oldStrategy(x) } ) -lazy val apiDockerSettings = Seq( - dockerBaseImage := "adoptopenjdk/openjdk11:jdk-11.0.7_10-alpine", - dockerUsername := Some("vinyldns"), - packageName in Docker := "api", - dockerExposedPorts := Seq(9000), - dockerEntrypoint := Seq("/opt/docker/bin/api"), - dockerExposedVolumes := Seq("/opt/docker/lib_extra"), // mount extra libs to the classpath - dockerExposedVolumes := Seq("/opt/docker/conf"), // mount extra config to the classpath - - // add extra libs to class path via mount - scriptClasspath in bashScriptDefines ~= (cp => cp :+ "${app_home}/../lib_extra/*"), - - // adds config file to mount - bashScriptExtraDefines += """addJava "-Dconfig.file=${app_home}/../conf/application.conf"""", - bashScriptExtraDefines += """addJava "-Dlogback.configurationFile=${app_home}/../conf/logback.xml"""", // adds logback - - // this is the default version, can be overridden - bashScriptExtraDefines += s"""addJava "-Dvinyldns.base-version=${(version in ThisBuild).value}"""", - bashScriptExtraDefines += "(cd ${app_home} && ./wait-for-dependencies.sh && cd -)", - credentials in Docker := Seq(Credentials(Path.userHome / ".ivy2" / ".dockerCredentials")), - dockerCommands ++= Seq( - Cmd("USER", "root"), // switch to root so we can install netcat - ExecCmd("RUN", "apk", "add", "--update", "--no-cache", "netcat-openbsd", "bash"), - Cmd("USER", "1001:0") // switch back to the daemon user - ), -) - -lazy val portalDockerSettings = Seq( - dockerBaseImage := "adoptopenjdk/openjdk11:jdk-11.0.7_10-alpine", - dockerUsername := Some("vinyldns"), - packageName in Docker := "portal", - dockerExposedPorts := Seq(9001), - dockerExposedVolumes := Seq("/opt/docker/lib_extra"), // mount extra libs to the classpath - dockerExposedVolumes := Seq("/opt/docker/conf"), // mount extra config to the classpath - - // add extra libs to class path via mount - scriptClasspath in bashScriptDefines ~= (cp => cp :+ "${app_home}/../lib_extra/*"), - - // adds config file to mount - bashScriptExtraDefines += """addJava "-Dconfig.file=${app_home}/../conf/application.conf"""", - bashScriptExtraDefines += """addJava "-Dlogback.configurationFile=${app_home}/../conf/logback.xml"""", - - // this is the default version, can be overridden - bashScriptExtraDefines += s"""addJava "-Dvinyldns.base-version=${(version in ThisBuild).value}"""", - - // needed to avoid access issue in play for the RUNNING_PID - // https://github.com/lightbend/sbt-reactive-app/issues/177 - bashScriptExtraDefines += s"""addJava "-Dplay.server.pidfile.path=/dev/null"""", - - // wait for mysql - bashScriptExtraDefines += "(cd ${app_home}/../ && ls && ./wait-for-dependencies.sh && cd -)", - dockerCommands ++= Seq( - Cmd("USER", "root"), // switch to root so we can install netcat - ExecCmd("RUN", "apk", "add", "--update", "--no-cache", "netcat-openbsd", "bash"), - Cmd("USER", "1001:0") // switch back to the user that runs the process - ), - - credentials in Docker := Seq(Credentials(Path.userHome / ".ivy2" / ".dockerCredentials")) -) - -lazy val noPublishSettings = Seq( - publish := {}, - publishLocal := {}, - publishArtifact := false -) - -lazy val apiPublishSettings = Seq( - publishArtifact := false, - publishLocal := (publishLocal in Docker).value, - publish := (publish in Docker).value -) - -lazy val portalPublishSettings = Seq( - publishArtifact := false, - publishLocal := (publishLocal in Docker).value, - publish := (publish in Docker).value, - // for sbt-native-packager (docker) to exclude local.conf - mappings in Universal ~= ( _.filterNot { - case (file, _) => file.getName.equals("local.conf") - }), - // for local.conf to be excluded in jars - mappings in (Compile, packageBin) ~= ( _.filterNot { - case (file, _) => file.getName.equals("local.conf") - }) -) - -lazy val pbSettings = Seq( - PB.targets in Compile := Seq( - PB.gens.java("2.6.1") -> (sourceManaged in Compile).value - ), - PB.protocVersion := "-v261" -) - lazy val allApiSettings = Revolver.settings ++ Defaults.itSettings ++ apiSettings ++ sharedSettings ++ apiAssemblySettings ++ - testSettings ++ - apiPublishSettings ++ - apiDockerSettings + testSettings lazy val api = (project in file("modules/api")) .enablePlugins(JavaAppPackaging, AutomateHeaderPlugin) @@ -196,35 +98,32 @@ lazy val api = (project in file("modules/api")) r53 % "compile->compile;it->it" ) -val killDocker = TaskKey[Unit]("killDocker", "Kills all vinyldns docker containers") -lazy val root = (project in file(".")).enablePlugins(DockerComposePlugin, AutomateHeaderPlugin) +lazy val root = (project in file(".")) + .enablePlugins(AutomateHeaderPlugin) .configs(IntegrationTest) .settings(headerSettings(IntegrationTest)) .settings(sharedSettings) .settings( - inConfig(IntegrationTest)(scalafmtConfigSettings), - killDocker := { - import scala.sys.process._ - "./bin/remove-vinyl-containers.sh" ! - }, + inConfig(IntegrationTest)(scalafmtConfigSettings) ) .aggregate(core, api, portal, mysql, sqs, r53) lazy val coreBuildSettings = Seq( name := "core", - // do not use unused params as NoOpCrypto ignores its constructor, we should provide a way // to write a crypto plugin so that we fall back to a noarg constructor - scalacOptions ++= scalacOptionsByV(scalaVersion.value).filterNot(_ == "-Ywarn-unused:params") -) ++ pbSettings + scalacOptions ++= scalacOptionsByV(scalaVersion.value).filterNot(_ == "-Ywarn-unused:params"), + PB.targets in Compile := Seq(PB.gens.java("2.6.1") -> (sourceManaged in Compile).value), + PB.protocVersion := "-v261" +) -import xerial.sbt.Sonatype._ lazy val corePublishSettings = Seq( publishMavenStyle := true, publishArtifact in Test := false, - pomIncludeRepository := { _ => false }, + pomIncludeRepository := { _ => + false + }, autoAPIMappings := true, - publish in Docker := {}, mainClass := None, homepage := Some(url("https://vinyldns.io")), scmInfo := Some( @@ -232,18 +131,11 @@ lazy val corePublishSettings = Seq( url("https://github.com/vinyldns/vinyldns"), "scm:git@github.com:vinyldns/vinyldns.git" ) - ), - developers := List( - Developer(id="pauljamescleary", name="Paul James Cleary", email="pauljamescleary@gmail.com", url=url("https://github.com/pauljamescleary")), - Developer(id="rebstar6", name="Rebecca Star", email="rebstar6@gmail.com", url=url("https://github.com/rebstar6")), - Developer(id="nimaeskandary", name="Nima Eskandary", email="nimaesk1@gmail.com", url=url("https://github.com/nimaeskandary")), - Developer(id="mitruly", name="Michael Ly", email="michaeltrulyng@gmail.com", url=url("https://github.com/mitruly")), - Developer(id="britneywright", name="Britney Wright", email="blw06g@gmail.com", url=url("https://github.com/britneywright")), - ), - sonatypeProfileName := "io.vinyldns" + ) ) -lazy val core = (project in file("modules/core")).enablePlugins(AutomateHeaderPlugin) +lazy val core = (project in file("modules/core")) + .enablePlugins(AutomateHeaderPlugin) .settings(sharedSettings) .settings(coreBuildSettings) .settings(corePublishSettings) @@ -265,7 +157,8 @@ lazy val mysql = (project in file("modules/mysql")) .settings(libraryDependencies ++= mysqlDependencies ++ commonTestDependencies.map(_ % "test, it")) .settings( organization := "io.vinyldns" - ).dependsOn(core % "compile->compile;test->test") + ) + .dependsOn(core % "compile->compile;test->test") .settings(name := "mysql") lazy val sqs = (project in file("modules/sqs")) @@ -279,8 +172,9 @@ lazy val sqs = (project in file("modules/sqs")) .settings(Defaults.itSettings) .settings(libraryDependencies ++= sqsDependencies ++ commonTestDependencies.map(_ % "test, it")) .settings( - organization := "io.vinyldns", - ).dependsOn(core % "compile->compile;test->test") + organization := "io.vinyldns" + ) + .dependsOn(core % "compile->compile;test->test") .settings(name := "sqs") lazy val r53 = (project in file("modules/r53")) @@ -295,55 +189,58 @@ lazy val r53 = (project in file("modules/r53")) .settings(libraryDependencies ++= r53Dependencies ++ commonTestDependencies.map(_ % "test, it")) .settings( organization := "io.vinyldns", - coverageMinimum := 65, - ).dependsOn(core % "compile->compile;test->test") + coverageMinimum := 65 + ) + .dependsOn(core % "compile->compile;test->test") .settings(name := "r53") val preparePortal = TaskKey[Unit]("preparePortal", "Runs NPM to prepare portal for start") -val checkJsHeaders = TaskKey[Unit]("checkJsHeaders", "Runs script to check for APL 2.0 license headers") -val createJsHeaders = TaskKey[Unit]("createJsHeaders", "Runs script to prepend APL 2.0 license headers to files") +val checkJsHeaders = + TaskKey[Unit]("checkJsHeaders", "Runs script to check for APL 2.0 license headers") +val createJsHeaders = + TaskKey[Unit]("createJsHeaders", "Runs script to prepend APL 2.0 license headers to files") -lazy val portal = (project in file("modules/portal")).enablePlugins(PlayScala, AutomateHeaderPlugin) +lazy val portalSettings = Seq( + libraryDependencies ++= portalDependencies, + routesGenerator := InjectedRoutesGenerator, + coverageExcludedPackages := ";views.html.*;router.*;controllers\\.javascript.*;.*Reverse.*", + javaOptions in Test += "-Dconfig.file=conf/application-test.conf", + // ads the version when working locally with sbt run + PlayKeys.devSettings += "vinyldns.base-version" -> (version in ThisBuild).value, + // adds an extra classpath to the portal loading so we can externalize jars, make sure to create the lib_extra + // directory and lay down any dependencies that are required when deploying + scriptClasspath in bashScriptDefines ~= (cp => cp :+ "lib_extra/*"), + mainClass in reStart := None, + // we need to filter out unused for the portal as the play framework needs a lot of unused things + scalacOptions ~= { opts => + opts.filterNot(p => p.contains("unused")) + }, + // runs our prepare portal process + preparePortal := { + import scala.sys.process._ + "./modules/portal/prepare-portal.sh" ! + }, + checkJsHeaders := { + import scala.sys.process._ + "./utils/add-license-headers.sh -d=modules/portal/public/lib -f=js -c" ! + }, + createJsHeaders := { + import scala.sys.process._ + "./utils/add-license-headers.sh -d=modules/portal/public/lib -f=js" ! + }, + + // Change the path of the output to artifacts/vinyldns-portal.zip + target in Universal := file("artifacts/"), + packageName in Universal := "vinyldns-portal" +) + +lazy val portal = (project in file("modules/portal")) + .enablePlugins(PlayScala, AutomateHeaderPlugin) .settings(sharedSettings) .settings(testSettings) - .settings(portalPublishSettings) - .settings(portalDockerSettings) + .settings(portalSettings) .settings( name := "portal", - libraryDependencies ++= portalDependencies, - routesGenerator := InjectedRoutesGenerator, - coverageExcludedPackages := ";views.html.*;router.*;controllers\\.javascript.*;.*Reverse.*", - javaOptions in Test += "-Dconfig.file=conf/application-test.conf", - - // ads the version when working locally with sbt run - PlayKeys.devSettings += "vinyldns.base-version" -> (version in ThisBuild).value, - - // adds an extra classpath to the portal loading so we can externalize jars, make sure to create the lib_extra - // directory and lay down any dependencies that are required when deploying - scriptClasspath in bashScriptDefines ~= (cp => cp :+ "lib_extra/*"), - mainClass in reStart := None, - - // we need to filter out unused for the portal as the play framework needs a lot of unused things - scalacOptions ~= { opts => opts.filterNot(p => p.contains("unused")) }, - - // runs our prepare portal process - preparePortal := { - import scala.sys.process._ - "./modules/portal/prepare-portal.sh" ! - }, - - checkJsHeaders := { - import scala.sys.process._ - "./bin/add-license-headers.sh -d=modules/portal/public/lib -f=js -c" ! - }, - - createJsHeaders := { - import scala.sys.process._ - "./bin/add-license-headers.sh -d=modules/portal/public/lib -f=js" ! - }, - - // change the name of the output to portal.zip - packageName in Universal := "portal" ) .dependsOn(mysql) @@ -352,13 +249,13 @@ lazy val docSettings = Seq( micrositeGithubOwner := "vinyldns", micrositeGithubRepo := "vinyldns", micrositeName := "VinylDNS", - micrositeDescription := "DNS Governance", + micrositeDescription := "DNS Automation and Governance", micrositeAuthor := "VinylDNS", - micrositeHomepage := "http://vinyldns.io", + micrositeHomepage := "https://vinyldns.io", micrositeDocumentationUrl := "/api", - micrositeGitterChannelUrl := "vinyldns/Lobby", - micrositeTwitterCreator := "@vinyldns", micrositeDocumentationLabelDescription := "API Documentation", + micrositeHighlightLanguages ++= Seq("json", "yaml", "bnf", "plaintext"), + micrositeGitterChannel := false, micrositeExtraMdFiles := Map( file("CONTRIBUTING.md") -> ExtraMdFileConfig( "contributing.md", @@ -371,12 +268,18 @@ lazy val docSettings = Seq( ghpagesNoJekyll := false, fork in mdoc := true, mdocIn := (sourceDirectory in Compile).value / "mdoc", - micrositeCssDirectory := (resourceDirectory in Compile).value / "microsite" / "css", - micrositeCompilingDocsTool := WithMdoc, - micrositeFavicons := Seq(MicrositeFavicon("favicon16x16.png", "16x16"), MicrositeFavicon("favicon32x32.png", "32x32")), - micrositeEditButton := Some(MicrositeEditButton("Improve this page", "/edit/master/modules/docs/src/main/mdoc/{{ page.path }}")), + micrositeFavicons := Seq( + MicrositeFavicon("favicon16x16.png", "16x16"), + MicrositeFavicon("favicon32x32.png", "32x32") + ), + micrositeEditButton := Some( + MicrositeEditButton( + "Improve this page", + "/edit/master/modules/docs/src/main/mdoc/{{ page.path }}" + ) + ), micrositeFooterText := None, - micrositeHighlightTheme := "atom-one-light", + micrositeHighlightTheme := "hybrid", includeFilter in makeSite := "*.html" | "*.css" | "*.png" | "*.jpg" | "*.jpeg" | "*.gif" | "*.js" | "*.swf" | "*.md" | "*.webm" | "*.ico" | "CNAME" | "*.yml" | "*.svg" | "*.json" | "*.csv" ) @@ -384,82 +287,29 @@ lazy val docs = (project in file("modules/docs")) .enablePlugins(MicrositesPlugin, MdocPlugin) .settings(docSettings) -// release stages - -lazy val setSonatypeReleaseSettings = ReleaseStep(action = oldState => { - // sonatype publish target, and sonatype release steps, are different if version is SNAPSHOT - val extracted = Project.extract(oldState) - val v = extracted.get(Keys.version) - val snap = v.endsWith("SNAPSHOT") - if (!snap) { - val publishToSettings = Some("releases" at "https://oss.sonatype.org/" + "service/local/staging/deploy/maven2") - val newState = extracted.appendWithSession(Seq(publishTo in core := publishToSettings), oldState) - - // create sonatypeReleaseCommand with releaseSonatype step - val sonatypeCommand = Command.command("sonatypeReleaseCommand") { - "project core" :: - "publish" :: - "sonatypeRelease" :: - _ - } - - newState.copy(definedCommands = newState.definedCommands :+ sonatypeCommand) - } else { - val publishToSettings = Some("snapshots" at "https://oss.sonatype.org/" + "content/repositories/snapshots") - val newState = extracted.appendWithSession(Seq(publishTo in core := publishToSettings), oldState) - - // create sonatypeReleaseCommand without releaseSonatype step - val sonatypeCommand = Command.command("sonatypeReleaseCommand") { - "project core" :: - "publish" :: - _ - } - - newState.copy(definedCommands = newState.definedCommands :+ sonatypeCommand) - } -}) - -lazy val sonatypePublishStage = Seq[ReleaseStep]( - releaseStepCommandAndRemaining(";sonatypeReleaseCommand") -) - -lazy val initReleaseStage = Seq[ReleaseStep]( - inquireVersions, // have a developer confirm versions - setReleaseVersion, - setSonatypeReleaseSettings -) - -lazy val finalReleaseStage = Seq[ReleaseStep] ( - releaseStepCommand("project root"), // use version.sbt file from root - commitReleaseVersion, - setNextVersion, - commitNextVersion -) def getPropertyFlagOrDefault(name: String, value: Boolean): Boolean = sys.props.get(name).flatMap(propValue => Try(propValue.toBoolean).toOption).getOrElse(value) -releaseProcess := - initReleaseStage ++ - sonatypePublishStage ++ - finalReleaseStage - // Let's do things in parallel! -addCommandAlias("validate", "; root/clean; " + - "all core/headerCheck core/test:headerCheck " + - "api/headerCheck api/test:headerCheck api/it:headerCheck " + - "mysql/headerCheck mysql/test:headerCheck mysql/it:headerCheck " + - "r53/headerCheck r53/test:headerCheck r53/it:headerCheck " + - "sqs/headerCheck sqs/test:headerCheck sqs/it:headerCheck " + - "portal/headerCheck portal/test:headerCheck; " + - "portal/createJsHeaders;portal/checkJsHeaders;" + - "root/compile;root/test:compile;root/it:compile" +addCommandAlias( + "validate", + "; root/clean; " + + "all core/headerCheck core/test:headerCheck " + + "api/headerCheck api/test:headerCheck api/it:headerCheck " + + "mysql/headerCheck mysql/test:headerCheck mysql/it:headerCheck " + + "r53/headerCheck r53/test:headerCheck r53/it:headerCheck " + + "sqs/headerCheck sqs/test:headerCheck sqs/it:headerCheck " + + "portal/headerCheck portal/test:headerCheck; " + + "portal/createJsHeaders;portal/checkJsHeaders;" + + "root/compile;root/test:compile;root/it:compile" ) -addCommandAlias("verify", "; project root; killDocker; dockerComposeUp; " + - "project root; coverage; " + - "all test it:test; " + - "project root; coverageReport; coverageAggregate; killDocker" +addCommandAlias( + "verify", + "; project root; coverage; " + + "all test it:test; " + + "project root; coverageReport; coverageAggregate" ) // Build the artifacts for release diff --git a/build/README.md b/build/README.md index 51ddb68f6..cb060269e 100644 --- a/build/README.md +++ b/build/README.md @@ -1,104 +1,14 @@ -## Building VinylDNS - -This folder contains scripts and everything you need to build and test VinylDNS from your own machine. - -## Pre-requisites - -- `docker` - you will need docker and docker-compose installed locally - -## Local Build and Test - -1. `./docker-release.sh --clean` -1. Open up `version.sbt` in the root to know the directory (or capture in the script output) -1. Once complete, run a test `./start.sh --version 0.9.4-SNAPSHOT` (replace 0.9.4 with the value in version.sbt). -1. Login to the portal at http://localhost:9001 to verify everything looks good -1. Run `./stop.sh` to bring everything down - -### Release Process - -1. If you are using image signing / docker notary, be sure you set the environment variable `export DOCKER_CONTENT_TRUST=1`. -Whether you sign or not is up to your organization. You need to have notary setup to be able to sign properly. -1. Be sure to login to your docker registry, typically done by `docker login` in the terminal you will release from. -1. The actual version number is pulled from the local `version.sbt` based on the branch specified (defaults to master) -1. Run `./docker-release.sh --push --clean --tag [your tag here] --branch [your branch here]` - 1. typically the `tag` is a build number that you maintain, for example a build number in Jenkins. Using this field is recommended. This value will be appended to the generated version as `-b[TAG]`; for example `0.9.4-b123` if using `123` for the tag. - 1. the `branch` defaults to `master` if not specified, you can choose any branch or tag from https://github.com/vinyldns/vinyldns -1. The version generated will be whatever the version is in the `version.sbt` on the `branch` specified (defaults to master) -1. Each of the images are built using the branch specified and the correct version -1. The func tests are run with only smoke tests against the API image to verify it is working -1. If everything passes, and the user specifies `--push`, the images are tagged and released to the docker repository (defaults to docker hub) - -### Release Script -Does a clean build off of remote master and tags it with -`./docker-release.sh --clean --push --tag 123` - -The release script is used for doing a release. It takes the following parameters: - -- `-b | --branch [BRANCH]` - what branch to pull from, can be any PR branch or a tag like `v0.9.3`, defaults to `master` -- `-c | --clean` - a flag that indicates to perform a build. If omitted, the release script will look for a -pre-built image locally -- `-p | --push` - a flag that indicates to push to the remote docker registry. The default docker registry -is `docker.io` -- `-r | --repository [REPOSITORY]` - a URL to your docker registry, defaults to `docker.io` -- `-t | --tag [TAG]` - a build qualifer for this build. For example, pass in the build number for your -continuous integration tool -- `-v | --version [VERSION]` - overrides the version calculation and forces the version passed in. Used primarily for official releases - -## Docker Images - -The build will generate several VinylDNS docker images that are used to deploy into any environment VinylDNS - -- `vinyldns/api` - this is the heart of the VinylDNS system, the backend API -- `vinyldns/portal` - the VinylDNS web UI -- `vinyldns/test-bind9` - a DNS server that is configured to support running the functional tests -- `vinyldns/test` - a container that will execute functional tests, and exit success or failure when the tests are complete - -### vinyldns/api - -The default build for vinyldns api assumes an **ALL MYSQL** installation. - -**Environment Variables** -- `VINYLDNS_VERSION` - this is the version of VinylDNS the API is running, typically you will not set this as -it is set as part of the container build - -**Volumes** -- `/opt/docker/conf/` - if you need to have your own application config file. This is **MANDATORY** for -any production environments. Typically, you will add your own `application.conf` file in here with your settings. -- `/opt/docker/lib_extra/` - if you need to have additional jar files available to your VinylDNS instance. -Rarely used, but if you want to bring your own message queue or database you can put the `jar` files there - -### vinyldns/portal - -The default build for vinyldns portal assumes an **ALL MYSQL** installation. - -**Environment Variables** -- `VINYLDNS_VERSION` - this is the version of VinylDNS the API is running, typically you will not set this as -it is set as part of the container build - -**Volumes** -- `/opt/docker/conf/` - if you need to have your own application config file. This is **MANDATORY** for -any production environments. Typically, you will add your own `application.conf` file in here with your settings. -- `/opt/docker/lib_extra/` - if you need to have additional jar files available to your VinylDNS instance. -Rarely used, but if you want to bring your own message queue or database you can put the `jar` files there - -### vinyldns/test-bind9 - -This pulls correct DNS configuration to run func tests. You can largely disregard what is in here - -### vinyldns/test - -This is used to run functional tests against a vinyldns instance. **This is very useful for verifying -your environment as part of doing an upgrade.** By default, it will run against a local docker-compose setup. - -**Environment Variables** -- `VINYLDNS_URL` - the url to the vinyldns you will test against -- `DNS_IP` - the IP address to the `vinyldns/test-bind9` container that you will use for test purposes -- `TEST_PATTERN` - the actual functional test you want to run. *Important, set to empty string to run -ALL test; otherwise, omit the environment variable when you run to just run smoke tests*. - -**Example** - -This example will run all functional tests on the given VinylDNS url and DNS IP address -`docker run -e VINYLDNS_URL="https://my.vinyldns.example.com" -e DNS_IP="1.2.3.4" -e TEST_PATTERN=""` +# Build +This folder contains scripts for building VinylDNS and it's related artifacts. +| Path | Description | +|-----------------------|-----------------------------------------------------------------------------------------| +| `assemble_api_jar.sh` | Builds the VinylDNS API jar file. You can find the resulting `jar` file in `assembly/`. | +| `deep_clean.sh` | Removes all of the build artifacts and all `target/` directories recursively. | +| `func-test-api.sh` | Runs the functional tests for the API | +| `func-test-portal.sh` | Runs the functional tests for the Portal | +| `publish_docs.sh` | Publishes the documentation site | +| `run_all_tests.sh` | Runs all of the tests: unit, integration, and functional | +| `sbt.sh` | Runs `sbt` in a Docker container with the current project bind-mounted in `/build` | +| `verify.sh` | Runs all of the unit and integration tests | diff --git a/build/assemble_api.sh b/build/assemble_api.sh new file mode 100755 index 000000000..a4f18017f --- /dev/null +++ b/build/assemble_api.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +# +# This script will build the vinyldns-api.jar file using Docker. The file will +# be placed in the configured location (currently `artifacts/` off of the root) +# +set -euo pipefail + +DIR=$( + cd "$(dirname "$0")" + pwd -P +) + +usage() { + echo "USAGE: assemble_api.sh [options]" + echo -e "\t-n, --no-cache do not use cache when building the artifact" + echo -e "\t-u, --update update the underlying docker image" +} + +NO_CACHE=0 +UPDATE_DOCKER=0 +while [[ $# -gt 0 ]]; do + case "$1" in + --no-cache | -n) + NO_CACHE=1 + shift + ;; + --update | -u) + UPDATE_DOCKER=1 + shift + ;; + *) + usage + exit 1 + ;; + esac +done + +if [[ $NO_CACHE -eq 1 ]]; then + rm -rf "${DIR}/../artifacts/vinyldns-api.jar" &> /dev/null || true + docker rmi vinyldns:api-artifact &> /dev/null || true +fi + +if [[ $UPDATE_DOCKER -eq 1 ]]; then + echo "Pulling latest version of 'vinyldns/build:base-build'" + docker pull vinyldns/build:base-build +fi + +echo "Building VinylDNS API artifact" +make -C "${DIR}/docker/api" artifact diff --git a/build/assemble_portal.sh b/build/assemble_portal.sh new file mode 100755 index 000000000..ccc6f9ac7 --- /dev/null +++ b/build/assemble_portal.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +# +# This script will build the vinyldns-portal.zip file using Docker. The file will +# be placed in the configured location (currently `artifacts/` off of the root) +# +set -euo pipefail + +DIR=$( + cd "$(dirname "$0")" + pwd -P +) + +usage() { + echo "USAGE: assemble_portal.sh [options]" + echo -e "\t-n, --no-cache do not use cache when building the artifact" + echo -e "\t-u, --update update the underlying docker image" +} + +NO_CACHE=0 +UPDATE_DOCKER=0 +while [[ $# -gt 0 ]]; do + case "$1" in + --no-clean | -n) + NO_CACHE=1 + shift + ;; + --update | -u) + UPDATE_DOCKER=1 + shift + ;; + *) + usage + exit 1 + ;; + esac +done + +if [[ $NO_CACHE -eq 1 ]]; then + rm -rf "${DIR}/../artifacts/vinyldns-portal.zip" &> /dev/null || true + docker rmi vinyldns:portal-artifact &> /dev/null || true +fi + +if [[ $UPDATE_DOCKER -eq 1 ]]; then + echo "Pulling latest version of 'vinyldns/build:base-build'" + docker pull vinyldns/build:base-build +fi + +echo "Building VinylDNS Portal artifact" +make -C "${DIR}/docker/portal" artifact diff --git a/build/deep_clean.sh b/build/deep_clean.sh new file mode 100755 index 000000000..d68681ce9 --- /dev/null +++ b/build/deep_clean.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +# +# This script will delete all target/ directories and the assembly/ directory +# +set -euo pipefail +DIR=$( + cd "$(dirname "$0")" + pwd -P +) + +echo "Performing deep clean" +find "${DIR}/.." -type d -name target -o -name assembly | while read -r p; do if [ -d "$p" ]; then + echo -n "Removing $(realpath --relative-to="$DIR" "$p").." && \ + { { rm -rf "$p" &> /dev/null && echo "done."; } || { echo -e "\e[93mERROR\e[0m: you may need to be root"; exit 1; } } +fi; done diff --git a/build/docker-release.sh b/build/docker-release.sh deleted file mode 100755 index 6d0f0a7c8..000000000 --- a/build/docker-release.sh +++ /dev/null @@ -1,138 +0,0 @@ -#!/bin/bash - -CURDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -function usage() { - printf "usage: docker-release.sh [OPTIONS]\n\n" - printf "builds and releases vinyldns artifacts\n\n" - printf "options:\n" - printf "\t-b, --branch: the branch of tag to use for the build; default is master\n" - printf "\t-c, --clean: indicates a fresh build or attempt to work with existing images; default is off\n" - printf "\t-l, --latest: indicates docker will tag image with latest; default is off\n" - printf "\t-p, --push: indicates docker will push to the repository; default is off\n" - printf "\t-r, --repository [REPOSITORY]: the docker repository where this image will be pushed; default is docker.io\n" - printf "\t-t, --tag [TAG]: sets the qualifier for the semver version; default is to not use a build tag\n" - printf "\t-v, --version [VERSION]: overrides version calculation and forces the version specified\n" -} - -# Default the build to -SNAPSHOT if not set -BUILD_TAG= -REPOSITORY="docker.io" -DOCKER_PUSH=0 -DO_BUILD=0 -BRANCH="master" -V= -TAG_LATEST=0 - -while [ "$1" != "" ]; do - case "$1" in - -b | --branch) - BRANCH="$2" - shift 2 - ;; - -c | --clean) - DO_BUILD=1 - shift - ;; - -l | --latest) - TAG_LATEST=1 - shift - ;; - -p | --push) - DOCKER_PUSH=1 - shift - ;; - -r | --repository) - REPOSITORY="$2" - shift 2 - ;; - -t | --tag) - BUILD_TAG="-b$2" - shift 2 - ;; - -v | --version) - V="$2" - shift 2 - ;; - *) - usage - exit - ;; - esac -done - -BASEDIR=$CURDIR/../ - -# Clear out our target -rm -rf $CURDIR/target && mkdir -p $CURDIR/target - -# Download just the version.sbt file from the branch specified, we use this to calculate the version -wget "https://raw.githubusercontent.com/vinyldns/vinyldns/${BRANCH}/version.sbt" -P "${CURDIR}/target" - -if [ -z "$V" ]; then - # Calculate the version by using version.sbt, this will pull out something like 0.9.4 - V=$(find $CURDIR/target -name "version.sbt" | head -n1 | xargs grep "[ \\t]*version in ThisBuild :=" | head -n1 | sed 's/.*"\(.*\)".*/\1/') - echo "VERSION ON BRANCH ${BRANCH} IS ${V}" - VINYLDNS_VERSION= - - if [[ "$V" == *-SNAPSHOT ]]; then - if [ -z "$BUILD_TAG" ]; then - # build tag is not defined, so assume -SNAPSHOT - VINYLDNS_VERSION="$V" - else - # build tag IS defined, drop the SNAPSHOT and append the build tag - VINYLDNS_VERSION="${V%?????????}${BUILD_TAG}" - fi - else - # NOT a -SNAPSHOT, append the build tag if there is one otherwise it will be empty! - VINYLDNS_VERSION="$V${BUILD_TAG}" - fi -else - VINYLDNS_VERSION="$V" -fi -export VINYLDNS_VERSION=$VINYLDNS_VERSION - -echo "VINYLDNS VERSION BEING RELEASED IS $VINYLDNS_VERSION" - -if [ $DO_BUILD -eq 1 ]; then - docker-compose -f $CURDIR/docker/docker-compose.yml build \ - --no-cache \ - --parallel \ - --build-arg VINYLDNS_VERSION="${VINYLDNS_VERSION}" \ - --build-arg BRANCH="${BRANCH}" - - if [ $? -eq 0 ]; then - # Runs smoke tests to make sure the new images are sound - docker-compose -f $CURDIR/docker/docker-compose.yml --log-level ERROR up --exit-code-from functest - fi - - if [ $? -eq 0 ]; then - docker tag vinyldns/test-bind9:$VINYLDNS_VERSION $REPOSITORY/vinyldns/test-bind9:$VINYLDNS_VERSION - docker tag vinyldns/test:$VINYLDNS_VERSION $REPOSITORY/vinyldns/test:$VINYLDNS_VERSION - docker tag vinyldns/api:$VINYLDNS_VERSION $REPOSITORY/vinyldns/api:$VINYLDNS_VERSION - docker tag vinyldns/portal:$VINYLDNS_VERSION $REPOSITORY/vinyldns/portal:$VINYLDNS_VERSION - - if [ $TAG_LATEST -eq 1 ]; then - echo "Tagging latest..." - docker tag vinyldns/test-bind9:$VINYLDNS_VERSION $REPOSITORY/vinyldns/test-bind9:latest - docker tag vinyldns/test:$VINYLDNS_VERSION $REPOSITORY/vinyldns/test:latest - docker tag vinyldns/api:$VINYLDNS_VERSION $REPOSITORY/vinyldns/api:latest - docker tag vinyldns/portal:$VINYLDNS_VERSION $REPOSITORY/vinyldns/portal:latest - fi - fi -fi - -if [ $DOCKER_PUSH -eq 1 ]; then - docker push $REPOSITORY/vinyldns/test-bind9:$VINYLDNS_VERSION - docker push $REPOSITORY/vinyldns/test:$VINYLDNS_VERSION - docker push $REPOSITORY/vinyldns/api:$VINYLDNS_VERSION - docker push $REPOSITORY/vinyldns/portal:$VINYLDNS_VERSION - - if [ $TAG_LATEST -eq 1 ]; then - echo "Pushing latest..." - docker push $REPOSITORY/vinyldns/test-bind9:latest - docker push $REPOSITORY/vinyldns/test:latest - docker push $REPOSITORY/vinyldns/api:latest - docker push $REPOSITORY/vinyldns/portal:latest - fi -fi diff --git a/build/docker/.env b/build/docker/.env new file mode 100644 index 000000000..f5bcadd7d --- /dev/null +++ b/build/docker/.env @@ -0,0 +1,19 @@ +# Portal settings +PORTAL_PORT=9001 +PLAY_HTTP_SECRET_KEY=change-this-for-prod +VINYLDNS_BACKEND_URL=http://vinyldns-api:9000 +LDAP_PROVIDER_URL=ldap://vinyldns-ldap:19004 +TEST_LOGIN=false + +# API Settings +REST_PORT=9000 +SQS_SERVICE_ENDPOINT=http://vinyldns-integration:19003 +SNS_SERVICE_ENDPOINT=http://vinyldns-integration:19003 +MYSQL_ENDPOINT=vinyldns-integration:19002 +DEFAULT_DNS_ADDRESS=vinyldns-integration:19001 + +JDBC_DRIVER=org.mariadb.jdbc.Driver +JDBC_URL=jdbc:mariadb://vinyldns-integration:19002/vinyldns?user=root&password=pass +JDBC_MIGRATION_URL=jdbc:mariadb://vinyldns-integration:19002/?user=root&password=pass +JDBC_USER=root +JDBC_PASSWORD=pass diff --git a/build/docker/README.md b/build/docker/README.md new file mode 100644 index 000000000..8e266e806 --- /dev/null +++ b/build/docker/README.md @@ -0,0 +1,41 @@ +# Docker Images + +This folder contains the tools to create Docker images for the VinylDNS API and Portal + + +## Docker Images + +- `vinyldns/api` - this is the heart of the VinylDNS system, the backend API +- `vinyldns/portal` - the VinylDNS web UI + +### `vinyldns/api` + +The default build for vinyldns api assumes an **ALL MYSQL** installation. + +#### Environment Variables + +- `VINYLDNS_VERSION` - this is the version of VinylDNS the API is running, typically you will not set this as it is set + as part of the container build + +#### Volumes + +- `/opt/vinyldns/conf/` - if you need to have your own application config file. This is **MANDATORY** for any production + environments. Typically, you will add your own `application.conf` file in here with your settings. +- `/opt/vinyldns/lib_extra/` - if you need to have additional jar files available to your VinylDNS instance. Rarely + used, but if you want to bring your own message queue or database you can put the `jar` files there + +### `vinyldns/portal` + +The default build for vinyldns portal assumes an **ALL MYSQL** installation. + +#### Environment Variables + +- `VINYLDNS_VERSION` - this is the version of VinylDNS the API is running, typically you will not set this as it is set + as part of the container build + +#### Volumes + +- `/opt/vinyldns/conf/` - if you need to have your own application config file. This is **MANDATORY** for any production + environments. Typically, you will add your own `application.conf` file in here with your settings. +- `/opt/vinyldns/lib_extra/` - if you need to have additional jar files available to your VinylDNS instance. Rarely + used, but if you want to bring your own message queue or database you can put the `jar` files there diff --git a/build/docker/api/.jvmopts b/build/docker/api/.jvmopts deleted file mode 100644 index 7c372e489..000000000 --- a/build/docker/api/.jvmopts +++ /dev/null @@ -1,6 +0,0 @@ --Xms512M --Xmx1024M --Xss2M --XX:MaxMetaspaceSize=512M --XX:ReservedCodeCacheSize=512M --Djava.net.preferIPv4Stack=true diff --git a/build/docker/api/Dockerfile b/build/docker/api/Dockerfile index 8c6c1ec81..379b7f36b 100644 --- a/build/docker/api/Dockerfile +++ b/build/docker/api/Dockerfile @@ -1,31 +1,38 @@ -FROM hseeberger/scala-sbt:11.0.8_1.3.13_2.11.12 as builder +# Build VinylDNS API if the JAR doesn't already exist +FROM vinyldns/build:base-build as base-build +COPY . /build/ +WORKDIR /build -ARG BRANCH=master +## Run the build if we don't already have a vinyldns-api.jar +RUN mkdir -p /opt/vinyldns/conf && \ + if [ -f artifacts/vinyldns-api.jar ]; then cp artifacts/vinyldns-api.jar /opt/vinyldns/; fi && \ + if [ ! -f /opt/vinyldns/vinyldns-api.jar ]; then \ + env SBT_OPTS="-Xmx2G -Xms512M -Xss2M -XX:MaxMetaspaceSize=2G" \ + sbt -Dbuild.scalafmtOnCompile=false -Dbuild.lintOnCompile=fase ";project api;coverageOff;assembly" \ + && cp artifacts/vinyldns-api.jar /opt/vinyldns/; \ + fi + +FROM openjdk:11-slim +ARG DOCKER_FILE_PATH ARG VINYLDNS_VERSION -RUN git clone -b ${BRANCH} --single-branch --depth 1 https://github.com/vinyldns/vinyldns.git /vinyldns +RUN test -n "VINYLDNS_VERSION" || (echo "VINYLDNS_VERSION not set" && false) && \ + test -n "DOCKER_FILE_PATH" || (echo "DOCKER_FILE_PATH not set" && false) && \ + mkdir -p /opt/vinyldns/lib_extra && \ + echo "${VINYLDNS_VERSION}" > /opt/vinyldns/version -# The default jvmopts are huge, meant for running everything, use a paired down version -COPY .jvmopts /vinyldns - -RUN cd /vinyldns ; sbt "set version in ThisBuild := \"${VINYLDNS_VERSION}\"" api/stage - -FROM adoptopenjdk/openjdk11:jdk-11.0.8_10-alpine - -RUN apk add --update --no-cache netcat-openbsd bash - -COPY --from=builder /vinyldns/modules/api/target/universal/stage /opt/docker - -# This will set the vinyldns version, make sure to have this in config... version = ${?VINYLDNS_VERSION} -ARG VINYLDNS_VERSION -ENV VINYLDNS_VERSION=$VINYLDNS_VERSION - -RUN mkdir -p /opt/docker/lib_extra +COPY --from=base-build /opt/vinyldns /opt/vinyldns +COPY ${DOCKER_FILE_PATH}/application.conf /opt/vinyldns/conf +COPY ${DOCKER_FILE_PATH}/logback.xml /opt/vinyldns/conf # Mount the volume for config file and lib extras -# Note: These volume names are used in the build.sbt -VOLUME ["/opt/docker/lib_extra/", "/opt/docker/conf"] +VOLUME ["/opt/vinyldns/lib_extra/", "/opt/vinyldns/conf/"] EXPOSE 9000 -ENTRYPOINT ["/opt/docker/bin/api"] +ENV JVM_OPTS="" +ENTRYPOINT ["/bin/bash", "-c", "java ${JVM_OPTS} -Dconfig.file=/opt/vinyldns/conf/application.conf \ + -Dlogback.configurationFile=/opt/vinyldns/conf/logback.xml \ + -Dvinyldns.version=$(cat /opt/vinyldns/version) \ + -cp /opt/vinyldns/lib_extra/* \ + -jar /opt/vinyldns/vinyldns-api.jar" ] diff --git a/build/docker/api/Makefile b/build/docker/api/Makefile new file mode 100644 index 000000000..142ba4b0b --- /dev/null +++ b/build/docker/api/Makefile @@ -0,0 +1,67 @@ +SHELL=bash +IMAGE_TAG=$(shell awk -F'"' '{print $$2}' ../../../version.sbt) +IMAGE_NAME=vinyldns/api +ROOT_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) + +# Check that the required version of make is being used +REQ_MAKE_VER:=3.82 +ifneq ($(REQ_MAKE_VER),$(firstword $(sort $(MAKE_VERSION) $(REQ_MAKE_VER)))) + $(error The version of MAKE $(REQ_MAKE_VER) or higher is required; you are running $(MAKE_VERSION)) +endif + +# Extract arguments for `make run` +EXTRACT_ARGS=false +ifeq (run,$(firstword $(MAKECMDGOALS))) + EXTRACT_ARGS=true +endif +ifeq ($(EXTRACT_ARGS),true) + # use the rest as arguments for "run" + WITH_ARGS ?= $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)) +endif +ifneq ($(WITH_ARGS),) + ARG_SEPARATOR=-- +endif + +%: + @: + +.ONESHELL: + +.PHONY: all artifact build run publish build-vnext publish-vnext + +all: build run + +artifact: + @set -euo pipefail + cd ../../.. + docker build $(BUILD_ARGS) --target base-build --build-arg DOCKER_FILE_PATH="$$(realpath --relative-to="." "$(ROOT_DIR)")" --build-arg VINYLDNS_VERSION="$(IMAGE_TAG)" -t "vinyldns:api-artifact" -f "$(ROOT_DIR)/Dockerfile" . + USE_TTY="" && test -t 1 && USE_TTY="-t" + docker run -i $${USE_TTY} --rm -v "$$(pwd)/:/output" vinyldns:api-artifact /bin/bash -c "mkdir -p /output/artifacts/ && cp /build/artifacts/*.jar /output/artifacts/" + +build: + @set -euo pipefail + cd ../../.. + docker build $(BUILD_ARGS) --build-arg DOCKER_FILE_PATH="$$(realpath --relative-to="." "$(ROOT_DIR)")" --build-arg VINYLDNS_VERSION="$(IMAGE_TAG)" -t $(IMAGE_NAME):$(IMAGE_TAG) -f "$(ROOT_DIR)/Dockerfile" . + docker tag $(IMAGE_NAME):$(IMAGE_TAG) $(IMAGE_NAME):latest + +run: + @set -euo pipefail + docker network create --driver bridge vinyldns_net &> /dev/null || true + USE_TTY="" && test -t 1 && USE_TTY="-t" + docker run -i $${USE_TTY} --rm --env-file "$(ROOT_DIR)/../.env" --network vinyldns_net $(DOCKER_PARAMS) -v "$$(pwd)/:/opt/vinyldns/conf/" -p 9000:9000 $(IMAGE_NAME):$(IMAGE_TAG) $(ARG_SEPARATOR) $(WITH_ARGS) + +publish: build + @set -euo pipefail + DOCKER_CONTENT_TRUST=1 docker push $(IMAGE_NAME):$(IMAGE_TAG) + DOCKER_CONTENT_TRUST=1 docker push $(IMAGE_NAME):latest + +build-vnext: + @set -euo pipefail + cd ../../.. + docker build $(BUILD_ARGS) --build-arg DOCKER_FILE_PATH="$$(realpath --relative-to="." "$(ROOT_DIR)")" --build-arg VINYLDNS_VERSION="vnext" -t $(IMAGE_NAME):vnext -f "$(ROOT_DIR)/Dockerfile" . + docker tag $(IMAGE_NAME):vnext "$(IMAGE_NAME):vnext-$$(date -u +"%Y%m%d")" + +publish-vnext: build-vnext + @set -euo pipefail + DOCKER_CONTENT_TRUST=1 docker push $(IMAGE_NAME):vnext + DOCKER_CONTENT_TRUST=1 docker push "$(IMAGE_NAME):vnext-$$(date -u +"%Y%m%d")" diff --git a/build/docker/api/application.conf b/build/docker/api/application.conf index 09eab0cf6..73208b9c3 100644 --- a/build/docker/api/application.conf +++ b/build/docker/api/application.conf @@ -1,69 +1,194 @@ vinyldns { - version = "unknown" - version = ${?VINYLDNS_VERSION} + base-version = "0.0.0-local-dev" + version = ${vinyldns.base-version} # default to the base version if not overridden + version = ${?VINYLDNS_VERSION} # override the base version via env var + + # How often to any particular zone can be synchronized in milliseconds + sync-delay = 10000 + sync-delay = ${?SYNC_DELAY} + + # If we should start up polling for change requests, set this to false for the inactive cluster + processing-disabled = false + processing-disabled = ${?PROCESSING_DISABLED} + + # Number of records that can be in a zone + max-zone-size = 60000 + max-zone-size = ${?MAX_ZONE_SIZE} + + # Types of unowned records that users can access in shared zones + shared-approved-types = ["A", "AAAA", "CNAME", "PTR", "TXT"] + + # Batch change settings + batch-change-limit = 1000 + batch-change-limit = ${?BATCH_CHANGE_LIMIT} + manual-batch-review-enabled = true + manual-batch-review-enabled = ${?MANUAL_BATCH_REVIEW_ENABLED} + scheduled-changes-enabled = true + scheduled-changes-enabled = ${?SCHEDULED_CHANGES_ENABLED} + multi-record-batch-change-enabled = true + multi-record-batch-change-enabled = ${?MULTI_RECORD_BATCH_CHANGE_ENABLED} + + # configured backend providers + backend { + # Use "default" when dns backend legacy = true + # otherwise, use the id of one of the connections in any of your backends + default-backend-id = "default" + + # this is where we can save additional backends + backend-providers = [ + { + class-name = "vinyldns.api.backend.dns.DnsBackendProviderLoader" + settings = { + legacy = false + backends = [ + { + id = "default" + zone-connection = { + name = "vinyldns." + key-name = "vinyldns." + key-name = ${?DEFAULT_DNS_KEY_NAME} + key = "nzisn+4G2ldMn0q1CV3vsg==" + key = ${?DEFAULT_DNS_KEY_SECRET} + primary-server = "127.0.0.1:19001" + primary-server = ${?DEFAULT_DNS_ADDRESS} + } + transfer-connection = { + name = "vinyldns." + key-name = "vinyldns." + key-name = ${?DEFAULT_DNS_KEY_NAME} + key = "nzisn+4G2ldMn0q1CV3vsg==" + key = ${?DEFAULT_DNS_KEY_SECRET} + primary-server = "127.0.0.1:19001" + primary-server = ${?DEFAULT_DNS_ADDRESS} + }, + tsig-usage = "always" + }, + { + id = "func-test-backend" + zone-connection = { + name = "vinyldns." + key-name = "vinyldns." + key-name = ${?DEFAULT_DNS_KEY_NAME} + key = "nzisn+4G2ldMn0q1CV3vsg==" + key = ${?DEFAULT_DNS_KEY_SECRET} + primary-server = "127.0.0.1:19001" + primary-server = ${?DEFAULT_DNS_ADDRESS} + } + transfer-connection = { + name = "vinyldns." + key-name = "vinyldns." + key-name = ${?DEFAULT_DNS_KEY_NAME} + key = "nzisn+4G2ldMn0q1CV3vsg==" + key = ${?DEFAULT_DNS_KEY_SECRET} + primary-server = "127.0.0.1:19001" + primary-server = ${?DEFAULT_DNS_ADDRESS} + }, + tsig-usage = "always" + } + ] + } + } + ] + } + queue { - class-name = "vinyldns.mysql.queue.MySqlMessageQueueProvider" - polling-interval = 250.millis + class-name = "vinyldns.sqs.queue.SqsMessageQueueProvider" + messages-per-poll = 10 + polling-interval = 250.millis + settings { + # AWS access key and secret. + access-key = "test" + access-key = ${?AWS_ACCESS_KEY} + secret-key = "test" + secret-key = ${?AWS_SECRET_ACCESS_KEY} + + # Regional endpoint to make your requests (eg. 'us-west-2', 'us-east-1', etc.). This is the region where your queue is housed. + signing-region = "us-east-1" + signing-region = ${?SQS_REGION} + + # Endpoint to access queue + service-endpoint = "http://localhost:19003/" + service-endpoint = ${?SQS_SERVICE_ENDPOINT} + + # Queue name. Should be used in conjunction with service endpoint, rather than using a queue url which is subject to change. + queue-name = "vinyldns" + queue-name = ${?SQS_QUEUE_NAME} + } + } + + email { + class-name = "vinyldns.api.notifier.email.EmailNotifierProvider" + class-name = ${?EMAIL_CLASS_NAME} settings = { - name = "vinyldns" - driver = "org.mariadb.jdbc.Driver" - migration-url = "jdbc:mariadb://vinyldns-mysql:3306/?user=root&password=pass" - url = "jdbc:mariadb://vinyldns-mysql:3306/vinyldns?user=root&password=pass" - user = "root" - password = "pass" + from = "VinylDNS " + from = ${?EMAIL_FROM} + } + } - # see https://github.com/brettwooldridge/HikariCP - connection-timeout-millis = 1000 - idle-timeout = 10000 - max-lifetime = 30000 - maximum-pool-size = 5 - minimum-idle = 0 - - my-sql-properties = { - cachePrepStmts=true - prepStmtCacheSize=250 - prepStmtCacheSqlLimit=2048 - rewriteBatchedStatements=true - } + sns { + class-name = "vinyldns.apadi.notifier.sns.SnsNotifierProvider" + class-name = ${?SNS_CLASS_NAME} + settings { + topic-arn = "arn:aws:sns:us-east-1:000000000000:batchChanges" + topic-arn = ${?SNS_TOPIC_ARN} + access-key = "test" + access-key = ${?SNS_ACCESS_KEY} + secret-key = "test" + secret-key = ${?SNS_SECRET_KEY} + service-endpoint = "http://localhost:19003" + service-endpoint = ${?SNS_SERVICE_ENDPOINT} + signing-region = "us-east-1" + signing-region = ${?SNS_REGION} } } rest { host = "0.0.0.0" port = 9000 + port=${?API_SERVICE_PORT} } - sync-delay = 10000 + approved-name-servers = [ + "172.17.42.1.", + "ns1.parent.com." + "ns1.parent.com1." + "ns1.parent.com2." + "ns1.parent.com3." + "ns1.parent.com4." + ] + + # Note: This MUST match the Portal or strange errors will ensue, NoOpCrypto should not be used for production crypto { type = "vinyldns.core.crypto.NoOpCrypto" + type = ${?CRYPTO_TYPE} + secret = ${?CRYPTO_SECRET} } data-stores = ["mysql"] - mysql { settings { # JDBC Settings, these are all values in scalikejdbc-config, not our own # these must be overridden to use MYSQL for production use # assumes a docker or mysql instance running locally name = "vinyldns" + name = ${?DATABASE_NAME} driver = "org.mariadb.jdbc.Driver" - migration-url = "jdbc:mariadb://vinyldns-mysql:3306/?user=root&password=pass" - url = "jdbc:mariadb://vinyldns-mysql:3306/vinyldns?user=root&password=pass" + driver = ${?JDBC_DRIVER} + migration-url = "jdbc:mariadb://localhost:19002/?user=root&password=pass" + migration-url = ${?JDBC_MIGRATION_URL} + url = "jdbc:mariadb://localhost:19002/vinyldns?user=root&password=pass" + url = ${?JDBC_URL} user = "root" + user = ${?JDBC_USER} password = "pass" - # see https://github.com/brettwooldridge/HikariCP - connection-timeout-millis = 1000 - idle-timeout = 10000 - max-lifetime = 600000 - maximum-pool-size = 20 - minimum-idle = 20 - register-mbeans = true + password = ${?JDBC_PASSWORD} } - # Repositories that use this data store are listed here + + # TODO: Remove the need for these useless configuration blocks repositories { zone { } @@ -86,39 +211,7 @@ vinyldns { } } - defaultZoneConnection { - name = "vinyldns." - keyName = "vinyldns." - key = "nzisn+4G2ldMn0q1CV3vsg==" - primaryServer = "vinyldns-bind9" - } - - defaultTransferConnection { - name = "vinyldns." - keyName = "vinyldns." - key = "nzisn+4G2ldMn0q1CV3vsg==" - primaryServer = "vinyldns-bind9" - } - - backends = [ - { - id = "func-test-backend" - zone-connection { - name = "vinyldns." - key-name = "vinyldns." - key = "nzisn+4G2ldMn0q1CV3vsg==" - primary-server = "vinyldns-bind9" - } - transfer-connection { - name = "vinyldns." - key-name = "vinyldns." - key = "nzisn+4G2ldMn0q1CV3vsg==" - primary-server = "vinyldns-bind9" - } - } - ] - - batch-change-limit = 1000 + backends = [] # FQDNs / IPs that cannot be modified via VinylDNS # regex-list used for all record types except PTR @@ -136,10 +229,78 @@ vinyldns { ] } - # types of unowned records that users can access in shared zones - shared-approved-types = ["A", "AAAA", "CNAME", "PTR", "TXT"] + # FQDNs / IPs / zone names that require manual review upon submission in batch change interface + # domain-list used for all record types except PTR + # ip-list used exclusively for PTR records + manual-review-domains = { + domain-list = [ + "needs-review.*" + ] + ip-list = [ + "192.0.1.254", + "192.0.1.255", + "192.0.2.254", + "192.0.2.255", + "192.0.3.254", + "192.0.3.255", + "192.0.4.254", + "192.0.4.255", + "fd69:27cc:fe91:0:0:0:ffff:1", + "fd69:27cc:fe91:0:0:0:ffff:2", + "fd69:27cc:fe92:0:0:0:ffff:1", + "fd69:27cc:fe92:0:0:0:ffff:2", + "fd69:27cc:fe93:0:0:0:ffff:1", + "fd69:27cc:fe93:0:0:0:ffff:2", + "fd69:27cc:fe94:0:0:0:ffff:1", + "fd69:27cc:fe94:0:0:0:ffff:2" + ] + zone-name-list = [ + "zone.requires.review." + "zone.requires.review1." + "zone.requires.review2." + "zone.requires.review3." + "zone.requires.review4." + ] + } - manual-batch-review-enabled = true + # FQDNs / IPs that cannot be modified via VinylDNS + # regex-list used for all record types except PTR + # ip-list used exclusively for PTR records + high-value-domains = { + regex-list = [ + "high-value-domain.*" # for testing + ] + ip-list = [ + # using reverse zones in the vinyldns/bind9 docker image for testing + "192.0.1.252", + "192.0.1.253", + "192.0.2.252", + "192.0.2.253", + "192.0.3.252", + "192.0.3.253", + "192.0.4.252", + "192.0.4.253", + "fd69:27cc:fe91:0:0:0:0:ffff", + "fd69:27cc:fe91:0:0:0:ffff:0", + "fd69:27cc:fe92:0:0:0:0:ffff", + "fd69:27cc:fe92:0:0:0:ffff:0", + "fd69:27cc:fe93:0:0:0:0:ffff", + "fd69:27cc:fe93:0:0:0:ffff:0", + "fd69:27cc:fe94:0:0:0:0:ffff", + "fd69:27cc:fe94:0:0:0:ffff:0" + ] + } + + global-acl-rules = [ + { + group-ids: ["global-acl-group-id"], + fqdn-regex-list: [".*shared[0-9]{1}."] + }, + { + group-ids: ["another-global-acl-group"], + fqdn-regex-list: [".*ok[0-9]{1}."] + } + ] } akka { @@ -168,3 +329,7 @@ akka.http { illegal-header-warnings = on } } + +# You can provide configuration overrides via local.conf if you don't want to replace everything in +# this configuration file +include "local.conf" diff --git a/build/docker/docker-compose.yml b/build/docker/docker-compose.yml deleted file mode 100644 index 6c145ce8b..000000000 --- a/build/docker/docker-compose.yml +++ /dev/null @@ -1,77 +0,0 @@ -version: "3.0" -services: - mysql: - image: "mysql:5.7" - container_name: "vinyldns-mysql" - environment: - MYSQL_ROOT_PASSWORD: 'pass' - MYSQL_ROOT_HOST: '%' - logging: - driver: none - ports: - - "19002:3306" - - bind9: - build: - context: ./test-bind9 - args: - BRANCH: master - image: "vinyldns/test-bind9:${VINYLDNS_VERSION}" - container_name: "vinyldns-bind9" - logging: - driver: none - ports: - - "19001:53/udp" - - "19001:53" - - api: - build: - context: ./api - image: "vinyldns/api:${VINYLDNS_VERSION}" - container_name: "vinyldns-api" - environment: - MYSQL_ROOT_PASSWORD: 'pass' - MYSQL_ROOT_HOST: '%' - logging: - driver: none - ports: - - "9000:9000" - volumes: - - ./api/application.conf:/opt/docker/conf/application.conf - - ./api/logback.xml:/opt/docker/conf/logback.xml - depends_on: - - mysql - - ldap: - image: rroemhild/test-openldap - container_name: "vinyldns-ldap" - ports: - - "19008:389" - - portal: - build: - context: ./portal - image: "vinyldns/portal:${VINYLDNS_VERSION}" - container_name: "vinyldns-portal" - environment: - MYSQL_ROOT_PASSWORD: 'pass' - MYSQL_ROOT_HOST: '%' - logging: - driver: none - ports: - - "9001:9000" - volumes: - - ./portal/application.conf:/opt/docker/conf/application.conf - depends_on: - - api - - ldap - - functest: - build: - context: ./test - image: "vinyldns/test:${VINYLDNS_VERSION}" - environment: - TEST_PATTERN: "test_verify_production" - container_name: "vinyldns-functest" - depends_on: - - api diff --git a/build/docker/portal/.jvmopts b/build/docker/portal/.jvmopts deleted file mode 100644 index 7c372e489..000000000 --- a/build/docker/portal/.jvmopts +++ /dev/null @@ -1,6 +0,0 @@ --Xms512M --Xmx1024M --Xss2M --XX:MaxMetaspaceSize=512M --XX:ReservedCodeCacheSize=512M --Djava.net.preferIPv4Stack=true diff --git a/build/docker/portal/Dockerfile b/build/docker/portal/Dockerfile index 62a0ebb28..ce28f6503 100644 --- a/build/docker/portal/Dockerfile +++ b/build/docker/portal/Dockerfile @@ -1,44 +1,46 @@ -FROM hseeberger/scala-sbt:11.0.8_1.3.13_2.11.12 as builder +FROM vinyldns/build:base-build-portal as base-build +ARG VINYLDNS_VERSION +COPY . /build +WORKDIR /build -ARG BRANCH=master +RUN mkdir -p /opt/vinyldns/conf && \ + if [ -f artifacts/vinyldns-portal.zip ]; then \ + unzip artifacts/vinyldns-portal.zip -d /opt/vinyldns && \ + mv /opt/vinyldns/vinyldns-portal/{lib,share,conf} /opt/vinyldns && \ + rm -rf /opt/vinyldns/vinyldns-portal*; \ + fi && \ + if [ ! -f /opt/vinyldns/lib/vinyldns.portal*.jar ]; then \ + cp /build/node_modules.tar.xz /build/modules/portal && \ + cd /build/modules/portal && tar Jxf node_modules.tar.xz && \ + cd /build && \ + modules/portal/prepare-portal.sh && \ + sbt "set version in ThisBuild := \"${VINYLDNS_VERSION}\"; project portal; dist" && \ + unzip artifacts/vinyldns-portal.zip -d /opt/vinyldns && \ + mv /opt/vinyldns/vinyldns-portal/{lib,share,conf} /opt/vinyldns && \ + rm -rf /opt/vinyldns/vinyldns-portal*; \ + fi + +FROM openjdk:11-slim +ARG DOCKER_FILE_PATH ARG VINYLDNS_VERSION -RUN git clone -b ${BRANCH} --single-branch --depth 1 https://github.com/vinyldns/vinyldns.git /vinyldns +RUN test -n "VINYLDNS_VERSION" || (echo "VINYLDNS_VERSION not set" && false) && \ + test -n "DOCKER_FILE_PATH" || (echo "DOCKER_FILE_PATH not set" && false) && \ + mkdir -p /opt/vinyldns/lib_extra && \ + echo "${VINYLDNS_VERSION}" > /opt/vinyldns/version -# The default jvmopts are huge, meant for running everything, use a paired down version -COPY .jvmopts /vinyldns +COPY --from=base-build /opt/vinyldns /opt/vinyldns +COPY ${DOCKER_FILE_PATH}/application.conf /opt/vinyldns/conf +COPY ${DOCKER_FILE_PATH}/logback.xml /opt/vinyldns/conf -# Needed for preparePortal -RUN apt-get update \ - && apt-get install -y \ - apt-transport-https \ - curl \ - gnupg \ - && curl -sL https://deb.nodesource.com/setup_12.x | bash - \ - && apt-get install -y nodejs \ - && npm install -g grunt-cli -RUN cd /vinyldns ; sbt "set version in ThisBuild := \"${VINYLDNS_VERSION}\"" portal/preparePortal universal:packageZipTarball +VOLUME ["/opt/vinyldns/lib_extra/", "/opt/vinyldns/conf/"] -FROM adoptopenjdk/openjdk11:jdk-11.0.8_10-alpine +EXPOSE 9001 -RUN apk add --update --no-cache netcat-openbsd bash - -COPY --from=builder /vinyldns/modules/portal/target/universal/portal.tgz / - -RUN mkdir -p /opt && \ - tar -xzvf /portal.tgz && \ - mv /portal /opt/docker && \ - mkdir -p /opt/docker/lib_extra - -# This will set the vinyldns version, make sure to have this in config... version = ${?VINYLDNS_VERSION} -ARG VINYLDNS_VERSION -ENV VINYLDNS_VERSION=$VINYLDNS_VERSION - -# Mount the volume for config file and lib extras -# Note: These volume names are used in the build.sbt -VOLUME ["/opt/docker/lib_extra/", "/opt/docker/conf"] - -EXPOSE 9000 - -ENTRYPOINT ["/opt/docker/bin/portal"] +ENV JVM_OPTS="" +ENTRYPOINT ["/bin/bash","-c", "java ${JVM_OPTS} -Dvinyldns.version=$(cat /opt/vinyldns/version) \ + -Dlogback.configurationFile=/opt/vinyldns/conf/logback.xml \ + -Dconfig.file=/opt/vinyldns/conf/application.conf \ + -cp /opt/vinyldns/conf:/opt/vinyldns/lib/*:/opt/vinyldns/lib_extra/* \ + play.core.server.ProdServerStart"] diff --git a/build/docker/portal/Makefile b/build/docker/portal/Makefile new file mode 100644 index 000000000..e902737db --- /dev/null +++ b/build/docker/portal/Makefile @@ -0,0 +1,67 @@ +SHELL=bash +IMAGE_TAG=$(shell awk -F'"' '{print $$2}' ../../../version.sbt) +IMAGE_NAME=vinyldns/portal +ROOT_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) + +# Check that the required version of make is being used +REQ_MAKE_VER:=3.82 +ifneq ($(REQ_MAKE_VER),$(firstword $(sort $(MAKE_VERSION) $(REQ_MAKE_VER)))) + $(error The version of MAKE $(REQ_MAKE_VER) or higher is required; you are running $(MAKE_VERSION)) +endif + +# Extract arguments for `make run` +EXTRACT_ARGS=false +ifeq (run,$(firstword $(MAKECMDGOALS))) + EXTRACT_ARGS=true +endif +ifeq ($(EXTRACT_ARGS),true) + # use the rest as arguments for "run" + WITH_ARGS ?= $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)) +endif +ifneq ($(WITH_ARGS),) + ARG_SEPARATOR=-- +endif + +%: + @: + +.ONESHELL: + +.PHONY: all artifact build run publish build-vnext publish-vnext + +all: build run + +artifact: + @set -euo pipefail + cd ../../.. + docker build $(BUILD_ARGS) --target base-build --build-arg DOCKER_FILE_PATH="$$(realpath --relative-to="." "$(ROOT_DIR)")" --build-arg VINYLDNS_VERSION="$(IMAGE_TAG)" -t "vinyldns:portal-artifact" -f "$(ROOT_DIR)/Dockerfile" . + USE_TTY="" && test -t 1 && USE_TTY="-t" + docker run -i $${USE_TTY} --rm -v "$$(pwd)/:/output" vinyldns:portal-artifact /bin/bash -c "mkdir -p /output/artifacts/ && cp /build/artifacts/*.zip /output/artifacts/" + +build: + @set -euo pipefail + cd ../../.. + docker build $(BUILD_ARGS) --build-arg DOCKER_FILE_PATH="$$(realpath --relative-to="." "$(ROOT_DIR)")" --build-arg VINYLDNS_VERSION="$(IMAGE_TAG)" -t $(IMAGE_NAME):$(IMAGE_TAG) -f "$(ROOT_DIR)/Dockerfile" . + docker tag $(IMAGE_NAME):$(IMAGE_TAG) $(IMAGE_NAME):latest + +run: + @set -euo pipefail + docker network create --driver bridge vinyldns_net &> /dev/null || true + USE_TTY="" && test -t 1 && USE_TTY="-t" + docker run -i $${USE_TTY} --rm --network vinyldns_net --env-file "$(ROOT_DIR)/../.env" $(DOCKER_PARAMS) -v "$$(pwd)/application.conf:/opt/vinyldns/conf/application.conf" -v "$$(pwd)/logback.xml:/opt/vinyldns/conf/logback.xml" -p 9001:9001 $(IMAGE_NAME):$(IMAGE_TAG) $(ARG_SEPARATOR) $(WITH_ARGS) + +publish: build + @set -euo pipefail + DOCKER_CONTENT_TRUST=1 docker push $(IMAGE_NAME):$(IMAGE_TAG) + DOCKER_CONTENT_TRUST=1 docker push $(IMAGE_NAME):latest + +build-vnext: + @set -euo pipefail + cd ../../.. + docker build $(BUILD_ARGS) --build-arg DOCKER_FILE_PATH="$$(realpath --relative-to="." "$(ROOT_DIR)")" --build-arg VINYLDNS_VERSION="vnext" -t $(IMAGE_NAME):vnext -f "$(ROOT_DIR)/Dockerfile" . + docker tag $(IMAGE_NAME):vnext "$(IMAGE_NAME):vnext-$$(date -u +'%Y%m%d')" + +publish-vnext: build-vnext + @set -euo pipefail + DOCKER_CONTENT_TRUST=1 docker push $(IMAGE_NAME):vnext + DOCKER_CONTENT_TRUST=1 docker push "$(IMAGE_NAME):vnext-$$(date -u +'%Y%m%d')" diff --git a/build/docker/portal/application.conf b/build/docker/portal/application.conf index 823a01668..35c7809e1 100644 --- a/build/docker/portal/application.conf +++ b/build/docker/portal/application.conf @@ -11,73 +11,52 @@ LDAP { # This will be the name of the LDAP field that carries the user's login id (what they enter in the username in login form) userNameAttribute = "uid" - # For ogranization, leave empty for this demo, the domainName is what matters, and that is the LDAP structure + # For organization, leave empty for this demo, the domainName is what matters, and that is the LDAP structure # to search for users that require login searchBase = [ {organization = "", domainName = "ou=people,dc=planetexpress,dc=com"}, ] context { initialContextFactory = "com.sun.jndi.ldap.LdapCtxFactory" + initialContextFactory = ${?LDAP_INITIAL_CONTEXT_CLASS} securityAuthentication = "simple" + securityAuthentication = ${?LDAP_SECURITY_AUTH} # Note: The following assumes a purely docker setup, using container_name = vinyldns-ldap - providerUrl = "ldap://vinyldns-ldap:389" + providerUrl = "ldap://vinyldns-ldap:19004" + providerUrl = ${?LDAP_PROVIDER_URL} } # This is only needed if keeping vinyldns user store in sync with ldap (to auto lock out users who left your # company for example) user-sync { enabled = false + enabled = ${?USER_SYNC_ENABLED} hours-polling-interval = 1 + hours-polling-interval = ${?USER_SYNC_POLL_INTERVAL} } } -# Note: This MUST match the API or strange errors will ensure, NoCrypto should not be used for production +# Note: This MUST match the API or strange errors will ensue, NoOpCrypto should not be used for production crypto { type = "vinyldns.core.crypto.NoOpCrypto" + type = ${?CRYPTO_TYPE} + secret = ${?CRYPTO_SECRET} } -http.port = 9000 +http.port = 9001 +http.port = ${?PORTAL_PORT} data-stores = ["mysql"] -portal.vinyldns.backend.url = "http://vinyldns-api:9000" - -# Note: The default mysql settings assume a local docker compose setup with mysql named vinyldns-mysql -# follow the configuration guide to point to your mysql -# Only 3 repositories are needed for portal: user, task, user-change -mysql { - settings { - # JDBC Settings, these are all values in scalikejdbc-config, not our own - # these must be overridden to use MYSQL for production use - # assumes a docker or mysql instance running locally - name = "vinyldns" - driver = "org.mariadb.jdbc.Driver" - migration-url = "jdbc:mariadb://vinyldns-mysql:3306/?user=root&password=pass" - url = "jdbc:mariadb://vinyldns-mysql:3306/vinyldns?user=root&password=pass" - user = "root" - password = "pass" - # see https://github.com/brettwooldridge/HikariCP - connection-timeout-millis = 1000 - idle-timeout = 10000 - max-lifetime = 600000 - maximum-pool-size = 20 - minimum-idle = 20 - register-mbeans = true - } - - repositories { - user { - } - task { - } - user-change { - } - } -} +# Must be true to manage shared zones through the portal +shared-display-enabled = true +shared-display-enabled = ${?SHARED_ZONES_ENABLED} # You generate this yourself following https://www.playframework.com/documentation/2.7.x/ApplicationSecret -play.http.secret.key = "rpkTGtoJvLIdIV?WU=0@yW^x:pcEGyAt`^p/P3G0fpbj9:uDnD@caSjCDqA0@tB=" +play.http.secret.key = "changeme" +play.http.secret.key = ${?PLAY_HTTP_SECRET_KEY} -vinyldns.version = "unknown" -vinyldns.version = ${?VINYLDNS_VERSION} +# You can provide configuration overrides via local.conf if you don't want to replace everything in +# this configuration file +include "local.conf" diff --git a/build/docker/portal/logback.xml b/build/docker/portal/logback.xml new file mode 100644 index 000000000..f8a08e496 --- /dev/null +++ b/build/docker/portal/logback.xml @@ -0,0 +1,21 @@ + + + + + + + %d{"yyyy-MM-dd HH:mm:ss,SSS"} %coloredLevel - %logger - %message%n%xException + + + + + + + + + + + diff --git a/build/docker/test-bind9/Dockerfile b/build/docker/test-bind9/Dockerfile deleted file mode 100644 index 1bfbf4852..000000000 --- a/build/docker/test-bind9/Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM alpine/git:1.0.7 as gitcheckout - -ARG BRANCH=master - -RUN git clone -b ${BRANCH} --single-branch --depth 1 https://github.com/vinyldns/vinyldns.git /vinyldns - -FROM vinyldns/bind9:0.0.5 - -COPY --from=gitcheckout /vinyldns/docker/bind9/zones/* /var/cache/bind/zones/ - -COPY --from=gitcheckout /vinyldns/docker/bind9/etc/named.conf.local /var/cache/bind/config diff --git a/build/docker/test/Dockerfile b/build/docker/test/Dockerfile deleted file mode 100644 index d05e261fd..000000000 --- a/build/docker/test/Dockerfile +++ /dev/null @@ -1,28 +0,0 @@ -FROM alpine/git:1.0.7 as gitcheckout - -ARG BRANCH=master - -RUN git clone -b ${BRANCH} --single-branch --depth 1 https://github.com/vinyldns/vinyldns.git /vinyldns - -FROM python:2.7.16-alpine3.9 - -RUN apk add --update --no-cache bind-tools netcat-openbsd bash curl - -# The run script is what actually runs our func tests -COPY run.sh /app/run.sh -COPY run-tests.py /app/run-tests.py - -RUN chmod a+x /app/run.sh && chmod a+x /app/run-tests.py - -# Copy over the functional test directory, this must have been copied into the build context previous to this building! -COPY --from=gitcheckout /vinyldns/modules/api/functional_test/ /app/ - -# Install our func test requirements -RUN pip install --index-url https://pypi.python.org/simple/ -r /app/requirements.txt - -ENV VINYLDNS_URL="" -ENV DNS_IP="" -ENV TEST_PATTERN="test_verify_production" - -# set the entry point for the container to start vinyl, specify the config resource -ENTRYPOINT ["/app/run.sh"] diff --git a/build/docker/test/run-tests.py b/build/docker/test/run-tests.py deleted file mode 100644 index e4e464be0..000000000 --- a/build/docker/test/run-tests.py +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env python -import os -import sys - -basedir = os.path.dirname(os.path.realpath(__file__)) - -report_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), '../target/pytest_reports') -if not os.path.exists(report_dir): - os.system('mkdir -p ' + report_dir) - -import pytest - -result = 1 -result = pytest.main(list(sys.argv[1:])) - -sys.exit(result) diff --git a/build/docker/test/run.sh b/build/docker/test/run.sh deleted file mode 100644 index 5128b2acb..000000000 --- a/build/docker/test/run.sh +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env bash - -# Assume defaults of local docker-compose if not set -if [ -z "${VINYLDNS_URL}" ]; then - VINYLDNS_URL="http://vinyldns-api:9000" -fi -if [ -z "${DNS_IP}" ]; then - DNS_IP=$(dig +short vinyldns-bind9) -fi - -# Assume all tests if not specified -if [ -z "${TEST_PATTERN}" ]; then - TEST_PATTERN= -else - TEST_PATTERN="-k ${TEST_PATTERN}" -fi - -echo "Waiting for API to be ready at ${VINYLDNS_URL} ..." -DATA="" -RETRY=60 -SLEEP_DURATION=1 -while [ "$RETRY" -gt 0 ] -do - DATA=$(curl -I -s "${VINYLDNS_URL}/ping" -o /dev/null -w "%{http_code}") - if [ $? -eq 0 ] - then - break - else - echo "Retrying" >&2 - - let RETRY-=1 - sleep "$SLEEP_DURATION" - - if [ "$RETRY" -eq 0 ] - then - echo "Exceeded retries waiting for VinylDNS API to be ready, failing" - exit 1 - fi - fi -done - -echo "Running live tests against ${VINYLDNS_URL} and DNS server ${DNS_IP}" - -cd /app - -# Cleanup any errant cached file copies -find . -name "*.pyc" -delete -find . -name "__pycache__" -delete - -ls -al - -# -m plays havoc with -k, using variables is a headache, so doing this by hand -# run parallel tests first (not serial) -set -x -./run-tests.py live_tests -n2 -v -m "not skip_production and not serial" ${TEST_PATTERN} --url=${VINYLDNS_URL} --dns-ip=${DNS_IP} --teardown=False -ret1=$? - -# IMPORTANT! pytest exists status code 5 if no tests are run, force that to 0 -if [ "$ret1" = 5 ]; then - echo "No tests collected." - ret1=0 -fi - -./run-tests.py live_tests -n0 -v -m "not skip_production and serial" ${TEST_PATTERN} --url=${VINYLDNS_URL} --dns-ip=${DNS_IP} --teardown=True -ret2=$? -if [ "$ret2" = 5 ]; then - echo "No tests collected." - ret2=0 -fi - -if [ $ret1 -ne 0 ] || [ $ret2 -ne 0 ]; then - exit 1 -else - exit 0 -fi - diff --git a/build/func-test-api.sh b/build/func-test-api.sh new file mode 100755 index 000000000..650e0c0c4 --- /dev/null +++ b/build/func-test-api.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +# +# This script will perform the functional tests for the API using Docker +# +set -euo pipefail + +DIR=$(cd -P -- "$(dirname -- "$0")" && pwd -P) + +cd "$DIR/../test/api/functional" +make diff --git a/build/func-test-portal.sh b/build/func-test-portal.sh new file mode 100755 index 000000000..b6534d0f1 --- /dev/null +++ b/build/func-test-portal.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +# +# This script will perform the functional tests for the Portal using Docker +# +set -euo pipefail + +DIR=$(cd -P -- "$(dirname -- "$0")" && pwd -P) + +cd "$DIR/../test/portal/functional" +make diff --git a/build/publish_docs.sh b/build/publish_docs.sh new file mode 100755 index 000000000..021d34e7f --- /dev/null +++ b/build/publish_docs.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +set -euo pipefail +DIR=$(cd -P -- "$(dirname -- "$0")" && pwd -P) + +USE_TTY="" && test -t 1 && USE_TTY="-t" +docker run -i ${USE_TTY} --rm -e RUN_SERVICES=none -e SBT_MICROSITES_PUBLISH_TOKEN="${SBT_MICROSITES_PUBLISH_TOKEN}" -v "${DIR}/../:/build" vinyldns/build:base-build-docs /bin/bash -c "sbt ';project docs; publishMicrosite'" diff --git a/build/run_all_tests.sh b/build/run_all_tests.sh new file mode 100755 index 000000000..36cdc2c62 --- /dev/null +++ b/build/run_all_tests.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +set -euo pipefail +DIR=$(cd -P -- "$(dirname -- "$0")" && pwd -P) + +source "${DIR}/../utils/includes/terminal_colors.sh" + +if [ ! -d "${DIR}/../artifacts" ] || [ ! -f "${DIR}/../artifacts/vinyldns-api.jar" ]; then + echo -e "${F_YELLOW}Warning:${F_RESET} you might want to run 'build/assemble_api.sh' first to improve performance" +fi + +echo "Running unit and integration tests..." +if ! "${DIR}/verify.sh"; then + echo "Error running unit and integration tests." + exit 1 +fi + +echo "Running API functional tests..." +if ! "${DIR}/func-test-api.sh"; then + echo "Error running API functional tests" + exit 1 +fi + +echo "Running Portal functional tests..." +if ! "${DIR}/func-test-portal.sh"; then + echo "Error running Portal functional tests" + exit 1 +fi diff --git a/build/sbt.sh b/build/sbt.sh new file mode 100755 index 000000000..e02750d64 --- /dev/null +++ b/build/sbt.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +set -euo pipefail + +DIR=$(cd -P -- "$(dirname -- "$0")" && pwd -P) + +cd "$DIR/../test/api/integration" +make build DOCKER_PARAMS="--build-arg SKIP_API_BUILD=true" && make run-local WITH_ARGS="sbt" DOCKER_PARAMS="-e RUN_SERVICES=none --env-file \"$DIR/../test/api/integration/.env.integration\"" diff --git a/build/start.sh b/build/start.sh deleted file mode 100755 index 1b5834d4d..000000000 --- a/build/start.sh +++ /dev/null @@ -1,73 +0,0 @@ -#!/bin/bash - -CURDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -function usage() { - printf "usage: start.sh [OPTIONS]\n\n" - printf "starts a specific version of vinyldns\n\n" - printf "options:\n" - printf "\t-v, --version: the version to start up; required\n" -} - -function wait_for_url() { - URL=$1 - DATA="" - RETRY="60" - echo "pinging $URL ..." - while [ "$RETRY" -gt 0 ]; do - DATA=$(curl -I -s "${URL}" -o /dev/null -w "%{http_code}") - if [ $? -eq 0 ]; then - echo "Succeeded in connecting to ${URL}!" - break - else - echo "Retrying" >&2 - - let RETRY-=1 - sleep 1 - - if [ "$RETRY" -eq 0 ]; then - echo "Exceeded retries waiting for ${URL} to be ready, failing" - exit 1 - fi - fi - done -} - -# Default the build to -SNAPSHOT if not set -VINYLDNS_VERSION= - -while [ "$1" != "" ]; do - case "$1" in - -v | --version) - VINYLDNS_VERSION="$2" - shift 2 - ;; - *) - usage - exit - ;; - esac -done - -if [ -z "$VINYLDNS_VERSION" ]; then - echo "VINYLDNS_VERSION not set" - usage - exit -else - export VINYLDNS_VERSION=$VINYLDNS_VERSION -fi - -# Actually starts up our docker images -docker-compose -f $CURDIR/docker/docker-compose.yml up --no-build -d api portal - -# Waits for the URL to be available -wait_for_url "http://localhost:9001" - -if [ $? -eq 0 ]; then - echo "VinylDNS started and available at http://localhost:9001" - exit 0 -else - echo "VinylDNS startup failed!" - $CURDIR/stop.sh - exit 1 -fi diff --git a/build/stop.sh b/build/stop.sh deleted file mode 100755 index b9b62a964..000000000 --- a/build/stop.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -CURDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -docker-compose -f $CURDIR/docker/docker-compose.yml down diff --git a/build/verify.sh b/build/verify.sh new file mode 100755 index 000000000..649c40edc --- /dev/null +++ b/build/verify.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +set -euo pipefail + +DIR=$(cd -P -- "$(dirname -- "$0")" && pwd -P) + +cd "${DIR}/../test/api/integration" +make build && make run DOCKER_PARAMS="-v \"$(pwd)/../../../target:/build/target\"" WITH_ARGS="bash -c \"sbt ';validate' && sbt ';verify'\"" diff --git a/docker/.env b/docker/.env deleted file mode 100644 index 9837a2470..000000000 --- a/docker/.env +++ /dev/null @@ -1,17 +0,0 @@ -REST_PORT=9000 -# Do not use quotes around the environment variables. -MYSQL_ROOT_PASSWORD=pass -# This is required as mysql is currently locked down to localhost -MYSQL_ROOT_HOST=% -# Host URL for queue -QUEUE_HOST=vinyldns-elasticmq - -# portal settings -PORTAL_PORT=9001 -PLAY_HTTP_SECRET_KEY=change-this-for-prod -VINYLDNS_BACKEND_URL=http://vinyldns-api:9000 -SQS_ENDPOINT=http://vinyldns-localstack:19007 -MYSQL_ENDPOINT=vinyldns-mysql:3306 -USER_TABLE_NAME=users -USER_CHANGE_TABLE_NAME=userChange -TEST_LOGIN=true diff --git a/docker/.env.quickstart b/docker/.env.quickstart deleted file mode 100644 index 9837a2470..000000000 --- a/docker/.env.quickstart +++ /dev/null @@ -1,17 +0,0 @@ -REST_PORT=9000 -# Do not use quotes around the environment variables. -MYSQL_ROOT_PASSWORD=pass -# This is required as mysql is currently locked down to localhost -MYSQL_ROOT_HOST=% -# Host URL for queue -QUEUE_HOST=vinyldns-elasticmq - -# portal settings -PORTAL_PORT=9001 -PLAY_HTTP_SECRET_KEY=change-this-for-prod -VINYLDNS_BACKEND_URL=http://vinyldns-api:9000 -SQS_ENDPOINT=http://vinyldns-localstack:19007 -MYSQL_ENDPOINT=vinyldns-mysql:3306 -USER_TABLE_NAME=users -USER_CHANGE_TABLE_NAME=userChange -TEST_LOGIN=true diff --git a/docker/admin/Dockerfile b/docker/admin/Dockerfile deleted file mode 100644 index e36eb6e55..000000000 --- a/docker/admin/Dockerfile +++ /dev/null @@ -1,18 +0,0 @@ -FROM znly/protoc:0.4.0 as pbcompile - -# Needs to protoc compile modules/core/src/main/protobuf/VinylDNSProto.proto -COPY VinylDNSProto.proto /vinyldns/target/ - -# Create a compiled protobuf in /vinyldns/target -RUN protoc --version && \ - protoc --proto_path=/vinyldns/target --python_out=/vinyldns/target /vinyldns/target/VinylDNSProto.proto - - -FROM python:3.7-alpine - -RUN pip install mysql-connector-python - -COPY --from=pbcompile /vinyldns/target /app/ -COPY update-support-user.py /app/update-support-user.py - -WORKDIR /app diff --git a/docker/api/.dockerignore b/docker/api/.dockerignore deleted file mode 100644 index f4ed141ba..000000000 --- a/docker/api/.dockerignore +++ /dev/null @@ -1,5 +0,0 @@ -.DS_Store -.dockerignore -.git -.gitignore -classes \ No newline at end of file diff --git a/docker/api/Dockerfile b/docker/api/Dockerfile deleted file mode 100644 index a65b93ad4..000000000 --- a/docker/api/Dockerfile +++ /dev/null @@ -1,18 +0,0 @@ -FROM adoptopenjdk/openjdk11:jdk-11.0.7_10-alpine - -RUN apk add --update --no-cache netcat-openbsd bash - -# install the jar onto the server, asserts this Dockerfile is copied to target/scala-2.12 after a build -COPY vinyldns.jar /app/vinyldns-server.jar -COPY run.sh /app/run.sh -RUN chmod a+x /app/run.sh - -COPY docker.conf /app/docker.conf - -EXPOSE 9000 -EXPOSE 2551 - -# set the entry point for the container to start vinyl, specify the config resource -ENTRYPOINT ["/app/run.sh"] - - diff --git a/docker/api/logback.xml b/docker/api/logback.xml deleted file mode 100644 index 4146a79c5..000000000 --- a/docker/api/logback.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - %d [test] %-5p | \(%logger{4}:%line\) | %msg %n - - - - - - - diff --git a/docker/api/run.sh b/docker/api/run.sh deleted file mode 100644 index 830e8bae5..000000000 --- a/docker/api/run.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env bash - -# gets the docker-ized ip address, sets it to an environment variable -export APP_HOST=`ip addr show eth0 | grep 'inet ' | awk '{print $2}' | cut -f1 -d'/'` - -export DYNAMO_ADDRESS="vinyldns-dynamodb" -export DYNAMO_PORT=8000 -export JOURNAL_HOST="vinyldns-dynamodb" -export JOURNAL_PORT=8000 -export MYSQL_ADDRESS="vinyldns-mysql" -export MYSQL_PORT=3306 -export JDBC_USER=root -export JDBC_PASSWORD=pass -export DNS_ADDRESS="vinyldns-bind9" -export DYNAMO_KEY="local" -export DYNAMO_SECRET="local" -export DYNAMO_TABLE_PREFIX="" -export ELASTICMQ_ADDRESS="vinyldns-elasticmq" -export DYNAMO_ENDPOINT="http://${DYNAMO_ADDRESS}:${DYNAMO_PORT}" -export JDBC_URL="jdbc:mariadb://${MYSQL_ADDRESS}:${MYSQL_PORT}/vinyldns?user=${JDBC_USER}&password=${JDBC_PASSWORD}" -export JDBC_MIGRATION_URL="jdbc:mariadb://${MYSQL_ADDRESS}:${MYSQL_PORT}/?user=${JDBC_USER}&password=${JDBC_PASSWORD}" - -# wait until mysql is ready... -echo 'Waiting for MYSQL to be ready...' -DATA="" -RETRY=40 -SLEEP_DURATION=1 -while [ "$RETRY" -gt 0 ] -do - DATA=$(nc -vzw1 vinyldns-mysql 3306) - if [ $? -eq 0 ] - then - break - else - echo "Retrying" >&2 - - let RETRY-=1 - sleep "$SLEEP_DURATION" - - if [ "$RETRY" -eq 0 ] - then - echo "Exceeded retries waiting for MYSQL to be ready, failing" - return 1 - fi - fi -done - -echo "Starting up Vinyl..." -sleep 2 -java -Djava.net.preferIPv4Stack=true -Dconfig.file=/app/docker.conf -Dakka.loglevel=INFO -Dlogback.configurationFile=test/logback.xml -jar /app/vinyldns-server.jar vinyldns.api.Boot - diff --git a/docker/bind9/etc/named.conf.local b/docker/bind9/etc/named.conf.local deleted file mode 100755 index f3efc1b6c..000000000 --- a/docker/bind9/etc/named.conf.local +++ /dev/null @@ -1,227 +0,0 @@ -// -// Do any local configuration here -// - -// Consider adding the 1918 zones here, if they are not used in your -// organization -//include "/etc/bind/zones.rfc1918"; - -key "vinyldns." { - algorithm hmac-md5; - secret "nzisn+4G2ldMn0q1CV3vsg=="; -}; - -key "vinyldns-sha1." { - algorithm hmac-sha1; - secret "0nIhR1zS/nHUg2n0AIIUyJwXUyQ="; -}; - -key "vinyldns-sha224." { - algorithm hmac-sha224; - secret "yud/F666YjcnfqPSulHaYXrNObNnS1Jv+rX61A=="; -}; - -key "vinyldns-sha256." { - algorithm hmac-sha256; - secret "wzLsDGgPRxFaC6z/9Bc0n1W4KrnmaUdFCgCn2+7zbPU="; -}; - -key "vinyldns-sha384." { - algorithm hmac-sha384; - secret "ne9jSUJ7PBGveM37aOX+ZmBXQgz1EqkbYBO1s5l/LNpjEno4OfYvGo1Lv1rnw3pE"; -}; - -key "vinyldns-sha512." { - algorithm hmac-sha512; - secret "xfKA0DYb88tiUGND+cWddwUg3/SugYSsdvCfBOJ1jr8MEdgbVRyrlVDEXLsfTUGorQ3ShENdymw2yw+rTr+lwA=="; -}; - -// Consider adding the 1918 zones here, if they are not used in your -// organization -//include "/etc/bind/zones.rfc1918"; -zone "vinyldns" { - type master; - file "/var/bind/vinyldns.hosts"; - allow-update { key "vinyldns."; }; - }; - -zone "old-vinyldns2" { - type master; - file "/var/bind/old-vinyldns2.hosts"; - allow-update { key "vinyldns."; }; - }; - -zone "old-vinyldns3" { - type master; - file "/var/bind/old-vinyldns3.hosts"; - allow-update { key "vinyldns."; }; - }; - -zone "dummy" { - type master; - file "/var/bind/dummy.hosts"; - allow-update { key "vinyldns."; }; - }; - -zone "ok" { - type master; - file "/var/bind/ok.hosts"; - allow-update { key "vinyldns."; }; - }; - -zone "shared" { - type master; - file "/var/bind/shared.hosts"; - allow-update { key "vinyldns."; }; - }; - -zone "non.test.shared" { - type master; - file "/var/bind/non.test.shared.hosts"; - allow-update { key "vinyldns."; }; - }; - -zone "system-test" { - type master; - file "/var/bind/system-test.hosts"; - allow-update { key "vinyldns."; }; - }; - -zone "system-test-history" { - type master; - file "/var/bind/system-test-history.hosts"; - allow-update { key "vinyldns."; }; - }; - -zone "10.10.in-addr.arpa" { - type master; - file "/var/bind/10.10.in-addr.arpa"; - allow-update { key "vinyldns."; }; - }; - -zone "2.0.192.in-addr.arpa" { - type master; - file "/var/bind/2.0.192.in-addr.arpa"; - allow-update { key "vinyldns."; }; - }; - -zone "192/30.2.0.192.in-addr.arpa" { - type master; - file "/var/bind/192^30.2.0.192.in-addr.arpa"; - allow-update { key "vinyldns."; }; - }; - -zone "1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa" { - type master; - file "/var/bind/1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa"; - allow-update { key "vinyldns."; }; - }; - -zone "0.0.0.1.1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa" { - type master; - file "/var/bind/0.0.0.1.1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa"; - allow-update { key "vinyldns."; }; - }; - -zone "one-time" { - type master; - file "/var/bind/one-time.hosts"; - allow-update { key "vinyldns."; key "vinyldns-sha1."; key "vinyldns-sha224."; key "vinyldns-sha256."; key "vinyldns-sha384."; key "vinyldns-sha512."; }; - }; - -zone "sync-test" { - type master; - file "/var/bind/sync-test.hosts"; - allow-update { key "vinyldns."; }; - }; - -zone "invalid-zone" { - type master; - file "/var/bind/invalid-zone.hosts"; - allow-update { key "vinyldns."; }; - }; - -zone "list-zones-test-searched-1" { - type master; - file "/var/bind/list-zones-test-searched-1.hosts"; - allow-update { key "vinyldns."; }; - }; - -zone "list-zones-test-searched-2" { - type master; - file "/var/bind/list-zones-test-searched-2.hosts"; - allow-update { key "vinyldns."; }; - }; - -zone "list-zones-test-searched-3" { - type master; - file "/var/bind/list-zones-test-searched-3.hosts"; - allow-update { key "vinyldns."; }; - }; - -zone "list-zones-test-unfiltered-1" { - type master; - file "/var/bind/list-zones-test-unfiltered-1.hosts"; - allow-update { key "vinyldns."; }; - }; - -zone "list-zones-test-unfiltered-2" { - type master; - file "/var/bind/list-zones-test-unfiltered-2.hosts"; - allow-update { key "vinyldns."; }; - }; - -zone "one-time-shared" { - type master; - file "/var/bind/one-time-shared.hosts"; - allow-update { key "vinyldns."; }; - }; - -zone "parent.com" { - type master; - file "/var/bind/parent.com.hosts"; - allow-update { key "vinyldns."; }; - }; - -zone "child.parent.com" { - type master; - file "/var/bind/child.parent.com.hosts"; - allow-update { key "vinyldns."; }; - }; - -zone "example.com" { - type master; - file "/var/bind/example.com.hosts"; - allow-update { key "vinyldns."; }; - }; - -zone "dskey.example.com" { - type master; - file "/var/bind/dskey.example.com.hosts"; - allow-update { key "vinyldns."; }; - }; - -zone "not.loaded" { - type master; - file "/var/bind/not.loaded.hosts"; - allow-update { key "vinyldns."; }; - }; - -zone "zone.requires.review" { - type master; - file "/var/bind/zone.requires.review.hosts"; - allow-update { key "vinyldns."; }; - }; - -zone "list-records" { - type master; - file "/var/bind/list-records.hosts"; - allow-update { key "vinyldns."; }; - }; - -zone "open" { - type master; - file "/var/bind/open.hosts"; - allow-update { any; }; - allow-transfer { any; }; - }; \ No newline at end of file diff --git a/docker/docker-compose-func-test-testbind9.yml b/docker/docker-compose-func-test-testbind9.yml deleted file mode 100644 index d4e3b6704..000000000 --- a/docker/docker-compose-func-test-testbind9.yml +++ /dev/null @@ -1,60 +0,0 @@ -version: "3.0" -services: - mysql: - image: "mysql:5.7" - env_file: - .env - container_name: "vinyldns-mysql" - ports: - - "19002:3306" - logging: - driver: none - - bind9: - image: "vinyldns/test-bind9:0.9.4" - container_name: "vinyldns-bind9" - ports: - - "19001:53/tcp" - - "19001:53/udp" - logging: - driver: none - - localstack: - image: localstack/localstack:0.10.4 - container_name: "vinyldns-localstack" - ports: - - "19000:19000" - - "19006:19006" - - "19007:19007" - - "19009:19009" - environment: - - SERVICES=sns:19006,sqs:19007,route53:19009 - - START_WEB=0 - - HOSTNAME_EXTERNAL=vinyldns-localstack - - # this file is copied into the target directory to get the jar! won't run in place as is! - api: - build: - context: api - env_file: - .env - container_name: "vinyldns-api" - ports: - - "9000:9000" - depends_on: - - mysql - - bind9 - - localstack - logging: - driver: none - - functest: - build: - context: functest - env_file: - .env - environment: - - PAR_CPU=${PAR_CPU} - container_name: "vinyldns-functest" - depends_on: - - api diff --git a/docker/docker-compose-func-test.yml b/docker/docker-compose-func-test.yml deleted file mode 100644 index 515a55c1f..000000000 --- a/docker/docker-compose-func-test.yml +++ /dev/null @@ -1,62 +0,0 @@ -version: "3.0" -services: - mysql: - image: "mysql:5.7" - env_file: - .env - container_name: "vinyldns-mysql" - ports: - - "19002:3306" - logging: - driver: none - - bind9: - image: "vinyldns/bind9:0.0.4" - env_file: - .env - container_name: "vinyldns-bind9" - volumes: - - ./bind9/etc:/var/cache/bind/config - - ./bind9/zones:/var/cache/bind/zones - ports: - - "19001:53/tcp" - - "19001:53/udp" - logging: - driver: none - - localstack: - image: localstack/localstack:0.10.4 - container_name: "vinyldns-localstack" - ports: - - "19006:19006" - - "19007:19007" - - "19009:19009" - environment: - - SERVICES=sns:19006,sqs:19007,route53:19009 - - START_WEB=0 - - HOSTNAME_EXTERNAL=vinyldns-localstack - - # this file is copied into the target directory to get the jar! won't run in place as is! - api: - build: - context: api - env_file: - .env - container_name: "vinyldns-api" - ports: - - "9000:9000" - depends_on: - - mysql - - bind9 - - localstack - - functest: - build: - context: functest - env_file: - .env - environment: - - PAR_CPU=${PAR_CPU} - container_name: "vinyldns-functest" - depends_on: - - api diff --git a/docker/docker-compose-quick-start.yml b/docker/docker-compose-quick-start.yml deleted file mode 100644 index 28990de85..000000000 --- a/docker/docker-compose-quick-start.yml +++ /dev/null @@ -1,68 +0,0 @@ -version: "3.0" -services: - mysql: - image: "mysql:5.7" - env_file: - .env.quickstart - container_name: "vinyldns-mysql" - ports: - - "19002:3306" - - bind9: - image: "vinyldns/bind9:0.0.4" - env_file: - .env.quickstart - container_name: "vinyldns-bind9" - ports: - - "19001:53/udp" - - "19001:53" - volumes: - - ./bind9/etc:/var/cache/bind/config - - ./bind9/zones:/var/cache/bind/zones - - localstack: - image: localstack/localstack:0.10.4 - container_name: "vinyldns-localstack" - ports: - - "19006:19006" - - "19007:19007" - - "19009:19009" - environment: - - SERVICES=sns:19006,sqs:19007,route53:19009 - - START_WEB=0 - - HOSTNAME_EXTERNAL=vinyldns-localstack - - ldap: - image: rroemhild/test-openldap - container_name: "vinyldns-ldap" - ports: - - "19008:389" - - api: - image: "vinyldns/api:${VINYLDNS_VERSION}" - env_file: - .env.quickstart - container_name: "vinyldns-api" - ports: - - "${REST_PORT}:${REST_PORT}" - volumes: - - ./api/docker.conf:/opt/docker/conf/application.conf - - ./api/logback.xml:/opt/docker/conf/logback.xml - depends_on: - - mysql - - bind9 - - localstack - - portal: - image: "vinyldns/portal:${VINYLDNS_VERSION}" - env_file: - .env.quickstart - ports: - - "${PORTAL_PORT}:${PORTAL_PORT}" - container_name: "vinyldns-portal" - volumes: - - ./portal/application.ini:/opt/docker/conf/application.ini - - ./portal/application.conf:/opt/docker/conf/application.conf - depends_on: - - api - - ldap diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml deleted file mode 100644 index 0c741a36a..000000000 --- a/docker/docker-compose.yml +++ /dev/null @@ -1,41 +0,0 @@ -version: "3.0" -services: - mysql: - image: mysql:5.7 - env_file: - .env - ports: - - "19002:3306" - - bind9: - image: vinyldns/bind9:0.0.4 - env_file: - .env - ports: - - "19001:53/udp" - - "19001:53" - volumes: - - ./bind9/etc:/var/cache/bind/config - - ./bind9/zones:/var/cache/bind/zones - - localstack: - image: localstack/localstack:0.10.4 - ports: - - "19006:19006" - - "19007:19007" - - "19009:19009" - environment: - - SERVICES=sns:19006,sqs:19007,route53:19009 - - START_WEB=0 - - mail: - image: flaviovs/mock-smtp:0.0.2 - ports: - - "19025:25" - volumes: - - ./email:/var/lib/mock-smtp - - ldap: - image: rroemhild/test-openldap:latest - ports: - - "19008:389" diff --git a/docker/elasticmq/Dockerfile b/docker/elasticmq/Dockerfile deleted file mode 100644 index a9f515970..000000000 --- a/docker/elasticmq/Dockerfile +++ /dev/null @@ -1,10 +0,0 @@ -FROM alpine:3.2 -FROM anapsix/alpine-java:8_server-jre - -EXPOSE 9324 - -COPY run.sh /elasticmq/run.sh -COPY custom.conf /elasticmq/custom.conf -COPY elasticmq-server-0.13.2.jar /elasticmq/server.jar - -ENTRYPOINT ["/elasticmq/run.sh"] diff --git a/docker/elasticmq/custom.conf b/docker/elasticmq/custom.conf deleted file mode 100644 index 83a3a86c5..000000000 --- a/docker/elasticmq/custom.conf +++ /dev/null @@ -1,22 +0,0 @@ -node-address { - protocol = http - host = "localhost" - host = ${?QUEUE_HOST} - port = 9324 - context-path = "" -} - -rest-sqs { - enabled = true - bind-port = 9324 - bind-hostname = "0.0.0.0" - // Possible values: relaxed, strict - sqs-limits = relaxed -} - -queues { - vinyldns { - defaultVisibilityTimeout = 10 seconds - receiveMessageWait = 0 seconds - } -} diff --git a/docker/elasticmq/run.sh b/docker/elasticmq/run.sh deleted file mode 100755 index f498d5992..000000000 --- a/docker/elasticmq/run.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -# gets the docker-ized ip address, sets it to an environment variable -export APP_HOST=`ip addr show eth0 | grep 'inet ' | awk '{print $2}' | cut -f1 -d'/'` - -echo "APP HOST = ${APP_HOST}" - -java -Djava.net.preferIPv4Stack=true -Dconfig.file=/elasticmq/custom.conf -jar /elasticmq/server.jar diff --git a/docker/email/.gitignore b/docker/email/.gitignore deleted file mode 100644 index d6b7ef32c..000000000 --- a/docker/email/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore diff --git a/docker/functest/Dockerfile b/docker/functest/Dockerfile deleted file mode 100644 index dad66350d..000000000 --- a/docker/functest/Dockerfile +++ /dev/null @@ -1,23 +0,0 @@ -FROM python:2.7.15-stretch - -# Install dns utils so we can run dig -RUN apt-get update && apt-get install dnsutils -y - -# The run script is what actually runs our func tests -COPY run.sh /app/run.sh -RUN chmod a+x /app/run.sh - -COPY run-tests.py /app/run-tests.py -RUN chmod a+x /app/run-tests.py - -# Copy over the functional test directory, this must have been copied into the build context previous to this building! -ADD functional_test /app - -# Install our func test requirements -RUN pip install --index-url https://pypi.python.org/simple/ -r /app/requirements.txt - -# Specifies how many CPUs to use for func tests; the more the better or specifiy "auto" for optimal results -ENV PAR_CPU=2 - -# set the entry point for the container to start vinyl, specify the config resource -ENTRYPOINT ["/app/run.sh"] diff --git a/docker/functest/run-tests.py b/docker/functest/run-tests.py deleted file mode 100644 index 1d270a6d5..000000000 --- a/docker/functest/run-tests.py +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env python -import os -import sys - -basedir = os.path.dirname(os.path.realpath(__file__)) - -report_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), '../target/pytest_reports') -if not os.path.exists(report_dir): - os.system('mkdir -p ' + report_dir) - -import pytest - -result = 1 -result = pytest.main(list(sys.argv[1:])) - -sys.exit(result) - - diff --git a/docker/functest/run.sh b/docker/functest/run.sh deleted file mode 100644 index 812c78c8c..000000000 --- a/docker/functest/run.sh +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env bash - -# Assume defaults of local docker-compose if not set -if [ -z "${VINYLDNS_URL}" ]; then - VINYLDNS_URL="http://vinyldns-api:9000" -fi -if [ -z "${DNS_IP}" ]; then - DNS_IP=$(dig +short vinyldns-bind9) -fi - -# Assume all tests if not specified -if [ -z "${TEST_PATTERN}" ]; then - TEST_PATTERN= -else - TEST_PATTERN="-k ${TEST_PATTERN}" -fi - -if [ -z "${PAR_CPU}" ]; then - export PAR_CPU=2 -fi - -echo "Waiting for API to be ready at ${VINYLDNS_URL} ..." -DATA="" -RETRY=60 -SLEEP_DURATION=1 -while [ "$RETRY" -gt 0 ] -do - DATA=$(curl -I -s "${VINYLDNS_URL}/ping" -o /dev/null -w "%{http_code}") - if [ $? -eq 0 ] - then - break - else - echo "Retrying" >&2 - - let RETRY-=1 - sleep "$SLEEP_DURATION" - - if [ "$RETRY" -eq 0 ] - then - echo "Exceeded retries waiting for VinylDNS API to be ready, failing" - exit 1 - fi - fi -done - -echo "Running live tests against ${VINYLDNS_URL} and DNS server ${DNS_IP}" - -cd /app - -# Cleanup any errant cached file copies -find . -name "*.pyc" -delete -find . -name "__pycache__" -delete - -result=0 -# If PROD_ENV is not true, we are in a local docker environment so do not skip anything -if [ "${PROD_ENV}" = "true" ]; then - # -m plays havoc with -k, using variables is a headache, so doing this by hand - # run parallel tests first (not serial) - echo "./run-tests.py live_tests -n${PAR_CPU} -v -m \"not skip_production and not serial\" -v --url=${VINYLDNS_URL} --dns-ip=${DNS_IP} ${TEST_PATTERN} --teardown=False" - ./run-tests.py live_tests -n${PAR_CPU} -v -m "not skip_production and not serial" --url=${VINYLDNS_URL} --dns-ip=${DNS_IP} ${TEST_PATTERN} --teardown=False - result=$? - if [ $result -eq 0 ]; then - # run serial tests second (serial marker) - echo "./run-tests.py live_tests -n0 -v -m \"not skip_production and serial\" -v --url=${VINYLDNS_URL} --dns-ip=${DNS_IP} ${TEST_PATTERN} --teardown=True" - ./run-tests.py live_tests -n0 -v -m "not skip_production and serial" --url=${VINYLDNS_URL} --dns-ip=${DNS_IP} ${TEST_PATTERN} --teardown=True - result=$? - fi -else - # run parallel tests first (not serial) - echo "./run-tests.py live_tests -n${PAR_CPU} -v -m \"not serial\" --url=${VINYLDNS_URL} --dns-ip=${DNS_IP} ${TEST_PATTERN} --teardown=False" - ./run-tests.py live_tests -n${PAR_CPU} -v -m "not serial" --url=${VINYLDNS_URL} --dns-ip=${DNS_IP} ${TEST_PATTERN} --teardown=False - result=$? - if [ $result -eq 0 ]; then - # run serial tests second (serial marker) - echo "./run-tests.py live_tests -n0 -v -m \"serial\" --url=${VINYLDNS_URL} --dns-ip=${DNS_IP} ${TEST_PATTERN} --teardown=True" - ./run-tests.py live_tests -n0 -v -m "serial" --url=${VINYLDNS_URL} --dns-ip=${DNS_IP} ${TEST_PATTERN} --teardown=True - result=$? - fi -fi - -exit $result diff --git a/docker/portal/application.conf b/docker/portal/application.conf deleted file mode 100644 index 9b035a971..000000000 --- a/docker/portal/application.conf +++ /dev/null @@ -1,59 +0,0 @@ -LDAP { - # For OpenLDAP, this would be a full DN to the admin for LDAP / user that can see all users - user = "cn=admin,dc=planetexpress,dc=com" - - # Password for the admin account - password = "GoodNewsEveryone" - - # Keep this as an empty string for OpenLDAP - domain = "" - - # This will be the name of the LDAP field that carries the user's login id (what they enter in the username in login form) - userNameAttribute = "uid" - - # For ogranization, leave empty for this demo, the domainName is what matters, and that is the LDAP structure - # to search for users that require login - searchBase = [ - {organization = "", domainName = "ou=people,dc=planetexpress,dc=com"}, - ] - context { - initialContextFactory = "com.sun.jndi.ldap.LdapCtxFactory" - securityAuthentication = "simple" - - # Note: The following assumes a purely docker setup, using container_name = vinyldns-ldap - providerUrl = "ldap://vinyldns-ldap:389" - } - - # This is only needed if keeping vinyldns user store in sync with ldap (to auto lock out users who left your - # company for example) - user-sync { - enabled = false - hours-polling-interval = 1 - } -} - -# Note: This MUST match the API or strange errors will ensure, NoCrypto should not be used for production -crypto { - type = "vinyldns.core.crypto.NoOpCrypto" -} - -http.port = 9001 - -data-stores = ["mysql"] - -# Note: The default mysql settings assume a local docker compose setup with mysql named vinyldns-mysql -# follow the configuration guide to point to your mysql -# Only 3 repositories are needed for portal: user, task, user-change -mysql { - repositories { - user { - } - task { - } - user-change { - } - } -} - -# You generate this yourself following https://www.playframework.com/documentation/2.7.x/ApplicationSecret -play.http.secret.key = "rpkTGtoJvLIdIV?WU=0@yW^x:pcEGyAt`^p/P3G0fpbj9:uDnD@caSjCDqA0@tB=" diff --git a/docker/portal/application.ini b/docker/portal/application.ini deleted file mode 100644 index ddbb62aa0..000000000 --- a/docker/portal/application.ini +++ /dev/null @@ -1,3 +0,0 @@ -# uncomment to set custom trustStore -# don't forget to mount trustStore to docker image -#-Djavax.net.ssl.trustStore=/opt/docker/conf/trustStore.jks diff --git a/img/VinylDNS_overview.png b/img/VinylDNS_overview.png deleted file mode 100644 index b673b0778..000000000 Binary files a/img/VinylDNS_overview.png and /dev/null differ diff --git a/img/vinyldns_overview.png b/img/vinyldns_overview.png new file mode 100644 index 000000000..cc33b79d8 Binary files /dev/null and b/img/vinyldns_overview.png differ diff --git a/modules/api/functional_test/bootstrap.sh b/modules/api/functional_test/bootstrap.sh deleted file mode 100755 index 0c43fe630..000000000 --- a/modules/api/functional_test/bootstrap.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -e - -if [ ! -d "./.virtualenv" ]; then - echo "Creating virtualenv..." - virtualenv --clear --python="$(which python2.7)" ./.virtualenv -fi - -if ! diff ./requirements.txt ./.virtualenv/requirements.txt &> /dev/null; then - echo "Installing dependencies..." - .virtualenv/bin/python ./.virtualenv/bin/pip install --index-url https://pypi.python.org/simple/ -r ./requirements.txt - cp ./requirements.txt ./.virtualenv/ -fi diff --git a/modules/api/functional_test/boto_request_signer.py b/modules/api/functional_test/boto_request_signer.py deleted file mode 100644 index f6cbc53a3..000000000 --- a/modules/api/functional_test/boto_request_signer.py +++ /dev/null @@ -1,103 +0,0 @@ -import logging - -from datetime import datetime -from hashlib import sha256 - -from boto.dynamodb2.layer1 import DynamoDBConnection - -import requests.compat as urlparse - -logger = logging.getLogger(__name__) - -__all__ = [u'BotoRequestSigner'] - - -class BotoRequestSigner(object): - - def __init__(self, index_url, access_key, secret_access_key): - url = urlparse.urlparse(index_url) - self.boto_connection = DynamoDBConnection( - host = url.hostname, - port = url.port, - aws_access_key_id = access_key, - aws_secret_access_key = secret_access_key, - is_secure = False) - - @staticmethod - def canonical_date(headers): - """Derive canonical date (ISO 8601 string) from headers if possible, - or synthesize it if no usable header exists.""" - iso_format = u'%Y%m%dT%H%M%SZ' - http_format = u'%a, %d %b %Y %H:%M:%S GMT' - - def try_parse(date_string, format): - if date_string is None: - return None - try: - return datetime.strptime(date_string, format) - except ValueError: - return None - - amz_date = try_parse(headers.get(u'X-Amz-Date'), iso_format) - http_date = try_parse(headers.get(u'Date'), http_format) - fallback_date = datetime.utcnow() - - date = next(d for d in [amz_date, http_date, fallback_date] if d is not None) - return date.strftime(iso_format) - - def build_auth_header(self, method, path, headers, body, params=None): - """Construct an Authorization header, using boto.""" - - request = self.boto_connection.build_base_http_request( - method=method, - path=path, - auth_path=path, - headers=headers, - data=body, - params=params or {}) - - auth_handler = self.boto_connection._auth_handler - - timestamp = BotoRequestSigner.canonical_date(headers) - request.timestamp = timestamp[0:8] - - request.region_name = u'us-east-1' - request.service_name = u'VinylDNS' - - credential_scope = u'/'.join([request.timestamp, request.region_name, request.service_name, u'aws4_request']) - - canonical_request = auth_handler.canonical_request(request) - split_request = canonical_request.split('\n') - - if params != {} and split_request[2] == '': - split_request[2] = self.generate_canonical_query_string(params) - canonical_request = '\n'.join(split_request) - hashed_request = sha256(canonical_request.encode(u'utf-8')).hexdigest() - - string_to_sign = u'\n'.join([u'AWS4-HMAC-SHA256', timestamp, credential_scope, hashed_request]) - signature = auth_handler.signature(request, string_to_sign) - headers_to_sign = auth_handler.headers_to_sign(request) - - auth_header = u','.join([ - u'AWS4-HMAC-SHA256 Credential=%s' % auth_handler.scope(request), - u'SignedHeaders=%s' % auth_handler.signed_headers(headers_to_sign), - u'Signature=%s' % signature]) - - return auth_header - - @staticmethod - def generate_canonical_query_string(params): - """ - Using in place of canonical_query_string from boto/auth.py to support POST requests with query parameters - """ - post_params = [] - for param in sorted(params): - value = params[param].encode('utf-8') - import urllib - try: - post_params.append('%s=%s' % (urllib.parse.quote(param, safe='-_.~'), - urllib.parse.quote(value, safe='-_.~'))) - except: - post_params.append('%s=%s' % (urllib.quote(param, safe='-_.~'), - urllib.quote(value, safe='-_.~'))) - return '&'.join(post_params) diff --git a/modules/api/functional_test/conftest.py b/modules/api/functional_test/conftest.py deleted file mode 100644 index fb0f04a96..000000000 --- a/modules/api/functional_test/conftest.py +++ /dev/null @@ -1,103 +0,0 @@ -import os - -from vinyldns_context import VinylDNSTestContext - - -def pytest_addoption(parser): - """ - Adds additional options that we can parse when we run the tests, stores them in the parser / py.test context - """ - parser.addoption("--url", dest="url", action="store", default="http://localhost:9000", - help="URL for application to root") - parser.addoption("--dns-ip", dest="dns_ip", action="store", default="127.0.0.1:19001", - help="The ip address for the dns server to use for the tests") - parser.addoption("--dns-zone", dest="dns_zone", action="store", default="vinyldns.", - help="The zone name that will be used for testing") - parser.addoption("--dns-key-name", dest="dns_key_name", action="store", default="vinyldns.", - help="The name of the key used to sign updates for the zone") - parser.addoption("--dns-key", dest="dns_key", action="store", default="nzisn+4G2ldMn0q1CV3vsg==", - help="The tsig key") - - # optional - parser.addoption("--basic-auth", dest="basic_auth_creds", - help="Basic auth credentials in 'user:pass' format") - parser.addoption("--basic-auth-realm", dest="basic_auth_realm", - help="Basic auth realm to use with credentials supplied by \"-b\"") - parser.addoption("--iauth-creds", dest="iauth_creds", - help="Intermediary auth (codebig style) in 'key:secret' format") - parser.addoption("--oauth-creds", dest="oauth_creds", - help="OAuth credentials in consumer:secret format") - parser.addoption("--environment", dest="cim_env", action="store", default="test", - help="CIM_ENV that we are testing against.") - parser.addoption("--teardown", dest="teardown", action="store", default="True", - help="True | False - Whether to teardown the test fixture, or leave it for another run") - - -def pytest_configure(config): - """ - Loads the test context since we are no longer using run.py - """ - - # Monkey patch ssl so we do not verify ssl certs - import ssl - try: - _create_unverified_https_context = ssl._create_unverified_context - except AttributeError: - # Legacy Python that doesn't verify HTTPS certificates by default - pass - else: - # Handle target environment that doesn't support HTTPS verification - ssl._create_default_https_context = _create_unverified_https_context - - url = config.getoption("url", default="http://localhost:9000/") - if not url.endswith('/'): - url += '/' - - import sys - sys.dont_write_bytecode = True - - VinylDNSTestContext.configure(config.getoption("dns_ip"), - config.getoption("dns_zone"), - config.getoption("dns_key_name"), - config.getoption("dns_key"), - config.getoption("url"), - config.getoption("teardown")) - - from shared_zone_test_context import SharedZoneTestContext - if not hasattr(config, 'workerinput'): - print 'Master, standing up the test fixture...' - # use the fixture file if it exists - if os.path.isfile('tmp.out'): - print 'Fixture file found, assuming the fixture file' - SharedZoneTestContext('tmp.out') - else: - print 'No fixture file found, loading a new test fixture' - ctx = SharedZoneTestContext() - ctx.out_fixture_file("tmp.out") - else: - print 'This is a worker' - - -def pytest_unconfigure(config): - # this attribute is only set on workers - print 'Master exiting...' - if not hasattr(config, 'workerinput') and VinylDNSTestContext.teardown: - print 'Master cleaning up...' - from shared_zone_test_context import SharedZoneTestContext - ctx = SharedZoneTestContext('tmp.out') - ctx.tear_down() - os.remove('tmp.out') - else: - print 'Worker exiting...' - - -def pytest_report_header(config): - """ - Overrides the test result header like we do in pyfunc test - """ - header = "Testing against CIM_ENV " + config.getoption("cim_env") - header += "\r\nURL: " + config.getoption("url") - header += "\r\nRunning from directory " + os.getcwd() - header += '\r\nTest shim directory ' + os.path.dirname(__file__) - header += "\r\nDNS IP: " + config.getoption("dns_ip") - return header diff --git a/modules/api/functional_test/live_tests/batch/approve_batch_change_test.py b/modules/api/functional_test/live_tests/batch/approve_batch_change_test.py deleted file mode 100644 index 54d442add..000000000 --- a/modules/api/functional_test/live_tests/batch/approve_batch_change_test.py +++ /dev/null @@ -1,156 +0,0 @@ -from hamcrest import * -from utils import * - - -@pytest.mark.serial -@pytest.mark.manual_batch_review -def test_approve_pending_batch_change_success(shared_zone_test_context): - """ - Test approving a batch change succeeds for a support user - """ - client = shared_zone_test_context.ok_vinyldns_client - approver = shared_zone_test_context.support_user_client - batch_change_input = { - "changes": [ - get_change_A_AAAA_json("test-approve-success.not.loaded.", address="4.3.2.1"), - get_change_A_AAAA_json("needs-review.not.loaded.", address="4.3.2.1"), - get_change_A_AAAA_json("zone-name-flagged-for-manual-review.zone.requires.review.") - ], - "ownerGroupId": shared_zone_test_context.ok_group['id'] - } - - to_delete = [] - to_disconnect = None - try: - result = client.create_batch_change(batch_change_input, status=202) - get_batch = client.get_batch_change(result['id']) - assert_that(get_batch['status'], is_('PendingReview')) - assert_that(get_batch['approvalStatus'], is_('PendingReview')) - assert_that(get_batch['changes'][0]['status'], is_('NeedsReview')) - assert_that(get_batch['changes'][0]['validationErrors'][0]['errorType'], is_('ZoneDiscoveryError')) - assert_that(get_batch['changes'][1]['status'], is_('NeedsReview')) - assert_that(get_batch['changes'][1]['validationErrors'][0]['errorType'], is_('RecordRequiresManualReview')) - assert_that(get_batch['changes'][2]['status'], is_('NeedsReview')) - assert_that(get_batch['changes'][2]['validationErrors'][0]['errorType'], is_('RecordRequiresManualReview')) - - # need to create the zone so the change can succeed - zone = { - 'name': 'not.loaded.', - 'email': 'test@test.com', - 'adminGroupId': shared_zone_test_context.ok_group['id'], - 'backendId': 'func-test-backend', - 'shared': True - } - zone_create = approver.create_zone(zone, status=202) - to_disconnect = zone_create['zone'] - approver.wait_until_zone_active(to_disconnect['id']) - - approved = approver.approve_batch_change(result['id'], status=202) - completed_batch = client.wait_until_batch_change_completed(approved) - to_delete = [(change['zoneId'], change['recordSetId']) for change in completed_batch['changes']] - - assert_that(completed_batch['status'], is_('Complete')) - for change in completed_batch['changes']: - assert_that(change['status'], is_('Complete')) - assert_that(len(change['validationErrors']), is_(0)) - assert_that(completed_batch['approvalStatus'], is_('ManuallyApproved')) - assert_that(completed_batch['reviewerId'], is_('support-user-id')) - assert_that(completed_batch['reviewerUserName'], is_('support-user')) - assert_that(completed_batch, has_key('reviewTimestamp')) - assert_that(get_batch, not(has_key('cancelledTimestamp'))) - finally: - clear_zoneid_rsid_tuple_list(to_delete, client) - if to_disconnect: - approver.abandon_zones(to_disconnect['id'], status=202) - -@pytest.mark.manual_batch_review -def test_approve_pending_batch_change_fails_if_there_are_still_errors(shared_zone_test_context): - """ - Test approving a batch change fails if there are still errors - """ - client = shared_zone_test_context.ok_vinyldns_client - approver = shared_zone_test_context.support_user_client - batch_change_input = { - "changes": [ - get_change_A_AAAA_json("needs-review.nonexistent.", address="4.3.2.1"), - get_change_A_AAAA_json("zone.does.not.exist.") - ], - "ownerGroupId": shared_zone_test_context.ok_group['id'] - } - complete_rs = None - - try: - result = client.create_batch_change(batch_change_input, status=202) - get_batch = client.get_batch_change(result['id']) - assert_that(get_batch['status'], is_('PendingReview')) - assert_that(get_batch['approvalStatus'], is_('PendingReview')) - assert_that(get_batch['changes'][0]['status'], is_('NeedsReview')) - assert_that(get_batch['changes'][0]['validationErrors'][0]['errorType'], is_('RecordRequiresManualReview')) - assert_that(get_batch['changes'][1]['status'], is_('NeedsReview')) - assert_that(get_batch['changes'][1]['validationErrors'][0]['errorType'], is_('ZoneDiscoveryError')) - - approval_response = approver.approve_batch_change(result['id'], status=400) - assert_that((approval_response[0]['errors'][0]), contains_string('Zone Discovery Failed')) - assert_that((approval_response[1]['errors'][0]), contains_string('Zone Discovery Failed')) - - updated_batch = client.get_batch_change(result['id'], status=200) - assert_that(updated_batch['status'], is_('PendingReview')) - assert_that(updated_batch['approvalStatus'], is_('PendingReview')) - assert_that(updated_batch, not(has_key('reviewerId'))) - assert_that(updated_batch, not(has_key('reviewerUserName'))) - assert_that(updated_batch, not(has_key('reviewTimestamp'))) - assert_that(updated_batch, not(has_key('cancelledTimestamp'))) - assert_that(updated_batch['changes'][0]['status'], is_('NeedsReview')) - assert_that(updated_batch['changes'][0]['validationErrors'][0]['errorType'], is_('ZoneDiscoveryError')) - assert_that(updated_batch['changes'][1]['status'], is_('NeedsReview')) - assert_that(updated_batch['changes'][1]['validationErrors'][0]['errorType'], is_('ZoneDiscoveryError')) - finally: - if complete_rs: - delete_result = client.delete_recordset(complete_rs['zoneId'], complete_rs['id'], status=202) - client.wait_until_recordset_change_status(delete_result, 'Complete') - -@pytest.mark.manual_batch_review -def test_approve_batch_change_with_invalid_batch_change_id_fails(shared_zone_test_context): - """ - Test approving a batch change with invalid batch change ID - """ - - client = shared_zone_test_context.ok_vinyldns_client - - error = client.approve_batch_change("some-id", status=404) - assert_that(error, is_("Batch change with id some-id cannot be found")) - -@pytest.mark.manual_batch_review -def test_approve_batch_change_with_comments_exceeding_max_length_fails(shared_zone_test_context): - """ - Test approving a batch change with comments exceeding 1024 characters fails - """ - - client = shared_zone_test_context.ok_vinyldns_client - approve_batch_change_input = { - "reviewComment": "a"*1025 - } - errors = client.approve_batch_change("some-id", approve_batch_change_input, status=400)['errors'] - assert_that(errors, contains_inanyorder("Comment length must not exceed 1024 characters.")) - -@pytest.mark.manual_batch_review -def test_approve_batch_change_fails_with_forbidden_error_for_non_system_admins(shared_zone_test_context): - """ - Test approving a batch change if the reviewer is not a super user or support user - """ - client = shared_zone_test_context.ok_vinyldns_client - batch_change_input = { - "changes": [ - get_change_A_AAAA_json("no-owner-group-id.ok.", address="4.3.2.1") - ] - } - to_delete = [] - - try: - result = client.create_batch_change(batch_change_input, status=202) - completed_batch = client.wait_until_batch_change_completed(result) - to_delete = [(change['zoneId'], change['recordSetId']) for change in completed_batch['changes']] - error = client.approve_batch_change(completed_batch['id'], status=403) - assert_that(error, is_("User does not have access to item " + completed_batch['id'])) - finally: - clear_zoneid_rsid_tuple_list(to_delete, client) diff --git a/modules/api/functional_test/live_tests/conftest.py b/modules/api/functional_test/live_tests/conftest.py deleted file mode 100644 index 6a0e21448..000000000 --- a/modules/api/functional_test/live_tests/conftest.py +++ /dev/null @@ -1,7 +0,0 @@ -import pytest - - -@pytest.fixture(scope="session") -def shared_zone_test_context(request): - from shared_zone_test_context import SharedZoneTestContext - return SharedZoneTestContext("tmp.out") diff --git a/modules/api/functional_test/live_tests/list_batch_summaries_test_context.py b/modules/api/functional_test/live_tests/list_batch_summaries_test_context.py deleted file mode 100644 index e457f191e..000000000 --- a/modules/api/functional_test/live_tests/list_batch_summaries_test_context.py +++ /dev/null @@ -1,106 +0,0 @@ -import time -from hamcrest import * -from utils import * -from vinyldns_context import VinylDNSTestContext -from vinyldns_python import VinylDNSClient - - -class ListBatchChangeSummariesTestContext(): - def __init__(self, shared_zone_test_context): - # Note: this fixture is designed so it will load summaries instead of creating them - self.client = VinylDNSClient(VinylDNSTestContext.vinyldns_url, 'listBatchSummariesAccessKey', - 'listBatchSummariesSecretKey') - self.completed_changes = [] - self.to_delete = None - - acl_rule = generate_acl_rule('Write', userId='list-batch-summaries-id') - add_ok_acl_rules(shared_zone_test_context, [acl_rule]) - - initial_db_check = self.client.list_batch_change_summaries(status=200) - self.group = self.client.get_group('list-summaries-group', status=200) - - batch_change_input_one = { - "comments": "first", - "changes": [ - get_change_CNAME_json("test-first.ok.", cname="one.") - ] - } - - batch_change_input_two = { - "comments": "second", - "changes": [ - get_change_CNAME_json("test-second.ok.", cname="two.") - ] - } - - batch_change_input_three = { - "comments": "last", - "changes": [ - get_change_CNAME_json("test-last.ok.", cname="three.") - ] - } - - batch_change_inputs = [batch_change_input_one, batch_change_input_two, batch_change_input_three] - - record_set_list = [] - self.completed_changes = [] - - if len(initial_db_check['batchChanges']) == 0: - print "\r\n!!! CREATING NEW SUMMARIES" - # make some batch changes - for input in batch_change_inputs: - change = self.client.create_batch_change(input, status=202) - - if 'Review' not in change['status']: - completed = self.client.wait_until_batch_change_completed(change) - assert_that(completed["comments"], equal_to(input["comments"])) - record_set_list += [(change['zoneId'], change['recordSetId']) for change in completed['changes']] - - # sleep for consistent ordering of timestamps, must be at least one second apart - time.sleep(1) - - self.completed_changes = self.client.list_batch_change_summaries(status=200)['batchChanges'] - assert_that(len(self.completed_changes), equal_to(len(batch_change_inputs))) - else: - print "\r\n!!! USING EXISTING SUMMARIES" - self.completed_changes = initial_db_check['batchChanges'] - self.to_delete = set(record_set_list) - - def tear_down(self, shared_zone_test_context): - for result_rs in self.to_delete: - delete_result = shared_zone_test_context.ok_vinyldns_client.delete_recordset(result_rs[0], result_rs[1], - status=202) - shared_zone_test_context.ok_vinyldns_client.wait_until_recordset_change_status(delete_result, 'Complete') - clear_ok_acl_rules(shared_zone_test_context) - - def check_batch_change_summaries_page_accuracy(self, summaries_page, size, next_id=False, start_from=False, - max_items=100, approval_status=False): - # validate fields - if next_id: - assert_that(summaries_page, has_key('nextId')) - else: - assert_that(summaries_page, is_not(has_key('nextId'))) - if start_from: - assert_that(summaries_page['startFrom'], is_(start_from)) - else: - assert_that(summaries_page, is_not(has_key('startFrom'))) - if approval_status: - assert_that(summaries_page, has_key('approvalStatus')) - else: - assert_that(summaries_page, is_not(has_key('approvalStatus'))) - assert_that(summaries_page['maxItems'], is_(max_items)) - - # validate actual page - list_batch_change_summaries = summaries_page['batchChanges'] - assert_that(list_batch_change_summaries, has_length(size)) - - for i, summary in enumerate(list_batch_change_summaries): - assert_that(summary["userId"], equal_to("list-batch-summaries-id")) - assert_that(summary["userName"], equal_to("list-batch-summaries-user")) - assert_that(summary["comments"], equal_to(self.completed_changes[i + start_from]["comments"])) - assert_that(summary["createdTimestamp"], - equal_to(self.completed_changes[i + start_from]["createdTimestamp"])) - assert_that(summary["totalChanges"], equal_to(self.completed_changes[i + start_from]["totalChanges"])) - assert_that(summary["status"], equal_to(self.completed_changes[i + start_from]["status"])) - assert_that(summary["id"], equal_to(self.completed_changes[i + start_from]["id"])) - assert_that(summary, is_not(has_key("reviewerId"))) diff --git a/modules/api/functional_test/live_tests/list_groups_test_context.py b/modules/api/functional_test/live_tests/list_groups_test_context.py deleted file mode 100644 index 76a410060..000000000 --- a/modules/api/functional_test/live_tests/list_groups_test_context.py +++ /dev/null @@ -1,35 +0,0 @@ -from hamcrest import * -from utils import * -from vinyldns_context import VinylDNSTestContext -from vinyldns_python import VinylDNSClient - - -class ListGroupsTestContext(object): - def __init__(self): - self.client = VinylDNSClient(VinylDNSTestContext.vinyldns_url, access_key='listGroupAccessKey', - secret_key='listGroupSecretKey') - self.support_user_client = VinylDNSClient(VinylDNSTestContext.vinyldns_url, 'supportUserAccessKey', - 'supportUserSecretKey') - - def build(self): - try: - for runner in range(0, 50): - new_group = { - 'name': "test-list-my-groups-{0:0>3}".format(runner), - 'email': 'test@test.com', - 'members': [{'id': 'list-group-user'}], - 'admins': [{'id': 'list-group-user'}] - } - self.client.create_group(new_group, status=200) - - except: - # teardown if there was any issue in setup - try: - self.tear_down() - except: - pass - raise - - def tear_down(self): - clear_zones(self.client) - clear_groups(self.client) diff --git a/modules/api/functional_test/live_tests/list_recordsets_test_context.py b/modules/api/functional_test/live_tests/list_recordsets_test_context.py deleted file mode 100644 index b940127f3..000000000 --- a/modules/api/functional_test/live_tests/list_recordsets_test_context.py +++ /dev/null @@ -1,89 +0,0 @@ -from hamcrest import * -from utils import * -from vinyldns_context import VinylDNSTestContext -from vinyldns_python import VinylDNSClient - - -class ListRecordSetsTestContext(object): - def __init__(self): - self.client = VinylDNSClient(VinylDNSTestContext.vinyldns_url, 'listRecordsAccessKey', 'listRecordsSecretKey') - self.zone = None - self.all_records = [] - self.group = None - get_zone = self.client.get_zone_by_name('list-records.', status=(200, 404)) - if get_zone and 'zone' in get_zone: - self.zone = get_zone['zone'] - self.all_records = self.client.list_recordsets_by_zone(self.zone['id'])['recordSets'] - my_groups = self.client.list_my_groups(group_name_filter='list-records-group') - if my_groups and 'groups' in my_groups and len(my_groups['groups']) > 0: - self.group = my_groups['groups'][0] - - def build(self): - # Only call this if the context needs to be built - self.tear_down() - group = { - 'name': 'list-records-group', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [{'id': 'list-records-user'}], - 'admins': [{'id': 'list-records-user'}] - } - self.group = self.client.create_group(group, status=200) - zone_change = self.client.create_zone( - { - 'name': 'list-records.', - 'email': 'test@test.com', - 'shared': False, - 'adminGroupId': self.group['id'], - 'isTest': True, - 'backendId': 'func-test-backend' - }, status=202) - self.client.wait_until_zone_active(zone_change[u'zone'][u'id']) - self.zone = zone_change[u'zone'] - self.all_records = self.client.list_recordsets_by_zone(self.zone['id'])['recordSets'] - - def tear_down(self): - clear_zones(self.client) - clear_groups(self.client) - - def check_recordsets_page_accuracy(self, list_results_page, size, offset, nextId=False, startFrom=False, maxItems=100, recordTypeFilter=False, nameSort="ASC"): - # validate fields - if nextId: - assert_that(list_results_page, has_key('nextId')) - else: - assert_that(list_results_page, is_not(has_key('nextId'))) - if startFrom: - assert_that(list_results_page['startFrom'], is_(startFrom)) - else: - assert_that(list_results_page, is_not(has_key('startFrom'))) - if recordTypeFilter: - assert_that(list_results_page, has_key('recordTypeFilter')) - else: - assert_that(list_results_page, is_not(has_key('recordTypeFilter'))) - assert_that(list_results_page['maxItems'], is_(maxItems)) - assert_that(list_results_page['nameSort'], is_(nameSort)) - - # validate actual page - list_results_recordsets_page = list_results_page['recordSets'] - assert_that(list_results_recordsets_page, has_length(size)) - for i in range(len(list_results_recordsets_page)): - assert_that(list_results_recordsets_page[i]['name'], is_(self.all_records[i+offset]['name'])) - verify_recordset(list_results_recordsets_page[i], self.all_records[i+offset]) - assert_that(list_results_recordsets_page[i]['accessLevel'], is_('Delete')) - - def check_recordsets_parameters(self, list_results_page, nextId=False, startFrom=False, maxItems=100, recordTypeFilter=False, nameSort="ASC"): - # validate fields - if nextId: - assert_that(list_results_page, has_key('nextId')) - else: - assert_that(list_results_page, is_not(has_key('nextId'))) - if startFrom: - assert_that(list_results_page['startFrom'], is_(startFrom)) - else: - assert_that(list_results_page, is_not(has_key('startFrom'))) - if recordTypeFilter: - assert_that(list_results_page, has_key('recordTypeFilter')) - else: - assert_that(list_results_page, is_not(has_key('recordTypeFilter'))) - assert_that(list_results_page['maxItems'], is_(maxItems)) - assert_that(list_results_page['nameSort'], is_(nameSort)) diff --git a/modules/api/functional_test/live_tests/list_zones_test_context.py b/modules/api/functional_test/live_tests/list_zones_test_context.py deleted file mode 100644 index 9d98d6005..000000000 --- a/modules/api/functional_test/live_tests/list_zones_test_context.py +++ /dev/null @@ -1,78 +0,0 @@ -from hamcrest import * -from utils import * -from vinyldns_context import VinylDNSTestContext -from vinyldns_python import VinylDNSClient - - -class ListZonesTestContext(object): - def __init__(self): - self.client = VinylDNSClient(VinylDNSTestContext.vinyldns_url, 'listZonesAccessKey', 'listZonesSecretKey') - - def build(self): - self.tear_down() - group = { - 'name': 'list-zones-group', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [{'id': 'list-zones-user'}], - 'admins': [{'id': 'list-zones-user'}] - } - list_zones_group = self.client.create_group(group, status=200) - search_zone_1_change = self.client.create_zone( - { - 'name': 'list-zones-test-searched-1.', - 'email': 'test@test.com', - 'shared': False, - 'adminGroupId': list_zones_group['id'], - 'isTest': True, - 'backendId': 'func-test-backend' - }, status=202) - - search_zone_2_change = self.client.create_zone( - { - 'name': 'list-zones-test-searched-2.', - 'email': 'test@test.com', - 'shared': False, - 'adminGroupId': list_zones_group['id'], - 'isTest': True, - 'backendId': 'func-test-backend' - }, status=202) - - search_zone_3_change = self.client.create_zone( - { - 'name': 'list-zones-test-searched-3.', - 'email': 'test@test.com', - 'shared': False, - 'adminGroupId': list_zones_group['id'], - 'isTest': True, - 'backendId': 'func-test-backend' - }, status=202) - - non_search_zone_1_change = self.client.create_zone( - { - 'name': 'list-zones-test-unfiltered-1.', - 'email': 'test@test.com', - 'shared': False, - 'adminGroupId': list_zones_group['id'], - 'isTest': True, - 'backendId': 'func-test-backend' - }, status=202) - - non_search_zone_2_change = self.client.create_zone( - { - 'name': 'list-zones-test-unfiltered-2.', - 'email': 'test@test.com', - 'shared': False, - 'adminGroupId': list_zones_group['id'], - 'isTest': True, - 'backendId': 'func-test-backend' - }, status=202) - - zone_changes = [search_zone_1_change, search_zone_2_change, search_zone_3_change, non_search_zone_1_change, - non_search_zone_2_change] - for change in zone_changes: - self.client.wait_until_zone_active(change[u'zone'][u'id']) - - def tear_down(self): - clear_zones(self.client) - clear_groups(self.client) diff --git a/modules/api/functional_test/live_tests/membership/create_group_test.py b/modules/api/functional_test/live_tests/membership/create_group_test.py deleted file mode 100644 index 4a989489a..000000000 --- a/modules/api/functional_test/live_tests/membership/create_group_test.py +++ /dev/null @@ -1,240 +0,0 @@ -import json - -from hamcrest import * - - -def test_create_group_success(shared_zone_test_context): - """ - Tests that creating a group works - """ - client = shared_zone_test_context.ok_vinyldns_client - result = None - - try: - new_group = { - 'name': 'test-create-group-success', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}] - } - result = client.create_group(new_group, status=200) - - assert_that(result['name'], is_(new_group['name'])) - assert_that(result['email'], is_(new_group['email'])) - assert_that(result['description'], is_(new_group['description'])) - assert_that(result['status'], is_('Active')) - assert_that(result['created'], not_none()) - assert_that(result['id'], not_none()) - assert_that(result['members'], has_length(1)) - assert_that(result['members'][0]['id'], is_('ok')) - assert_that(result['admins'], has_length(1)) - assert_that(result['admins'][0]['id'], is_('ok')) - - finally: - if result: - client.delete_group(result['id'], status=(200, 404)) - - -def test_creator_is_an_admin(shared_zone_test_context): - """ - Tests that the creator is an admin - """ - client = shared_zone_test_context.ok_vinyldns_client - result = None - - try: - new_group = { - 'name': 'test-create-group-success', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [{'id': 'ok'}], - 'admins': [] - } - result = client.create_group(new_group, status=200) - - assert_that(result['name'], is_(new_group['name'])) - assert_that(result['email'], is_(new_group['email'])) - assert_that(result['description'], is_(new_group['description'])) - assert_that(result['status'], is_('Active')) - assert_that(result['created'], not_none()) - assert_that(result['id'], not_none()) - assert_that(result['members'], has_length(1)) - assert_that(result['members'][0]['id'], is_('ok')) - assert_that(result['admins'], has_length(1)) - assert_that(result['admins'][0]['id'], is_('ok')) - - finally: - if result: - client.delete_group(result['id'], status=(200, 404)) - - -def test_create_group_without_name(shared_zone_test_context): - """ - Tests that creating a group without a name fails - """ - client = shared_zone_test_context.ok_vinyldns_client - - new_group = { - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}] - } - errors = client.create_group(new_group, status=400)['errors'] - assert_that(errors[0], is_("Missing Group.name")) - - -def test_create_group_without_email(shared_zone_test_context): - """ - Tests that creating a group without an email fails - """ - client = shared_zone_test_context.ok_vinyldns_client - - new_group = { - 'name': 'without-email', - 'description': 'this is a description', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}] - } - errors = client.create_group(new_group, status=400)['errors'] - assert_that(errors[0], is_("Missing Group.email")) - - -def test_create_group_without_name_or_email(shared_zone_test_context): - """ - Tests that creating a group without name or an email fails - """ - client = shared_zone_test_context.ok_vinyldns_client - - new_group = { - 'description': 'this is a description', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}] - } - errors = client.create_group(new_group, status=400)['errors'] - assert_that(errors, has_length(2)) - assert_that(errors, contains_inanyorder( - "Missing Group.name", - "Missing Group.email" - )) - - -def test_create_group_without_members_or_admins(shared_zone_test_context): - """ - Tests that creating a group without members or admins fails - """ - client = shared_zone_test_context.ok_vinyldns_client - - new_group = { - 'name': 'some-group-name', - 'email': 'test@test.com', - 'description': 'this is a description' - } - errors = client.create_group(new_group, status=400)['errors'] - assert_that(errors, has_length(2)) - assert_that(errors, contains_inanyorder( - "Missing Group.members", - "Missing Group.admins" - )) - - -def test_create_group_adds_admins_as_members(shared_zone_test_context): - """ - Tests that creating a group adds admins as members - """ - client = shared_zone_test_context.ok_vinyldns_client - result = None - try: - - new_group = { - 'name': 'test-create-group-add-admins-as-members', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [], - 'admins': [{'id': 'ok'}] - } - result = client.create_group(new_group, status=200) - - assert_that(result['name'], is_(new_group['name'])) - assert_that(result['email'], is_(new_group['email'])) - assert_that(result['description'], is_(new_group['description'])) - assert_that(result['status'], is_('Active')) - assert_that(result['created'], not_none()) - assert_that(result['id'], not_none()) - assert_that(result['members'][0]['id'], is_('ok')) - assert_that(result['admins'][0]['id'], is_('ok')) - finally: - if result: - client.delete_group(result['id'], status=(200, 404)) - - -def test_create_group_duplicate(shared_zone_test_context): - """ - Tests that creating a group that has already been created fails - """ - client = shared_zone_test_context.ok_vinyldns_client - result = None - try: - new_group = { - 'name': 'test-create-group-duplicate', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}] - } - - result = client.create_group(new_group, status=200) - client.create_group(new_group, status=409) - - finally: - if result: - client.delete_group(result['id'], status=(200, 404)) - - -def test_create_group_no_members(shared_zone_test_context): - """ - Tests that creating a group that has no members adds current user as a member and an admin - """ - client = shared_zone_test_context.ok_vinyldns_client - result = None - - try: - new_group = { - 'name': 'test-create-group-no-members', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [], - 'admins': [] - } - - result = client.create_group(new_group, status=200) - assert_that(result['members'][0]['id'], is_('ok')) - assert_that(result['admins'][0]['id'], is_('ok')) - finally: - if result: - client.delete_group(result['id'], status=(200, 404)) - - -def test_create_group_adds_admins_to_member_list(shared_zone_test_context): - """ - Tests that creating a group adds admins to member list - """ - client = shared_zone_test_context.ok_vinyldns_client - result = None - - try: - new_group = { - 'name': 'test-create-group-add-admins-to-members', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'dummy'}] - } - - result = client.create_group(new_group, status=200) - assert_that(map(lambda x: x['id'], result['members']), contains('ok', 'dummy')) - assert_that(result['admins'][0]['id'], is_('dummy')) - finally: - if result: - client.delete_group(result['id'], status=(200, 404)) diff --git a/modules/api/functional_test/live_tests/membership/delete_group_test.py b/modules/api/functional_test/live_tests/membership/delete_group_test.py deleted file mode 100644 index 61609a690..000000000 --- a/modules/api/functional_test/live_tests/membership/delete_group_test.py +++ /dev/null @@ -1,143 +0,0 @@ -import pytest -import uuid -import json - -from hamcrest import * -from vinyldns_python import VinylDNSClient -from vinyldns_context import VinylDNSTestContext - - -def test_delete_group_success(shared_zone_test_context): - """ - Tests that we can delete a group that has been created - """ - - client = shared_zone_test_context.ok_vinyldns_client - saved_group = None - try: - new_group = { - 'name': 'test-delete-group-success', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [ { 'id': 'ok'} ], - 'admins': [ { 'id': 'ok'} ] - } - saved_group = client.create_group(new_group, status=200) - result = client.delete_group(saved_group['id'], status=200) - assert_that(result['status'], is_('Deleted')) - finally: - if result: - client.delete_group(saved_group['id'], status=(200,404)) - - -def test_delete_group_not_found(shared_zone_test_context): - """ - Tests that deleting a group that does not exist returns a 404 - """ - client = shared_zone_test_context.ok_vinyldns_client - client.delete_group('doesntexist', status=404) - - -def test_delete_group_that_is_already_deleted(shared_zone_test_context): - """ - Tests that deleting a group that is already deleted - """ - - client = shared_zone_test_context.ok_vinyldns_client - saved_group = None - - try: - new_group = { - 'name': 'test-delete-group-already', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [ { 'id': 'ok'} ], - 'admins': [ { 'id': 'ok'} ] - } - saved_group = client.create_group(new_group, status=200) - - client.delete_group(saved_group['id'], status=200) - client.delete_group(saved_group['id'], status=404) - - finally: - if saved_group: - client.delete_group(saved_group['id'], status=(200,404)) - - -def test_delete_admin_group(shared_zone_test_context): - """ - Tests that we cannot delete a group that is the admin of a zone - """ - client = shared_zone_test_context.ok_vinyldns_client - result_group = None - result_zone = None - - try: - #Create group - new_group = { - 'name': 'test-delete-group-already', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [ { 'id': 'ok'} ], - 'admins': [ { 'id': 'ok'} ] - } - - result_group = client.create_group(new_group, status=200) - print result_group - - #Create zone with that group ID as admin - zone = { - 'name': 'one-time.', - 'email': 'test@test.com', - 'adminGroupId': result_group['id'], - 'connection': { - 'name': 'vinyldns.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - }, - 'transferConnection': { - 'name': 'vinyldns.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - } - } - - result = client.create_zone(zone, status=202) - result_zone = result['zone'] - client.wait_until_zone_active(result[u'zone'][u'id']) - - client.delete_group(result_group['id'], status=400) - - #Delete zone - client.delete_zone(result_zone['id'], status=202) - client.wait_until_zone_deleted(result_zone['id']) - - #Should now be able to delete group - client.delete_group(result_group['id'], status=200) - finally: - if result_zone: - client.delete_zone(result_zone['id'], status=(202,404)) - if result_group: - client.delete_group(result_group['id'], status=(200,404)) - -def test_delete_group_not_authorized(shared_zone_test_context): - """ - Tests that only the admins can delete a zone - """ - ok_client = shared_zone_test_context.ok_vinyldns_client - not_admin_client = shared_zone_test_context.dummy_vinyldns_client - try: - new_group = { - 'name': 'test-delete-group-not-authorized', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [ { 'id': 'ok'} ], - 'admins': [ { 'id': 'ok'} ] - } - saved_group = ok_client.create_group(new_group, status=200) - not_admin_client.delete_group(saved_group['id'], status=403) - finally: - if saved_group: - ok_client.delete_group(saved_group['id'], status=(200,404)) diff --git a/modules/api/functional_test/live_tests/membership/get_group_changes_test.py b/modules/api/functional_test/live_tests/membership/get_group_changes_test.py deleted file mode 100644 index 656df2174..000000000 --- a/modules/api/functional_test/live_tests/membership/get_group_changes_test.py +++ /dev/null @@ -1,179 +0,0 @@ -import pytest - -from hamcrest import * - - -@pytest.fixture(scope="module") -def group_activity_context(request, shared_zone_test_context): - return { - 'created_group': shared_zone_test_context.group_activity_created, - 'updated_groups': shared_zone_test_context.group_activity_updated - } - - -def test_list_group_activity_start_from_success(group_activity_context, shared_zone_test_context): - """ - Test that we can list the changes starting from a given timestamp - """ - import json - - client = shared_zone_test_context.ok_vinyldns_client - created_group = group_activity_context['created_group'] - updated_groups = group_activity_context['updated_groups'] - - # updated groups holds all the groups just updated, not the original group that has no dummy user - # [0] = dummy000; [1] = dummy001; [2] = dummy002; [3] = dummy003, etc. - - # we grab 3 items, which when sorted by most recent will give the 3 most recent items - page_one = client.get_group_changes(created_group['id'], max_items=3, status=200) - - # our start from will align with the created on the 3rd change in the list - start_from_index = 2 - start_from = page_one['changes'][start_from_index]['created'] # start from a known good timestamp - - # now, we say give me all changes since the start_from, which should yield 8-7-6-5-4 - result = client.get_group_changes(created_group['id'], start_from=start_from, max_items=5, status=200) - - assert_that(result['changes'], has_length(5)) - assert_that(result['maxItems'], is_(5)) - assert_that(result['startFrom'], is_(start_from)) - assert_that(result['nextId'], is_not(none())) - - # we should have, in order, changes 8 7 6 5 4 - # changes that came in worked off... - # , 000, 001, 002, 003, 004, 005, 006 <-- 8th change - expected_start = 6 - for i in range(0, 5): - # The new group should be the later, the group it is replacing should be one back - assert_that(result['changes'][i]['newGroup'], is_(updated_groups[expected_start - i])) - assert_that(result['changes'][i]['oldGroup'], is_(updated_groups[expected_start - i - 1])) - - -def test_list_group_activity_start_from_fake_time(group_activity_context, shared_zone_test_context): - """ - Test that we can start from a fake time stamp - """ - - client = shared_zone_test_context.ok_vinyldns_client - created_group = group_activity_context['created_group'] - updated_groups = group_activity_context['updated_groups'] - start_from = '9999999999999' # start from a random timestamp far in the future - - result = client.get_group_changes(created_group['id'], start_from=start_from, max_items=5, status=200) - - # there are 10 updates, proceeded by 1 create - assert_that(result['changes'], has_length(5)) - assert_that(result['maxItems'], is_(5)) - assert_that(result['startFrom'], is_(start_from)) - assert_that(result['nextId'], is_not(none())) - - for i in range(0, 5): - assert_that(result['changes'][i]['newGroup'], is_(updated_groups[9 - i])) - assert_that(result['changes'][i]['oldGroup'], is_(updated_groups[9 - i - 1])) - - -def test_list_group_activity_max_item_success(group_activity_context, shared_zone_test_context): - """ - Test that we can set the max_items returned - """ - - client = shared_zone_test_context.ok_vinyldns_client - created_group = group_activity_context['created_group'] - updated_groups = group_activity_context['updated_groups'] - - result = client.get_group_changes(created_group['id'], max_items=4, status=200) - - # there are 200 updates, and 1 create - assert_that(result['changes'], has_length(4)) - assert_that(result['maxItems'], is_(4)) - assert_that(result, is_not(has_key('startFrom'))) - assert_that(result['nextId'], is_not(none())) - - for i in range(0, 4): - assert_that(result['changes'][i]['newGroup'], is_(updated_groups[9 - i])) - assert_that(result['changes'][i]['oldGroup'], is_(updated_groups[9 - i - 1])) - - -def test_list_group_activity_max_item_zero(group_activity_context, shared_zone_test_context): - """ - Test that max_item set to zero fails - """ - - client = shared_zone_test_context.ok_vinyldns_client - created_group = group_activity_context['created_group'] - client.get_group_changes(created_group['id'], max_items=0, status=400) - - -def test_list_group_activity_max_item_over_1000(group_activity_context, shared_zone_test_context): - """ - Test that when max_item is over 1000 fails - """ - - client = shared_zone_test_context.ok_vinyldns_client - created_group = group_activity_context['created_group'] - client.get_group_changes(created_group['id'], max_items=1001, status=400) - - -def test_get_group_changes_paging(group_activity_context, shared_zone_test_context): - """ - Test that we can page through multiple pages of group changes - """ - - client = shared_zone_test_context.ok_vinyldns_client - created_group = group_activity_context['created_group'] - updated_groups = group_activity_context['updated_groups'] - - page_one = client.get_group_changes(created_group['id'], max_items=5, status=200) - page_two = client.get_group_changes(created_group['id'], start_from=page_one['nextId'], max_items=5, status=200) - page_three = client.get_group_changes(created_group['id'], start_from=page_two['nextId'], max_items=5, status=200) - - assert_that(page_one['changes'], has_length(5)) - assert_that(page_one['maxItems'], is_(5)) - assert_that(page_one, is_not(has_key('startFrom'))) - assert_that(page_one['nextId'], is_not(none())) - - for i in range(0, 5): - assert_that(page_one['changes'][i]['newGroup'], is_(updated_groups[9 - i])) - assert_that(page_one['changes'][i]['oldGroup'], is_(updated_groups[9 - i - 1])) - - assert_that(page_two['changes'], has_length(5)) - assert_that(page_two['maxItems'], is_(5)) - assert_that(page_two['startFrom'], is_(page_one['nextId'])) - assert_that(page_two['nextId'], is_not(none())) - - # Do not compare the last item on the second page, as it is touches the original group - for i in range(5, 9): - assert_that(page_two['changes'][i - 5]['newGroup'], is_(updated_groups[9 - i])) - assert_that(page_two['changes'][i - 5]['oldGroup'], is_(updated_groups[9 - i - 1])) - - # Last page should be only the very last change - assert_that(page_three['changes'], has_length(1)) - assert_that(page_three['maxItems'], is_(5)) - assert_that(page_three['startFrom'], is_(page_two['nextId'])) - assert_that(page_three, is_not(has_key('nextId'))) - - assert_that(page_three['changes'][0]['newGroup'], is_(created_group)) - - -def test_get_group_changes_unauthed(shared_zone_test_context): - """ - Tests that we cant get group changes without access - """ - - client = shared_zone_test_context.ok_vinyldns_client - dummy_client = shared_zone_test_context.dummy_vinyldns_client - saved_group = None - try: - new_group = { - 'name': 'test-list-group-admins-unauthed-2', - 'email': 'test@test.com', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}] - } - saved_group = client.create_group(new_group, status=200) - - dummy_client.get_group_changes(saved_group['id'], status=403) - client.get_group_changes(saved_group['id'], status=200) - finally: - if saved_group: - client.delete_group(saved_group['id'], status=(200, 404)) diff --git a/modules/api/functional_test/live_tests/membership/get_group_test.py b/modules/api/functional_test/live_tests/membership/get_group_test.py deleted file mode 100644 index 8d51b9073..000000000 --- a/modules/api/functional_test/live_tests/membership/get_group_test.py +++ /dev/null @@ -1,93 +0,0 @@ -import pytest -import json - -from hamcrest import * -from vinyldns_python import VinylDNSClient - - -def test_get_group_success(shared_zone_test_context): - """ - Tests that we can get a group that has been created - """ - - client = shared_zone_test_context.ok_vinyldns_client - saved_group = None - try: - new_group = { - 'name': 'test-get-group-success', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [ { 'id': 'ok'} ], - 'admins': [ { 'id': 'ok'} ] - } - saved_group = client.create_group(new_group, status=200) - - group = client.get_group(saved_group['id'], status=200) - - assert_that(group['name'], is_(saved_group['name'])) - assert_that(group['email'], is_(saved_group['email'])) - assert_that(group['description'], is_(saved_group['description'])) - assert_that(group['status'], is_(saved_group['status'])) - assert_that(group['created'], is_(saved_group['created'])) - assert_that(group['id'], is_(saved_group['id'])) - finally: - if saved_group: - client.delete_group(saved_group['id'], status=(200,404)) - - -def test_get_group_not_found(shared_zone_test_context): - """ - Tests that getting a group that does not exist returns a 404 - """ - client = shared_zone_test_context.ok_vinyldns_client - client.get_group('doesntexist', status=404) - - -def test_get_deleted_group(shared_zone_test_context): - """ - Tests getting a group that was already deleted - """ - - client = shared_zone_test_context.ok_vinyldns_client - saved_group = None - - try: - new_group = { - 'name': 'test-get-deleted-group', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [ { 'id': 'ok'} ], - 'admins': [ { 'id': 'ok'} ] - } - saved_group = client.create_group(new_group, status=200) - - client.delete_group(saved_group['id'], status=200) - client.get_group(saved_group['id'], status=404) - finally: - if saved_group: - client.delete_group(saved_group['id'], status=(200,404)) - - -def test_get_group_unauthed(shared_zone_test_context): - """ - Tests that we cant get a group were not in - """ - - client = shared_zone_test_context.ok_vinyldns_client - dummy_client = shared_zone_test_context.dummy_vinyldns_client - saved_group = None - try: - new_group = { - 'name': 'test-get-group-unauthed', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [ { 'id': 'ok'} ], - 'admins': [ { 'id': 'ok'} ] - } - saved_group = client.create_group(new_group, status=200) - - dummy_client.get_group(saved_group['id'], status=403) - client.get_group(saved_group['id'], status=200) - finally: - if saved_group: - client.delete_group(saved_group['id'], status=(200,404)) diff --git a/modules/api/functional_test/live_tests/membership/list_group_admins_test.py b/modules/api/functional_test/live_tests/membership/list_group_admins_test.py deleted file mode 100644 index deeb598fb..000000000 --- a/modules/api/functional_test/live_tests/membership/list_group_admins_test.py +++ /dev/null @@ -1,80 +0,0 @@ - -import pytest -import json - -from hamcrest import * - -from vinyldns_python import VinylDNSClient - - -def test_list_group_admins_success(shared_zone_test_context): - """ - Test that we can list all the admins of a given group - """ - - client = shared_zone_test_context.ok_vinyldns_client - saved_group = None - try: - new_group = { - 'name': 'test-list-group-admins-success', - 'email': 'test@test.com', - 'members': [ { 'id': 'ok'} ], - 'admins': [ { 'id': 'ok'}, { 'id': 'dummy'} ] - } - saved_group = client.create_group(new_group, status=200) - - admin_user_1_id = 'ok' - admin_user_2_id = 'dummy' - - result = client.get_group(saved_group['id'], status=200) - - assert_that(result['admins'], has_length(2)) - assert_that([admin_user_1_id, admin_user_2_id], has_item(result['admins'][0]['id'])) - assert_that([admin_user_1_id, admin_user_2_id], has_item(result['admins'][1]['id'])) - - result = client.list_group_admins(saved_group['id'], status=200) - - result = sorted(result['admins'], key=lambda user: user['userName']) - assert_that(result, has_length(2)) - assert_that(result[0]['userName'], is_('dummy')) - assert_that(result[0]['id'], is_('dummy')) - assert_that(result[0]['created'], not_none()) - assert_that(result[1]['userName'], is_('ok')) - assert_that(result[1]['id'], is_('ok')) - assert_that(result[1]['created'], not_none()) - finally: - if saved_group: - client.delete_group(saved_group['id'], status=(200,404)) - - -def test_list_group_admins_group_not_found(shared_zone_test_context): - """ - Test that listing the admins of a non-existent group fails - """ - - client = shared_zone_test_context.ok_vinyldns_client - client.list_group_admins('doesntexist', status=404) - - -def test_list_group_admins_unauthed(shared_zone_test_context): - """ - Tests that we cant list admins without access - """ - - client = shared_zone_test_context.ok_vinyldns_client - dummy_client = shared_zone_test_context.dummy_vinyldns_client - saved_group = None - try: - new_group = { - 'name': 'test-list-group-admins-unauthed', - 'email': 'test@test.com', - 'members': [ { 'id': 'ok'} ], - 'admins': [ { 'id': 'ok'} ] - } - saved_group = client.create_group(new_group, status=200) - - dummy_client.list_group_admins(saved_group['id'], status=403) - client.list_group_admins(saved_group['id'], status=200) - finally: - if saved_group: - client.delete_group(saved_group['id'], status=(200,404)) diff --git a/modules/api/functional_test/live_tests/membership/list_group_members_test.py b/modules/api/functional_test/live_tests/membership/list_group_members_test.py deleted file mode 100644 index 59eceac9b..000000000 --- a/modules/api/functional_test/live_tests/membership/list_group_members_test.py +++ /dev/null @@ -1,577 +0,0 @@ -import pytest -import json - -from hamcrest import * - -from vinyldns_python import VinylDNSClient - - -def test_list_group_members_success(shared_zone_test_context): - """ - Test that we can list all the members of a group - """ - - client = shared_zone_test_context.ok_vinyldns_client - saved_group = None - - try: - new_group = { - 'name': 'test-list-group-members-success', - 'email': 'test@test.com', - 'members': [ { 'id': 'ok'}, { 'id': 'dummy' } ], - 'admins': [ { 'id': 'ok'} ] - } - - members = sorted(['dummy', 'ok']) - saved_group = client.create_group(new_group, status=200) - result = client.get_group(saved_group['id'], status=200) - assert_that(result['members'], has_length(len(members))) - - result_member_ids = map(lambda member: member['id'], result['members']) - for id in members: - assert_that(result_member_ids, has_item(id)) - - result = client.list_members_group(saved_group['id'], status=200) - result = sorted(result['members'], key=lambda user: user['id']) - - assert_that(result, has_length(len(members))) - dummy = result[0] - assert_that(dummy['id'], is_('dummy')) - assert_that(dummy['userName'], is_('dummy')) - assert_that(dummy['isAdmin'], is_(False)) - assert_that(dummy['lockStatus'], is_("Unlocked")) - assert_that(dummy, is_not(has_key('firstName'))) - assert_that(dummy, is_not(has_key('lastName'))) - assert_that(dummy, is_not(has_key('email'))) - assert_that(dummy['created'], is_not(none())) - - ok = result[1] - assert_that(ok['id'], is_('ok')) - assert_that(ok['userName'], is_('ok')) - assert_that(ok['isAdmin'], is_(True)) - assert_that(ok['firstName'], is_('ok')) - assert_that(ok['lastName'], is_('ok')) - assert_that(ok['email'], is_('test@test.com')) - assert_that(ok['created'], is_not(none())) - assert_that(ok['lockStatus'], is_("Unlocked")) - - finally: - if saved_group: - client.delete_group(saved_group['id'], status=(200,404)) - - -def test_list_group_members_not_found(shared_zone_test_context): - """ - Tests that we can not list the members of a non-existent group - """ - - client = shared_zone_test_context.ok_vinyldns_client - - client.list_members_group('not_found', status=404) - - -def test_list_group_members_start_from(shared_zone_test_context): - """ - Test that we can list the members starting from a given user - """ - - client = shared_zone_test_context.ok_vinyldns_client - saved_group = None - try: - members = [] - for runner in range(0, 200): - id = "dummy{0:0>3}".format(runner) - members.append({ 'id': id }) - members = sorted(members) - - new_group = { - 'name': 'test-list-group-members-start-from', - 'email': 'test@test.com', - 'members': members, - 'admins': [ { 'id': 'ok'} ] - } - - saved_group = client.create_group(new_group, status=200) - result = client.get_group(saved_group['id'], status=200) - - # members has one more because admins are added as members - assert_that(result['members'], has_length(len(members) + 1)) - assert_that(result['members'], has_item({'id': 'ok'})) - result_member_ids = map(lambda member: member['id'], result['members']) - for user in members: - assert_that(result_member_ids, has_item(user['id'])) - - result = client.list_members_group(saved_group['id'], start_from='dummy050', status=200) - - group_members = sorted(result['members'], key=lambda user: user['id']) - - assert_that(result['startFrom'], is_('dummy050')) - assert_that(result['nextId'], is_('dummy150')) - - assert_that(group_members, has_length(100)) - for i in range(0, len(group_members)-1): - dummy = group_members[i] - id = "dummy{0:0>3}".format(i+51) #starts from dummy051 - user_name = "name-"+id - assert_that(dummy['id'], is_(id)) - assert_that(dummy['userName'], is_(user_name)) - assert_that(dummy['isAdmin'], is_(False)) - assert_that(dummy, is_not(has_key('firstName'))) - assert_that(dummy, is_not(has_key('lastName'))) - assert_that(dummy, is_not(has_key('email'))) - assert_that(dummy['created'], is_not(none())) - assert_that(dummy['lockStatus'], is_("Unlocked")) - finally: - if saved_group: - client.delete_group(saved_group['id'], status=(200,404)) - - -def test_list_group_members_start_from_non_user(shared_zone_test_context): - """ - Test that we can list the members starting from a non existent username - """ - - client = shared_zone_test_context.ok_vinyldns_client - saved_group = None - try: - members = [] - for runner in range(0, 200): - id = "dummy{0:0>3}".format(runner) - members.append({ 'id': id }) - members = sorted(members) - - new_group = { - 'name': 'test-list-group-members-start-from-nonexistent', - 'email': 'test@test.com', - 'members': members, - 'admins': [ { 'id': 'ok'} ] - } - - saved_group = client.create_group(new_group, status=200) - result = client.get_group(saved_group['id'], status=200) - - # members has one more because admins are added as members - assert_that(result['members'], has_length(len(members) + 1)) - result_member_ids = map(lambda member: member['id'], result['members']) - assert_that(result_member_ids, has_item('ok')) - for user in members: - assert_that(result_member_ids, has_item(user['id'])) - - result = client.list_members_group(saved_group['id'], start_from='abc', status=200) - - group_members = sorted(result['members'], key=lambda user: user['id']) - - assert_that(result['startFrom'], is_('abc')) - assert_that(result['nextId'], is_('dummy099')) - - assert_that(group_members, has_length(100)) - for i in range(0, len(group_members)-1): - dummy = group_members[i] - id = "dummy{0:0>3}".format(i) - user_name = "name-"+id - assert_that(dummy['id'], is_(id)) - assert_that(dummy['userName'], is_(user_name)) - assert_that(dummy['isAdmin'], is_(False)) - assert_that(dummy, is_not(has_key('firstName'))) - assert_that(dummy, is_not(has_key('lastName'))) - assert_that(dummy, is_not(has_key('email'))) - assert_that(dummy['created'], is_not(none())) - assert_that(dummy['lockStatus'], is_("Unlocked")) - finally: - if saved_group: - client.delete_group(saved_group['id'], status=(200,404)) - - -def test_list_group_members_max_item(shared_zone_test_context): - """ - Test that we can chose the number of items to list - """ - - client = shared_zone_test_context.ok_vinyldns_client - saved_group = None - try: - members = [] - for runner in range(0, 200): - id = "dummy{0:0>3}".format(runner) - members.append({ 'id': id }) - members = sorted(members) - - new_group = { - 'name': 'test-list-group-members-max-items', - 'email': 'test@test.com', - 'members': members, - 'admins': [ { 'id': 'ok'} ] - } - - saved_group = client.create_group(new_group, status=200) - result = client.get_group(saved_group['id'], status=200) - - # members has one more because admins are added as members - assert_that(result['members'], has_length(len(members) + 1)) - result_member_ids = map(lambda member: member['id'], result['members']) - assert_that(result_member_ids, has_item('ok')) - for user in members: - assert_that(result_member_ids, has_item(user['id'])) - - result = client.list_members_group(saved_group['id'], max_items=10, status=200) - - group_members = sorted(result['members'], key=lambda user: user['id']) - - assert_that(result['nextId'], is_('dummy009')) - assert_that(result['maxItems'], is_(10)) - - assert_that(group_members, has_length(10)) - for i in range(0, len(group_members)-1): - dummy = group_members[i] - id = "dummy{0:0>3}".format(i) - user_name = "name-"+id - assert_that(dummy['id'], is_(id)) - assert_that(dummy['userName'], is_(user_name)) - assert_that(dummy['isAdmin'], is_(False)) - assert_that(dummy, is_not(has_key('firstName'))) - assert_that(dummy, is_not(has_key('lastName'))) - assert_that(dummy, is_not(has_key('email'))) - assert_that(dummy['created'], is_not(none())) - assert_that(dummy['lockStatus'], is_("Unlocked")) - finally: - if saved_group: - client.delete_group(saved_group['id'], status=(200,404)) - - -def test_list_group_members_max_item_default(shared_zone_test_context): - """ - Test that the default for max_item is 100 items - """ - - client = shared_zone_test_context.ok_vinyldns_client - saved_group = None - try: - members = [] - for runner in range(0, 200): - id = "dummy{0:0>3}".format(runner) - members.append({ 'id': id }) - members = sorted(members) - - new_group = { - 'name': 'test-list-group-members-max-items-default', - 'email': 'test@test.com', - 'members': members, - 'admins': [ { 'id': 'ok'} ] - } - - saved_group = client.create_group(new_group, status=200) - result = client.get_group(saved_group['id'], status=200) - - # members has one more because admins are added as members - assert_that(result['members'], has_length(len(members) + 1)) - result_member_ids = map(lambda member: member['id'], result['members']) - assert_that(result_member_ids, has_item('ok')) - for user in members: - assert_that(result_member_ids, has_item(user['id'])) - - result = client.list_members_group(saved_group['id'], status=200) - - group_members = sorted(result['members'], key=lambda user: user['id']) - - assert_that(result['nextId'], is_('dummy099')) - - assert_that(group_members, has_length(100)) - for i in range(0, len(group_members)-1): - dummy = group_members[i] - id = "dummy{0:0>3}".format(i) - user_name = "name-"+id - assert_that(dummy['id'], is_(id)) - assert_that(dummy['userName'], is_(user_name)) - assert_that(dummy['isAdmin'], is_(False)) - assert_that(dummy, is_not(has_key('firstName'))) - assert_that(dummy, is_not(has_key('lastName'))) - assert_that(dummy, is_not(has_key('email'))) - assert_that(dummy['created'], is_not(none())) - assert_that(dummy['lockStatus'], is_("Unlocked")) - finally: - if saved_group: - client.delete_group(saved_group['id'], status=(200,404)) - - -def test_list_group_members_max_item_zero(shared_zone_test_context): - """ - Test that the call fails when max_item is 0 - """ - - client = shared_zone_test_context.ok_vinyldns_client - saved_group = None - try: - members = [] - for runner in range(0, 200): - id = "dummy{0:0>3}".format(runner) - members.append({ 'id': id }) - members = sorted(members) - - new_group = { - 'name': 'test-list-group-members-max-items-zero', - 'email': 'test@test.com', - 'members': members, - 'admins': [ { 'id': 'ok'} ] - } - - saved_group = client.create_group(new_group, status=200) - result = client.get_group(saved_group['id'], status=200) - - # members has one more because admins are added as members - assert_that(result['members'], has_length(len(members) + 1)) - result_member_ids = map(lambda member: member['id'], result['members']) - assert_that(result_member_ids, has_item('ok')) - for user in members: - assert_that(result_member_ids, has_item(user['id'])) - - client.list_members_group(saved_group['id'], max_items=0, status=400) - finally: - if saved_group: - client.delete_group(saved_group['id'], status=(200,404)) - - -def test_list_group_members_max_item_over_1000(shared_zone_test_context): - """ - Test that the call fails when max_item is over 1000 - """ - - client = shared_zone_test_context.ok_vinyldns_client - saved_group = None - try: - members = [] - for runner in range(0, 200): - id = "dummy{0:0>3}".format(runner) - members.append({ 'id': id }) - members = sorted(members) - - new_group = { - 'name': 'test-list-group-members-max-items-over-limit', - 'email': 'test@test.com', - 'members': members, - 'admins': [ { 'id': 'ok'} ] - } - - saved_group = client.create_group(new_group, status=200) - result = client.get_group(saved_group['id'], status=200) - - # members has one more because admins are added as members - assert_that(result['members'], has_length(len(members) + 1)) - result_member_ids = map(lambda member: member['id'], result['members']) - assert_that(result_member_ids, has_item('ok')) - for user in members: - assert_that(result_member_ids, has_item(user['id'])) - - client.list_members_group(saved_group['id'], max_items=1001, status=400) - finally: - if saved_group: - client.delete_group(saved_group['id'], status=(200,404)) - - -def test_list_group_members_next_id_correct(shared_zone_test_context): - """ - Test that the correct next_id is returned - """ - - client = shared_zone_test_context.ok_vinyldns_client - saved_group = None - try: - members = [] - for runner in range(0, 200): - id = "dummy{0:0>3}".format(runner) - members.append({ 'id': id }) - members = sorted(members) - - new_group = { - 'name': 'test-list-group-members-next-id', - 'email': 'test@test.com', - 'members': members, - 'admins': [ { 'id': 'ok'} ] - } - - saved_group = client.create_group(new_group, status=200) - result = client.get_group(saved_group['id'], status=200) - - # members has one more because admins are added as members - assert_that(result['members'], has_length(len(members) + 1)) - result_member_ids = map(lambda member: member['id'], result['members']) - assert_that(result_member_ids, has_item('ok')) - for user in members: - assert_that(result_member_ids, has_item(user['id'])) - - result = client.list_members_group(saved_group['id'], status=200) - - group_members = sorted(result['members'], key=lambda user: user['id']) - - assert_that(result['nextId'], is_('dummy099')) - - assert_that(group_members, has_length(100)) - for i in range(0, len(group_members)-1): - dummy = group_members[i] - id = "dummy{0:0>3}".format(i) - user_name = "name-"+id - assert_that(dummy['id'], is_(id)) - assert_that(dummy['userName'], is_(user_name)) - assert_that(dummy['isAdmin'], is_(False)) - assert_that(dummy, is_not(has_key('firstName'))) - assert_that(dummy, is_not(has_key('lastName'))) - assert_that(dummy, is_not(has_key('email'))) - assert_that(dummy['created'], is_not(none())) - assert_that(dummy['lockStatus'], is_("Unlocked")) - finally: - if saved_group: - client.delete_group(saved_group['id'], status=(200,404)) - - -def test_list_group_members_next_id_exhausted(shared_zone_test_context): - """ - Test that the next_id is null when the list is exhausted - """ - - client = shared_zone_test_context.ok_vinyldns_client - saved_group = None - try: - members = [] - for runner in range(0, 5): - id = "dummy{0:0>3}".format(runner) - members.append({ 'id': id }) - members = sorted(members) - - new_group = { - 'name': 'test-list-group-members-next-id-exhausted', - 'email': 'test@test.com', - 'members': members, - 'admins': [ { 'id': 'ok'} ] - } - - saved_group = client.create_group(new_group, status=200) - result = client.get_group(saved_group['id'], status=200) - - # members has one more because admins are added as members - assert_that(result['members'], has_length(len(members) + 1)) - result_member_ids = map(lambda member: member['id'], result['members']) - assert_that(result_member_ids, has_item('ok')) - for user in members: - assert_that(result_member_ids, has_item(user['id'])) - - result = client.list_members_group(saved_group['id'], status=200) - - group_members = sorted(result['members'], key=lambda user: user['id']) - - assert_that(result, is_not(has_key('nextId'))) - - assert_that(group_members, has_length(6)) # add one more for the admin - for i in range(0, len(group_members)-1): - dummy = group_members[i] - id = "dummy{0:0>3}".format(i) - user_name = "name-"+id - assert_that(dummy['id'], is_(id)) - assert_that(dummy['userName'], is_(user_name)) - assert_that(dummy, is_not(has_key('firstName'))) - assert_that(dummy, is_not(has_key('lastName'))) - assert_that(dummy, is_not(has_key('email'))) - assert_that(dummy['created'], is_not(none())) - assert_that(dummy['lockStatus'], is_("Unlocked")) - finally: - if saved_group: - client.delete_group(saved_group['id'], status=(200,404)) - - -def test_list_group_members_next_id_exhausted_two_pages(shared_zone_test_context): - """ - Test that the next_id is null when the list is exhausted over 2 pages - """ - - client = shared_zone_test_context.ok_vinyldns_client - saved_group = None - try: - members = [] - for runner in range(0, 19): - id = "dummy{0:0>3}".format(runner) - members.append({ 'id': id }) - members = sorted(members) - - new_group = { - 'name': 'test-list-group-members-next-id-exhausted-two-pages', - 'email': 'test@test.com', - 'members': members, - 'admins': [ { 'id': 'ok'} ] - } - - saved_group = client.create_group(new_group, status=200) - result = client.get_group(saved_group['id'], status=200) - - # members has one more because admins are added as members - assert_that(result['members'], has_length(len(members) + 1)) - result_member_ids = map(lambda member: member['id'], result['members']) - assert_that(result_member_ids, has_item('ok')) - for user in members: - assert_that(result_member_ids, has_item(user['id'])) - - first_page = client.list_members_group(saved_group['id'], max_items=10, status=200) - - group_members = sorted(first_page['members'], key=lambda user: user['id']) - - assert_that(first_page['nextId'], is_('dummy009')) - assert_that(first_page['maxItems'], is_(10)) - - assert_that(group_members, has_length(10)) - for i in range(0, len(group_members)-1): - dummy = group_members[i] - id = "dummy{0:0>3}".format(i) - user_name = "name-"+id - assert_that(dummy['id'], is_(id)) - assert_that(dummy['userName'], is_(user_name)) - assert_that(dummy, is_not(has_key('firstName'))) - assert_that(dummy, is_not(has_key('lastName'))) - assert_that(dummy, is_not(has_key('email'))) - assert_that(dummy['created'], is_not(none())) - assert_that(dummy['lockStatus'], is_("Unlocked")) - - second_page = client.list_members_group(saved_group['id'], - start_from=first_page['nextId'], - max_items=10, - status=200) - - group_members = sorted(second_page['members'], key=lambda user: user['id']) - - assert_that(second_page, is_not(has_key('nextId'))) - assert_that(second_page['maxItems'], is_(10)) - - assert_that(group_members, has_length(10)) - for i in range(0, len(group_members)-1): - dummy = group_members[i] - id = "dummy{0:0>3}".format(i+10) - user_name = "name-"+id - assert_that(dummy['id'], is_(id)) - assert_that(dummy['userName'], is_(user_name)) - assert_that(dummy, is_not(has_key('firstName'))) - assert_that(dummy, is_not(has_key('lastName'))) - assert_that(dummy, is_not(has_key('email'))) - assert_that(dummy['created'], is_not(none())) - finally: - if saved_group: - client.delete_group(saved_group['id'], status=(200,404)) - - -def test_list_group_members_unauthed(shared_zone_test_context): - """ - Tests that we cant list members without access - """ - - client = shared_zone_test_context.ok_vinyldns_client - dummy_client = shared_zone_test_context.dummy_vinyldns_client - saved_group = None - try: - new_group = { - 'name': 'test-list-group-members-unauthed', - 'email': 'test@test.com', - 'members': [ { 'id': 'ok'} ], - 'admins': [ { 'id': 'ok'} ] - } - saved_group = client.create_group(new_group, status=200) - - dummy_client.list_members_group(saved_group['id'], status=403) - client.list_members_group(saved_group['id'], status=200) - finally: - if saved_group: - client.delete_group(saved_group['id'], status=(200,404)) diff --git a/modules/api/functional_test/live_tests/membership/list_my_groups_test.py b/modules/api/functional_test/live_tests/membership/list_my_groups_test.py deleted file mode 100644 index 9a2cfb354..000000000 --- a/modules/api/functional_test/live_tests/membership/list_my_groups_test.py +++ /dev/null @@ -1,171 +0,0 @@ -import pytest -from hamcrest import * -from utils import * - - -@pytest.fixture(scope="module") -def list_my_groups_context(request, shared_zone_test_context): - return shared_zone_test_context.list_groups_context - - -def test_list_my_groups_no_parameters(list_my_groups_context): - """ - Test that we can get all the groups where a user is a member - """ - - results = list_my_groups_context.client.list_my_groups(status=200) - - assert_that(results, has_length(3)) # 3 fields - - assert_that(results['groups'], has_length(50)) - assert_that(results, is_not(has_key('groupNameFilter'))) - assert_that(results, is_not(has_key('startFrom'))) - assert_that(results, is_not(has_key('nextId'))) - assert_that(results['maxItems'], is_(100)) - - results['groups'] = sorted(results['groups'], key=lambda x: x['name']) - - for i in range(0, 50): - assert_that(results['groups'][i]['name'], is_("test-list-my-groups-{0:0>3}".format(i))) - - -def test_get_my_groups_using_old_account_auth(list_my_groups_context): - """ - Test passing in an account will return an empty set - """ - results = list_my_groups_context.client.list_my_groups(status=200) - assert_that(results, has_length(3)) - assert_that(results, is_not(has_key('groupNameFilter'))) - assert_that(results, is_not(has_key('startFrom'))) - assert_that(results, is_not(has_key('nextId'))) - assert_that(results['maxItems'], is_(100)) - - -def test_list_my_groups_max_items(list_my_groups_context): - """ - Tests that when maxItem is set, only return #maxItems items - """ - results = list_my_groups_context.client.list_my_groups(max_items=5, status=200) - - assert_that(results, has_length(4)) # 4 fields - - assert_that(results, has_key('groups')) - assert_that(results, is_not(has_key('groupNameFilter'))) - assert_that(results, is_not(has_key('startFrom'))) - assert_that(results, has_key('nextId')) - assert_that(results['maxItems'], is_(5)) - - -def test_list_my_groups_paging(list_my_groups_context): - """ - Tests that we can return all items by paging - """ - results = list_my_groups_context.client.list_my_groups(max_items=20, status=200) - - assert_that(results, has_length(4)) # 4 fields - assert_that(results, has_key('groups')) - assert_that(results, is_not(has_key('groupNameFilter'))) - assert_that(results, is_not(has_key('startFrom'))) - assert_that(results, has_key('nextId')) - assert_that(results['maxItems'], is_(20)) - - while 'nextId' in results: - prev = results - results = list_my_groups_context.client.list_my_groups(max_items=20, start_from=results['nextId'], status=200) - - if 'nextId' in results: - assert_that(results, has_length(5)) # 5 fields - assert_that(results, has_key('groups')) - assert_that(results, is_not(has_key('groupNameFilter'))) - assert_that(results['startFrom'], is_(prev['nextId'])) - assert_that(results, has_key('nextId')) - assert_that(results['maxItems'], is_(20)) - - else: - assert_that(results, has_length(4)) # 4 fields - assert_that(results, has_key('groups')) - assert_that(results, is_not(has_key('groupNameFilter'))) - assert_that(results['startFrom'], is_(prev['nextId'])) - assert_that(results, is_not(has_key('nextId'))) - assert_that(results['maxItems'], is_(20)) - - -def test_list_my_groups_filter_matches(list_my_groups_context): - """ - Tests that only matched groups are returned - """ - results = list_my_groups_context.client.list_my_groups(group_name_filter="test-list-my-groups-01", status=200) - - assert_that(results, has_length(4)) # 4 fields - - assert_that(results['groups'], has_length(10)) - assert_that(results['groupNameFilter'], is_('test-list-my-groups-01')) - assert_that(results, is_not(has_key('startFrom'))) - assert_that(results, is_not(has_key('nextId'))) - assert_that(results['maxItems'], is_(100)) - - results['groups'] = sorted(results['groups'], key=lambda x: x['name']) - - for i in range(0, 10): - assert_that(results['groups'][i]['name'], is_("test-list-my-groups-{0:0>3}".format(i + 10))) - - -def test_list_my_groups_no_deleted(list_my_groups_context): - """ - Tests that no deleted groups are returned - """ - results = list_my_groups_context.client.list_my_groups(max_items=100, status=200) - - assert_that(results, has_key('groups')) - for g in results['groups']: - assert_that(g['status'], is_not('Deleted')) - - while 'nextId' in results: - results = client.list_my_groups(max_items=20, group_name_filter="test-list-my-groups-", - start_from=results['nextId'], status=200) - - assert_that(results, has_key('groups')) - for g in results['groups']: - assert_that(g['status'], is_not('Deleted')) - - -def test_list_my_groups_with_ignore_access_true(list_my_groups_context): - """ - Test that we can get all the groups whether a user is a member or not - """ - - results = list_my_groups_context.client.list_my_groups(ignore_access=True, status=200) - - assert_that(len(results['groups']), greater_than(50)) - assert_that(results['maxItems'], is_(100)) - assert_that(results['ignoreAccess'], is_(True)) - - my_results = list_my_groups_context.client.list_my_groups(status=200) - my_results['groups'] = sorted(my_results['groups'], key=lambda x: x['name']) - - for i in range(0, 50): - assert_that(my_results['groups'][i]['name'], is_("test-list-my-groups-{0:0>3}".format(i))) - - -def test_list_my_groups_as_support_user(list_my_groups_context): - """ - Test that we can get all the groups as a support user, even without ignore_access - """ - - results = list_my_groups_context.support_user_client.list_my_groups(status=200) - - assert_that(len(results['groups']), greater_than(50)) - assert_that(results['maxItems'], is_(100)) - assert_that(results['ignoreAccess'], is_(False)) - - -def test_list_my_groups_as_support_user_with_ignore_access_true(list_my_groups_context): - """ - Test that we can get all the groups as a support user - """ - - results = list_my_groups_context.support_user_client.list_my_groups(ignore_access=True, status=200) - - assert_that(len(results['groups']), greater_than(50)) - assert_that(results['maxItems'], is_(100)) - assert_that(results['ignoreAccess'], is_(True)) diff --git a/modules/api/functional_test/live_tests/membership/update_group_test.py b/modules/api/functional_test/live_tests/membership/update_group_test.py deleted file mode 100644 index 4f6aa649c..000000000 --- a/modules/api/functional_test/live_tests/membership/update_group_test.py +++ /dev/null @@ -1,639 +0,0 @@ -import time - -from hamcrest import * - - -def test_update_group_success(shared_zone_test_context): - """ - Tests that we can update a group that has been created - """ - - client = shared_zone_test_context.ok_vinyldns_client - saved_group = None - - try: - new_group = { - 'name': 'test-update-group-success', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}] - } - saved_group = client.create_group(new_group, status=200) - - group = client.get_group(saved_group['id'], status=200) - - assert_that(group['name'], is_(saved_group['name'])) - assert_that(group['email'], is_(saved_group['email'])) - assert_that(group['description'], is_(saved_group['description'])) - assert_that(group['status'], is_(saved_group['status'])) - assert_that(group['created'], is_(saved_group['created'])) - assert_that(group['id'], is_(saved_group['id'])) - - time.sleep(1) # sleep to ensure that update doesnt change created time - - update_group = { - 'id': group['id'], - 'name': 'updated-name', - 'email': 'update@test.com', - 'description': 'this is a new description', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}] - } - group = client.update_group(update_group['id'], update_group, status=200) - - assert_that(group['name'], is_(update_group['name'])) - assert_that(group['email'], is_(update_group['email'])) - assert_that(group['description'], is_(update_group['description'])) - assert_that(group['status'], is_(saved_group['status'])) - assert_that(group['created'], is_(saved_group['created'])) - assert_that(group['id'], is_(saved_group['id'])) - assert_that(group['members'][0]['id'], is_('ok')) - assert_that(group['admins'][0]['id'], is_('ok')) - finally: - if saved_group: - client.delete_group(saved_group['id'], status=(200, 404)) - - -def test_update_group_without_name(shared_zone_test_context): - """ - Tests that updating a group without a name fails - """ - client = shared_zone_test_context.ok_vinyldns_client - result = None - try: - new_group = { - 'name': 'test-update-without-name', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}] - } - result = client.create_group(new_group, status=200) - assert_that(result['name'], is_(new_group['name'])) - assert_that(result['email'], is_(new_group['email'])) - - update_group = { - 'id': result['id'], - 'email': 'update@test.com', - 'description': 'this is a new description' - } - - errors = client.update_group(update_group['id'], update_group, status=400)['errors'] - assert_that(errors[0], is_("Missing Group.name")) - finally: - if result: - client.delete_group(result['id'], status=(200, 404)) - - -def test_update_group_without_email(shared_zone_test_context): - """ - Tests that updating a group without an email fails - """ - client = shared_zone_test_context.ok_vinyldns_client - result = None - try: - new_group = { - 'name': 'test-update-without-email', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}] - } - result = client.create_group(new_group, status=200) - assert_that(result['name'], is_(new_group['name'])) - assert_that(result['email'], is_(new_group['email'])) - - update_group = { - 'id': result['id'], - 'name': 'without-email', - 'description': 'this is a description', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}] - } - errors = client.update_group(update_group['id'], update_group, status=400)['errors'] - assert_that(errors[0], is_("Missing Group.email")) - finally: - if result: - client.delete_group(result['id'], status=(200, 404)) - - -def test_updating_group_without_name_or_email(shared_zone_test_context): - """ - Tests that updating a group without name or an email fails - """ - client = shared_zone_test_context.ok_vinyldns_client - result = None - try: - new_group = { - 'name': 'test-update-without-name-and-email', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}] - } - result = client.create_group(new_group, status=200) - assert_that(result['name'], is_(new_group['name'])) - assert_that(result['email'], is_(new_group['email'])) - - update_group = { - 'id': result['id'], - 'description': 'this is a description', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}] - } - errors = client.update_group(update_group['id'], update_group, status=400)['errors'] - assert_that(errors, has_length(2)) - assert_that(errors, contains_inanyorder( - "Missing Group.name", - "Missing Group.email" - )) - finally: - if result: - client.delete_group(result['id'], status=(200, 404)) - - -def test_updating_group_without_members_or_admins(shared_zone_test_context): - """ - Tests that updating a group without members or admins fails - """ - client = shared_zone_test_context.ok_vinyldns_client - result = None - - try: - new_group = { - 'name': 'test-update-without-members', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}] - } - result = client.create_group(new_group, status=200) - assert_that(result['name'], is_(new_group['name'])) - assert_that(result['email'], is_(new_group['email'])) - - update_group = { - 'id': result['id'], - 'name': 'test-update-without-members', - 'email': 'test@test.com', - 'description': 'this is a description', - } - errors = client.update_group(update_group['id'], update_group, status=400)['errors'] - assert_that(errors, has_length(2)) - assert_that(errors, contains_inanyorder( - "Missing Group.members", - "Missing Group.admins" - )) - finally: - if result: - client.delete_group(result['id'], status=(200, 404)) - - -def test_update_group_adds_admins_as_members(shared_zone_test_context): - """ - Tests that when we add an admin to a group the admin is also a member - """ - - client = shared_zone_test_context.ok_vinyldns_client - saved_group = None - - try: - new_group = { - 'name': 'test-update-group-admins-as-members', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}] - } - saved_group = client.create_group(new_group, status=200) - - group = client.get_group(saved_group['id'], status=200) - - assert_that(group['name'], is_(saved_group['name'])) - assert_that(group['email'], is_(saved_group['email'])) - assert_that(group['description'], is_(saved_group['description'])) - assert_that(group['status'], is_(saved_group['status'])) - assert_that(group['created'], is_(saved_group['created'])) - assert_that(group['id'], is_(saved_group['id'])) - - update_group = { - 'id': group['id'], - 'name': 'test-update-group-admins-as-members', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}, {'id': 'dummy'}] - } - group = client.update_group(update_group['id'], update_group, status=200) - - assert_that(group['members'], has_length(2)) - assert_that(['ok', 'dummy'], has_item(group['members'][0]['id'])) - assert_that(['ok', 'dummy'], has_item(group['members'][1]['id'])) - assert_that(group['admins'], has_length(2)) - assert_that(['ok', 'dummy'], has_item(group['admins'][0]['id'])) - assert_that(['ok', 'dummy'], has_item(group['admins'][1]['id'])) - finally: - if saved_group: - client.delete_group(saved_group['id'], status=(200, 404)) - - -def test_update_group_conflict(shared_zone_test_context): - """ - Tests that we can not update a groups name to a name already in use - """ - - client = shared_zone_test_context.ok_vinyldns_client - result = None - conflict_group = None - try: - new_group = { - 'name': 'test_update_group_conflict', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}] - } - conflict_group = client.create_group(new_group, status=200) - assert_that(conflict_group['name'], is_(new_group['name'])) - - other_group = { - 'name': 'change_me', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}] - } - result = client.create_group(other_group, status=200) - assert_that(result['name'], is_(other_group['name'])) - - # change the name of the other_group to the first group (conflict) - update_group = { - 'id': result['id'], - 'name': 'test_update_group_conflict', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}] - } - client.update_group(update_group['id'], update_group, status=409) - finally: - if result: - client.delete_group(result['id'], status=(200, 404)) - if conflict_group: - client.delete_group(conflict_group['id'], status=(200, 404)) - - -def test_update_group_not_found(shared_zone_test_context): - """ - Tests that we can not update a group that has not been created - """ - - client = shared_zone_test_context.ok_vinyldns_client - - update_group = { - 'id': 'test-update-group-not-found', - 'name': 'test-update-group-not-found', - 'email': 'update@test.com', - 'description': 'this is a new description', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}] - } - client.update_group(update_group['id'], update_group, status=404) - - -def test_update_group_deleted(shared_zone_test_context): - """ - Tests that we can not update a group that has been deleted - """ - - client = shared_zone_test_context.ok_vinyldns_client - saved_group = None - - try: - new_group = { - 'name': 'test-update-group-deleted', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}] - } - saved_group = client.create_group(new_group, status=200) - client.delete_group(saved_group['id'], status=200) - - update_group = { - 'id': saved_group['id'], - 'name': 'test-update-group-deleted-updated', - 'email': 'update@test.com', - 'description': 'this is a new description', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}] - } - client.update_group(update_group['id'], update_group, status=404) - finally: - if saved_group: - client.delete_group(saved_group['id'], status=(200, 404)) - - -def test_add_member_via_update_group_success(shared_zone_test_context): - """ - Tests that we can add a member to a group via update successfully - """ - - client = shared_zone_test_context.ok_vinyldns_client - saved_group = None - try: - new_group = { - 'name': 'test-add-member-to-via-update-group-success', - 'email': 'test@test.com', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}] - } - saved_group = client.create_group(new_group, status=200) - - updated_group = { - 'id': saved_group['id'], - 'name': 'test-add-member-to-via-update-group-success', - 'email': 'test@test.com', - 'members': [{'id': 'ok'}, {'id': 'dummy'}], - 'admins': [{'id': 'ok'}] - } - - saved_group = client.update_group(updated_group['id'], updated_group, status=200) - expected_members = ['ok', 'dummy'] - assert_that(saved_group['members'], has_length(2)) - assert_that(expected_members, has_item(saved_group['members'][0]['id'])) - assert_that(expected_members, has_item(saved_group['members'][1]['id'])) - finally: - if saved_group: - client.delete_group(saved_group['id'], status=(200, 404)) - - -def test_add_member_to_group_twice_via_update_group(shared_zone_test_context): - """ - Tests that we can add a member to a group twice successfully via update group - """ - - client = shared_zone_test_context.ok_vinyldns_client - saved_group = None - try: - new_group = { - 'name': 'test-add-member-to-group-twice-success-via-update-group', - 'email': 'test@test.com', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}] - } - saved_group = client.create_group(new_group, status=200) - - updated_group = { - 'id': saved_group['id'], - 'name': 'test-add-member-to-group-twice-success-via-update-group', - 'email': 'test@test.com', - 'members': [{'id': 'ok'}, {'id': 'dummy'}], - 'admins': [{'id': 'ok'}] - } - - saved_group = client.update_group(updated_group['id'], updated_group, status=200) - saved_group = client.update_group(updated_group['id'], updated_group, status=200) - expected_members = ['ok', 'dummy'] - assert_that(saved_group['members'], has_length(2)) - assert_that(expected_members, has_item(saved_group['members'][0]['id'])) - assert_that(expected_members, has_item(saved_group['members'][1]['id'])) - finally: - if saved_group: - client.delete_group(saved_group['id'], status=(200, 404)) - - -def test_add_not_found_member_to_group_via_update_group(shared_zone_test_context): - """ - Tests that we can not add a non-existent member to a group via update group - """ - - client = shared_zone_test_context.ok_vinyldns_client - saved_group = None - - try: - new_group = { - 'name': 'test-add-not-found-member-to-group-via-update-group', - 'email': 'test@test.com', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}] - } - saved_group = client.create_group(new_group, status=200) - result = client.get_group(saved_group['id'], status=200) - assert_that(result['members'], has_length(1)) - - updated_group = { - 'id': saved_group['id'], - 'name': 'test-add-not-found-member-to-group-via-update-group', - 'email': 'test@test.com', - 'members': [{'id': 'ok'}, {'id': 'not_found'}], - 'admins': [{'id': 'ok'}] - } - - client.update_group(updated_group['id'], updated_group, status=404) - finally: - if saved_group: - client.delete_group(saved_group['id'], status=(200, 404)) - - -def test_remove_member_via_update_group_success(shared_zone_test_context): - """ - Tests that we can remove a member via update group successfully - """ - - client = shared_zone_test_context.ok_vinyldns_client - saved_group = None - - try: - new_group = { - 'name': 'test-remove-member-via-update-group-success', - 'email': 'test@test.com', - 'members': [{'id': 'ok'}, {'id': 'dummy'}], - 'admins': [{'id': 'ok'}] - } - saved_group = client.create_group(new_group, status=200) - assert_that(saved_group['members'], has_length(2)) - - updated_group = { - 'id': saved_group['id'], - 'name': 'test-remove-member-via-update-group-success', - 'email': 'test@test.com', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}] - } - saved_group = client.update_group(updated_group['id'], updated_group, status=200) - - assert_that(saved_group['members'], has_length(1)) - assert_that(saved_group['members'][0]['id'], is_('ok')) - finally: - if saved_group: - client.delete_group(saved_group['id'], status=(200, 404)) - - -def test_remove_member_and_admin(shared_zone_test_context): - """ - Tests that if we remove a member who is an admin, the admin is also removed - """ - client = shared_zone_test_context.ok_vinyldns_client - saved_group = None - - try: - new_group = { - 'name': 'test-remove-member-and-admin', - 'email': 'test@test.com', - 'members': [{'id': 'ok'}, {'id': 'dummy'}], - 'admins': [{'id': 'ok'}, {'id': 'dummy'}] - } - saved_group = client.create_group(new_group, status=200) - assert_that(saved_group['members'], has_length(2)) - - updated_group = { - 'id': saved_group['id'], - 'name': 'test-remove-member-and-admin', - 'email': 'test@test.com', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}] - } - saved_group = client.update_group(updated_group['id'], updated_group, status=200) - - assert_that(saved_group['members'], has_length(1)) - assert_that(saved_group['members'][0]['id'], is_('ok')) - assert_that(saved_group['admins'], has_length(1)) - assert_that(saved_group['admins'][0]['id'], is_('ok')) - finally: - if saved_group: - client.delete_group(saved_group['id'], status=(200, 404)) - - -def test_remove_member_but_not_admin_keeps_member(shared_zone_test_context): - """ - Tests that if we remove a member but do not remove the admin, the admin remains a member - """ - client = shared_zone_test_context.ok_vinyldns_client - saved_group = None - - try: - new_group = { - 'name': 'test-remove-member-not-admin-keeps-member', - 'email': 'test@test.com', - 'members': [{'id': 'ok'}, {'id': 'dummy'}], - 'admins': [{'id': 'ok'}, {'id': 'dummy'}] - } - saved_group = client.create_group(new_group, status=200) - assert_that(saved_group['members'], has_length(2)) - - updated_group = { - 'id': saved_group['id'], - 'name': 'test-remove-member-not-admin-keeps-member', - 'email': 'test@test.com', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}, {'id': 'dummy'}] - } - saved_group = client.update_group(updated_group['id'], updated_group, status=200) - - expected_members = ['ok', 'dummy'] - assert_that(saved_group['members'], has_length(2)) - assert_that(expected_members, has_item(saved_group['members'][0]['id'])) - assert_that(expected_members, has_item(saved_group['members'][1]['id'])) - assert_that(expected_members, has_item(saved_group['admins'][0]['id'])) - assert_that(expected_members, has_item(saved_group['admins'][1]['id'])) - finally: - if saved_group: - client.delete_group(saved_group['id'], status=(200, 404)) - - -def test_remove_admin_keeps_member(shared_zone_test_context): - """ - Tests that if we remove a member from admins, the member still remains part of the group - """ - client = shared_zone_test_context.ok_vinyldns_client - saved_group = None - - try: - new_group = { - 'name': 'test-remove-admin-keeps-member', - 'email': 'test@test.com', - 'members': [{'id': 'ok'}, {'id': 'dummy'}], - 'admins': [{'id': 'ok'}, {'id': 'dummy'}] - } - saved_group = client.create_group(new_group, status=200) - assert_that(saved_group['members'], has_length(2)) - - updated_group = { - 'id': saved_group['id'], - 'name': 'test-remove-admin-keeps-member', - 'email': 'test@test.com', - 'members': [{'id': 'ok'}, {'id': 'dummy'}], - 'admins': [{'id': 'ok'}] - } - saved_group = client.update_group(updated_group['id'], updated_group, status=200) - - expected_members = ['ok', 'dummy'] - assert_that(saved_group['members'], has_length(2)) - assert_that(expected_members, has_item(saved_group['members'][0]['id'])) - assert_that(expected_members, has_item(saved_group['members'][1]['id'])) - - assert_that(saved_group['admins'], has_length(1)) - assert_that(saved_group['admins'][0]['id'], is_('ok')) - finally: - if saved_group: - client.delete_group(saved_group['id'], status=(200, 404)) - - -def test_update_group_not_authorized(shared_zone_test_context): - """ - Tests that only the admins can update a zone - """ - ok_client = shared_zone_test_context.ok_vinyldns_client - not_admin_client = shared_zone_test_context.dummy_vinyldns_client - try: - new_group = { - 'name': 'test-update-group-not-authorized', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}] - } - saved_group = ok_client.create_group(new_group, status=200) - - update_group = { - 'id': saved_group['id'], - 'name': 'updated-name', - 'email': 'update@test.com', - 'description': 'this is a new description', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}] - } - not_admin_client.update_group(update_group['id'], update_group, status=403) - finally: - if saved_group: - ok_client.delete_group(saved_group['id'], status=(200, 404)) - - -def test_update_group_adds_admins_to_member_list(shared_zone_test_context): - """ - Tests that updating a group adds admins to member list - """ - ok_client = shared_zone_test_context.ok_vinyldns_client - dummy_client = shared_zone_test_context.dummy_vinyldns_client - result = None - - try: - new_group = { - 'name': 'test-update-group-add-admins-to-members', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [{'id': 'ok'}], - 'admins': [{'id': 'ok'}] - } - - saved_group = ok_client.create_group(new_group, status=200) - - saved_group['admins'] = [{'id': 'dummy'}] - result = ok_client.update_group(saved_group['id'], saved_group, status=200) - - assert_that(map(lambda x: x['id'], result['members']), contains('ok', 'dummy')) - assert_that(result['admins'][0]['id'], is_('dummy')) - finally: - if result: - dummy_client.delete_group(result['id'], status=(200, 404)) diff --git a/modules/api/functional_test/live_tests/production_verify_test.py b/modules/api/functional_test/live_tests/production_verify_test.py deleted file mode 100644 index 87cd57a64..000000000 --- a/modules/api/functional_test/live_tests/production_verify_test.py +++ /dev/null @@ -1,70 +0,0 @@ -import pytest -import sys -import dns.query -import dns.tsigkeyring -import dns.update - -from utils import * -from hamcrest import * -from vinyldns_python import VinylDNSClient -from test_data import TestData -from dns.resolver import * - - -def test_verify_production(shared_zone_test_context): - """ - Test that production works. This test sets up the shared context, which creates a lot of groups and zones - and then really just creates a single recordset and delete it. - """ - client = shared_zone_test_context.ok_vinyldns_client - result_rs = None - try: - new_rs = { - 'zoneId': shared_zone_test_context.ok_zone['id'], - 'name': 'test_create_recordset_with_dns_verify', - 'type': 'A', - 'ttl': 100, - 'records': [ - { - 'address': '10.1.1.1' - }, - { - 'address': '10.2.2.2' - } - ] - } - print "\r\nCreating recordset in zone " + str(shared_zone_test_context.ok_zone) + "\r\n" - result = client.create_recordset(new_rs, status=202) - print str(result) - - assert_that(result['changeType'], is_('Create')) - assert_that(result['status'], is_('Pending')) - assert_that(result['created'], is_not(none())) - assert_that(result['userId'], is_not(none())) - - result_rs = result['recordSet'] - result_rs = client.wait_until_recordset_change_status(result, 'Complete')['recordSet'] - print "\r\n\r\n!!!recordset is active! Verifying..." - - verify_recordset(result_rs, new_rs) - print "\r\n\r\n!!!recordset verified..." - - records = [x['address'] for x in result_rs['records']] - assert_that(records, has_length(2)) - assert_that('10.1.1.1', is_in(records)) - assert_that('10.2.2.2', is_in(records)) - - print "\r\n\r\n!!!verifying recordset in dns backend" - answers = dns_resolve(shared_zone_test_context.ok_zone, result_rs['name'], result_rs['type']) - rdata_strings = rdata(answers) - - assert_that(answers, has_length(2)) - assert_that('10.1.1.1', is_in(rdata_strings)) - assert_that('10.2.2.2', is_in(rdata_strings)) - finally: - if result_rs: - try: - delete_result = client.delete_recordset(result_rs['zoneId'], result_rs['id'], status=202) - client.wait_until_recordset_deleted(delete_result['zoneId'], delete_result['id']) - except: - pass \ No newline at end of file diff --git a/modules/api/functional_test/live_tests/shared_zone_test_context.py b/modules/api/functional_test/live_tests/shared_zone_test_context.py deleted file mode 100644 index a69c0da18..000000000 --- a/modules/api/functional_test/live_tests/shared_zone_test_context.py +++ /dev/null @@ -1,618 +0,0 @@ -import time -from hamcrest import * -from utils import * -from vinyldns_context import VinylDNSTestContext -from vinyldns_python import VinylDNSClient - -from list_batch_summaries_test_context import ListBatchChangeSummariesTestContext -from list_groups_test_context import ListGroupsTestContext -from list_recordsets_test_context import ListRecordSetsTestContext -from list_zones_test_context import ListZonesTestContext - - -class SharedZoneTestContext(object): - """ - Creates multiple zones to test authorization / access to shared zones across users - """ - - def __init__(self, fixture_file=None): - self.ok_vinyldns_client = VinylDNSClient(VinylDNSTestContext.vinyldns_url, 'okAccessKey', 'okSecretKey') - self.dummy_vinyldns_client = VinylDNSClient(VinylDNSTestContext.vinyldns_url, 'dummyAccessKey', - 'dummySecretKey') - self.shared_zone_vinyldns_client = VinylDNSClient(VinylDNSTestContext.vinyldns_url, 'sharedZoneUserAccessKey', - 'sharedZoneUserSecretKey') - self.support_user_client = VinylDNSClient(VinylDNSTestContext.vinyldns_url, 'supportUserAccessKey', - 'supportUserSecretKey') - self.unassociated_client = VinylDNSClient(VinylDNSTestContext.vinyldns_url, 'listGroupAccessKey', - 'listGroupSecretKey') - self.test_user_client = VinylDNSClient(VinylDNSTestContext.vinyldns_url, 'testUserAccessKey', - 'testUserSecretKey') - self.history_client = VinylDNSClient(VinylDNSTestContext.vinyldns_url, 'history-key', 'history-secret') - self.list_zones = ListZonesTestContext() - self.list_zones_client = self.list_zones.client - self.list_records_context = ListRecordSetsTestContext() - self.list_groups_context = ListGroupsTestContext() - self.list_batch_summaries_context = None - - self.dummy_group = None - self.ok_group = None - self.shared_record_group = None - self.history_group = None - self.group_activity_created = None - self.group_activity_updated = None - - # if we are using an existing fixture, load the fixture file and pull all of our data from there - if fixture_file: - print "\r\n!!! FIXTURE FILE IS SET !!!" - self.load_fixture_file(fixture_file) - else: - print "\r\n!!! FIXTURE FILE NOT SET, BUILDING FIXTURE !!!" - # No fixture file, so we have to build everything ourselves - self.tear_down() # ensures that the environment is clean before starting - try: - ok_group = { - 'name': 'ok-group', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [{'id': 'ok'}, {'id': 'support-user-id'}], - 'admins': [{'id': 'ok'}] - } - - self.ok_group = self.ok_vinyldns_client.create_group(ok_group, status=200) - # in theory this shouldn't be needed, but getting 'user is not in group' errors on zone creation - self.confirm_member_in_group(self.ok_vinyldns_client, self.ok_group) - - dummy_group = { - 'name': 'dummy-group', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [{'id': 'dummy'}], - 'admins': [{'id': 'dummy'}] - } - self.dummy_group = self.dummy_vinyldns_client.create_group(dummy_group, status=200) - # in theory this shouldn't be needed, but getting 'user is not in group' errors on zone creation - self.confirm_member_in_group(self.dummy_vinyldns_client, self.dummy_group) - - shared_record_group = { - 'name': 'record-ownergroup', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [{'id': 'sharedZoneUser'}, {'id': 'ok'}], - 'admins': [{'id': 'sharedZoneUser'}, {'id': 'ok'}] - } - self.shared_record_group = self.ok_vinyldns_client.create_group(shared_record_group, status=200) - - history_group = { - 'name': 'history-group', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [{'id': 'history-id'}], - 'admins': [{'id': 'history-id'}] - } - self.history_group = self.history_client.create_group(history_group, status=200) - self.confirm_member_in_group(self.history_client, self.history_group) - - history_zone_change = self.history_client.create_zone( - { - 'name': 'system-test-history.', - 'email': 'i.changed.this.1.times@history-test.com', - 'shared': False, - 'adminGroupId': self.history_group['id'], - 'isTest': True, - 'connection': { - 'name': 'vinyldns.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - }, - 'transferConnection': { - 'name': 'vinyldns.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - } - }, status=202) - self.history_zone = history_zone_change['zone'] - - ok_zone_change = self.ok_vinyldns_client.create_zone( - { - 'name': 'ok.', - 'email': 'test@test.com', - 'shared': False, - 'adminGroupId': self.ok_group['id'], - 'isTest': True, - 'connection': { - 'name': 'ok.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - }, - 'transferConnection': { - 'name': 'ok.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - } - }, status=202) - self.ok_zone = ok_zone_change['zone'] - - dummy_zone_change = self.dummy_vinyldns_client.create_zone( - { - 'name': 'dummy.', - 'email': 'test@test.com', - 'shared': False, - 'adminGroupId': self.dummy_group['id'], - 'isTest': True, - 'connection': { - 'name': 'dummy.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - }, - 'transferConnection': { - 'name': 'dummy.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - } - }, status=202) - self.dummy_zone = dummy_zone_change['zone'] - - ip6_reverse_zone_change = self.ok_vinyldns_client.create_zone( - { - 'name': '1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa.', - 'email': 'test@test.com', - 'shared': False, - 'adminGroupId': self.ok_group['id'], - 'isTest': True, - 'connection': { - 'name': 'ip6.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - }, - 'transferConnection': { - 'name': 'ip6.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - } - }, status=202 - ) - self.ip6_reverse_zone = ip6_reverse_zone_change['zone'] - - ip6_16_nibble_zone_change = self.ok_vinyldns_client.create_zone( - { - 'name': '0.0.0.1.1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa.', - 'email': 'test@test.com', - 'shared': False, - 'adminGroupId': self.ok_group['id'], - 'isTest': True, - 'backendId': 'func-test-backend' - }, status=202 - ) - self.ip6_16_nibble_zone = ip6_16_nibble_zone_change['zone'] - - ip4_reverse_zone_change = self.ok_vinyldns_client.create_zone( - { - 'name': '10.10.in-addr.arpa.', - 'email': 'test@test.com', - 'shared': False, - 'adminGroupId': self.ok_group['id'], - 'isTest': True, - 'connection': { - 'name': 'ip4.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - }, - 'transferConnection': { - 'name': 'ip4.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - } - }, status=202 - ) - self.ip4_reverse_zone = ip4_reverse_zone_change['zone'] - - self.classless_base_zone_json = { - 'name': '2.0.192.in-addr.arpa.', - 'email': 'test@test.com', - 'shared': False, - 'adminGroupId': self.ok_group['id'], - 'isTest': True, - 'connection': { - 'name': 'classless-base.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - }, - 'transferConnection': { - 'name': 'classless-base.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - } - } - - classless_base_zone_change = self.ok_vinyldns_client.create_zone( - self.classless_base_zone_json, status=202 - ) - self.classless_base_zone = classless_base_zone_change['zone'] - - classless_zone_delegation_change = self.ok_vinyldns_client.create_zone( - { - 'name': '192/30.2.0.192.in-addr.arpa.', - 'email': 'test@test.com', - 'shared': False, - 'adminGroupId': self.ok_group['id'], - 'isTest': True, - 'connection': { - 'name': 'classless.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - }, - 'transferConnection': { - 'name': 'classless.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - } - }, status=202 - ) - self.classless_zone_delegation_zone = classless_zone_delegation_change['zone'] - - system_test_zone_change = self.ok_vinyldns_client.create_zone( - { - 'name': 'system-test.', - 'email': 'test@test.com', - 'shared': False, - 'adminGroupId': self.ok_group['id'], - 'isTest': True, - 'connection': { - 'name': 'system-test.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - }, - 'transferConnection': { - 'name': 'system-test.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - } - }, status=202 - ) - self.system_test_zone = system_test_zone_change['zone'] - - # parent zone gives access to the dummy user, dummy user cannot manage ns records - parent_zone_change = self.ok_vinyldns_client.create_zone( - { - 'name': 'parent.com.', - 'email': 'test@test.com', - 'shared': False, - 'adminGroupId': self.ok_group['id'], - 'isTest': True, - 'acl': { - 'rules': [ - { - 'accessLevel': 'Delete', - 'description': 'some_test_rule', - 'userId': 'dummy' - } - ] - }, - 'connection': { - 'name': 'parent.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - }, - 'transferConnection': { - 'name': 'parent.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - } - }, status=202) - self.parent_zone = parent_zone_change['zone'] - - # mimicking the spec example - ds_zone_change = self.ok_vinyldns_client.create_zone( - { - 'name': 'example.com.', - 'email': 'test@test.com', - 'shared': False, - 'adminGroupId': self.ok_group['id'], - 'isTest': True, - 'connection': { - 'name': 'example.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - }, - 'transferConnection': { - 'name': 'example.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - } - }, status=202) - self.ds_zone = ds_zone_change['zone'] - - # zone with name configured for manual review - requires_review_zone_change = self.ok_vinyldns_client.create_zone( - { - 'name': 'zone.requires.review.', - 'email': 'test@test.com', - 'shared': False, - 'adminGroupId': self.ok_group['id'], - 'isTest': True, - 'backendId': 'func-test-backend' - }, status=202) - self.requires_review_zone = requires_review_zone_change['zone'] - - get_shared_zones = self.shared_zone_vinyldns_client.list_zones(status=200)['zones'] - shared_zone = [zone for zone in get_shared_zones if zone['name'] == "shared."] - non_test_shared_zone = [zone for zone in get_shared_zones if zone['name'] == "non.test.shared."] - - shared_zone_change = self.set_up_shared_zone(shared_zone[0]['id']) - self.shared_zone = shared_zone_change['zone'] - - non_test_shared_zone_change = self.set_up_shared_zone(non_test_shared_zone[0]['id']) - self.non_test_shared_zone = non_test_shared_zone_change['zone'] - - # wait until our zones are created - self.ok_vinyldns_client.wait_until_zone_active(system_test_zone_change[u'zone'][u'id']) - self.ok_vinyldns_client.wait_until_zone_active(ok_zone_change[u'zone'][u'id']) - self.dummy_vinyldns_client.wait_until_zone_active(dummy_zone_change[u'zone'][u'id']) - self.ok_vinyldns_client.wait_until_zone_active(ip6_reverse_zone_change[u'zone'][u'id']) - self.ok_vinyldns_client.wait_until_zone_active(ip6_16_nibble_zone_change[u'zone'][u'id']) - self.ok_vinyldns_client.wait_until_zone_active(ip4_reverse_zone_change[u'zone'][u'id']) - self.ok_vinyldns_client.wait_until_zone_active(classless_base_zone_change[u'zone'][u'id']) - self.ok_vinyldns_client.wait_until_zone_active(classless_zone_delegation_change[u'zone'][u'id']) - self.ok_vinyldns_client.wait_until_zone_active(system_test_zone_change[u'zone'][u'id']) - self.ok_vinyldns_client.wait_until_zone_active(parent_zone_change[u'zone'][u'id']) - self.ok_vinyldns_client.wait_until_zone_active(ds_zone_change[u'zone'][u'id']) - self.ok_vinyldns_client.wait_until_zone_active(requires_review_zone_change[u'zone'][u'id']) - self.history_client.wait_until_zone_active(history_zone_change[u'zone'][u'id']) - self.shared_zone_vinyldns_client.wait_until_zone_change_status_synced(shared_zone_change) - - shared_sync_change = self.shared_zone_vinyldns_client.sync_zone(self.shared_zone['id']) - self.shared_zone_vinyldns_client.wait_until_zone_change_status_synced(non_test_shared_zone_change) - non_test_shared_sync_change = self.shared_zone_vinyldns_client.sync_zone( - self.non_test_shared_zone['id']) - - self.shared_zone_vinyldns_client.wait_until_zone_change_status_synced(shared_sync_change) - self.shared_zone_vinyldns_client.wait_until_zone_change_status_synced(non_test_shared_sync_change) - - # validate all in there - zones = self.dummy_vinyldns_client.list_zones()['zones'] - assert_that(len(zones), is_(2)) - zones = self.ok_vinyldns_client.list_zones()['zones'] - assert_that(len(zones), is_(10)) - zones = self.shared_zone_vinyldns_client.list_zones()['zones'] - assert_that(len(zones), is_(2)) - - # initialize history - self.init_history() - - # initalize group activity - self.init_group_activity() - - # initialize list zones, only do this when constructing the whole! - self.list_zones.build() - - # note: there are no state to load, the tests only need the client - self.list_zones_client = self.list_zones.client - - # build the list of records; note: we do need to save the test records - self.list_records_context.build() - - # build the list of groups - self.list_groups_context.build() - - except: - # teardown if there was any issue in setup - try: - self.tear_down() - except: - pass - raise - - # We need to load somethings AFTER we are all initialized, do that here - self.list_batch_summaries_context = ListBatchChangeSummariesTestContext(self) - - def init_history(self): - from test_data import TestData - import copy - # Initialize the zone history - # change the zone nine times to we have update events in zone change history, - # ten total changes including creation - for i in range(2, 11): - zone_update = copy.deepcopy(self.history_zone) - zone_update['connection']['key'] = VinylDNSTestContext.dns_key - zone_update['transferConnection']['key'] = VinylDNSTestContext.dns_key - zone_update['email'] = 'i.changed.this.{0}.times@history-test.com'.format(i) - zone_update = self.history_client.update_zone(zone_update, status=202)['zone'] - - # create some record sets - test_a = TestData.A.copy() - test_a['zoneId'] = self.history_zone['id'] - test_aaaa = TestData.AAAA.copy() - test_aaaa['zoneId'] = self.history_zone['id'] - test_cname = TestData.CNAME.copy() - test_cname['zoneId'] = self.history_zone['id'] - - a_record = self.history_client.create_recordset(test_a, status=202)['recordSet'] - aaaa_record = self.history_client.create_recordset(test_aaaa, status=202)['recordSet'] - cname_record = self.history_client.create_recordset(test_cname, status=202)['recordSet'] - - # wait here for all the record sets to be created - self.history_client.wait_until_recordset_exists(a_record['zoneId'], a_record['id']) - self.history_client.wait_until_recordset_exists(aaaa_record['zoneId'], aaaa_record['id']) - self.history_client.wait_until_recordset_exists(cname_record['zoneId'], cname_record['id']) - - # update the record sets - a_record_update = copy.deepcopy(a_record) - a_record_update['ttl'] += 100 - a_record_update['records'][0]['address'] = '9.9.9.9' - a_change = self.history_client.update_recordset(a_record_update, status=202) - - aaaa_record_update = copy.deepcopy(aaaa_record) - aaaa_record_update['ttl'] += 100 - aaaa_record_update['records'][0]['address'] = '2003:db8:0:0:0:0:0:4' - aaaa_change = self.history_client.update_recordset(aaaa_record_update, status=202) - - cname_record_update = copy.deepcopy(cname_record) - cname_record_update['ttl'] += 100 - cname_record_update['records'][0]['cname'] = 'changed-cname.' - cname_change = self.history_client.update_recordset(cname_record_update, status=202) - - self.history_client.wait_until_recordset_change_status(a_change, 'Complete') - self.history_client.wait_until_recordset_change_status(aaaa_change, 'Complete') - self.history_client.wait_until_recordset_change_status(cname_change, 'Complete') - - # delete the recordsets - self.history_client.delete_recordset(a_record['zoneId'], a_record['id']) - self.history_client.delete_recordset(aaaa_record['zoneId'], aaaa_record['id']) - self.history_client.delete_recordset(cname_record['zoneId'], cname_record['id']) - - self.history_client.wait_until_recordset_deleted(a_record['zoneId'], a_record['id']) - self.history_client.wait_until_recordset_deleted(aaaa_record['zoneId'], aaaa_record['id']) - self.history_client.wait_until_recordset_deleted(cname_record['zoneId'], cname_record['id']) - - def init_group_activity(self): - client = self.ok_vinyldns_client - created_group = None - - group_name = 'test-list-group-activity-max-item-success' - - # cleanup existing group if it's already in there - groups = client.list_all_my_groups() - existing = [grp for grp in groups if grp['name'] == group_name] - for grp in existing: - client.delete_group(grp['id'], status=200) - - members = [{'id': 'ok'}] - new_group = { - 'name': group_name, - 'email': 'test@test.com', - 'members': members, - 'admins': [{'id': 'ok'}] - } - created_group = client.create_group(new_group, status=200) - - update_groups = [] - updated_groups = [] - # each update changes the member - for runner in range(0, 10): - id = "dummy{0:0>3}".format(runner) - members = [{'id': id}] - update_groups.append({ - 'id': created_group['id'], - 'name': group_name, - 'email': 'test@test.com', - 'members': members, - 'admins': [{'id': 'ok'}] - }) - updated_groups.append(client.update_group(update_groups[runner]['id'], update_groups[runner], status=200)) - - self.group_activity_created = created_group - self.group_activity_updated = updated_groups - - def load_fixture_file(self, fixture_file): - # The fixture file contains all of the groups and zones, - # The format is simply json where groups = [] and zones = [] - import json - with open(fixture_file) as json_file: - data = json.load(json_file) - self.ok_group = data['ok_group'] - self.ok_zone = data['ok_zone'] - self.dummy_group = data['dummy_group'] - self.shared_record_group = data['shared_record_group'] - self.dummy_zone = data['dummy_zone'] - self.ip6_reverse_zone = data['ip6_reverse_zone'] - self.ip6_16_nibble_zone = data['ip6_16_nibble_zone'] - self.ip4_reverse_zone = data['ip4_reverse_zone'] - self.classless_base_zone = data['classless_base_zone'] - self.classless_zone_delegation_zone = data['classless_zone_delegation_zone'] - self.system_test_zone = data['system_test_zone'] - self.parent_zone = data['parent_zone'] - self.ds_zone = data['ds_zone'] - self.requires_review_zone = data['requires_review_zone'] - self.shared_zone = data['shared_zone'] - self.non_test_shared_zone = data['non_test_shared_zone'] - self.history_zone = data['history_zone'] - self.history_group = data['history_group'] - self.group_activity_created = data['group_activity_created'] - self.group_activity_updated = data['group_activity_updated'] - - def out_fixture_file(self, fixture_file): - print "\r\n!!! PRINTING OUT FIXTURE FILE !!!" - import json - # output the fixture file, be sure to be in sync with the load_fixture_file - data = {'ok_group': self.ok_group, 'ok_zone': self.ok_zone, 'dummy_group': self.dummy_group, - 'shared_record_group': self.shared_record_group, 'dummy_zone': self.dummy_zone, - 'ip6_reverse_zone': self.ip6_reverse_zone, 'ip6_16_nibble_zone': self.ip6_16_nibble_zone, - 'ip4_reverse_zone': self.ip4_reverse_zone, 'classless_base_zone': self.classless_base_zone, - 'classless_zone_delegation_zone': self.classless_zone_delegation_zone, - 'system_test_zone': self.system_test_zone, 'parent_zone': self.parent_zone, 'ds_zone': self.ds_zone, - 'requires_review_zone': self.requires_review_zone, 'shared_zone': self.shared_zone, - 'non_test_shared_zone': self.non_test_shared_zone, 'history_zone': self.history_zone, - 'history_group': self.history_group, 'group_activity_created': self.group_activity_created, - 'group_activity_updated': self.group_activity_updated} - with open(fixture_file, 'w') as out_file: - json.dump(data, out_file) - - def set_up_shared_zone(self, zone_id): - # shared zones are created through test data loader, but needs connection info added here to use - get_shared_zone = self.shared_zone_vinyldns_client.get_zone(zone_id) - shared_zone = get_shared_zone['zone'] - - connection_info = { - 'name': 'shared.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - } - - shared_zone['connection'] = connection_info - shared_zone['transferConnection'] = connection_info - - return self.shared_zone_vinyldns_client.update_zone(shared_zone, status=202) - - def tear_down(self): - """ - The ok_vinyldns_client is a zone admin on _all_ the zones. - - We shouldn't have to do any checks now, as zone admins have full rights to all zones, including - deleting all records (even in the old shared model) - """ - self.list_zones.tear_down() - self.list_records_context.tear_down() - - if self.list_batch_summaries_context: - self.list_batch_summaries_context.tear_down(self) - - if self.list_groups_context: - self.list_groups_context.tear_down() - - clear_zones(self.dummy_vinyldns_client) - clear_zones(self.ok_vinyldns_client) - clear_zones(self.history_client) - clear_groups(self.dummy_vinyldns_client, "global-acl-group-id") - clear_groups(self.ok_vinyldns_client, "global-acl-group-id") - clear_groups(self.history_client) - - @staticmethod - def confirm_member_in_group(client, group): - retries = 2 - success = group in client.list_all_my_groups(status=200) - while retries >= 0 and not success: - success = group in client.list_all_my_groups(status=200) - time.sleep(.05) - retries -= 1 - assert_that(success, is_(True)) diff --git a/modules/api/functional_test/live_tests/test_data.py b/modules/api/functional_test/live_tests/test_data.py deleted file mode 100644 index 3069d9f2c..000000000 --- a/modules/api/functional_test/live_tests/test_data.py +++ /dev/null @@ -1,124 +0,0 @@ -class TestData: - A = { - 'zoneId': None, - 'name': 'test-create-a-ok', - 'type': 'A', - 'ttl': 100, - 'account': 'foo', - 'records': [ - { - 'address': '10.1.1.1' - }, - { - 'address': '10.2.2.2' - } - ] - } - AAAA = { - 'zoneId': None, - 'name': 'test-create-aaaa-ok', - 'type': 'AAAA', - 'ttl': 100, - 'account': 'foo', - 'records': [ - { - 'address': '2001:db8:0:0:0:0:0:3' - }, - { - 'address': '2002:db8:0:0:0:0:0:3' - } - ] - } - CNAME = { - 'zoneId': None, - 'name': 'test-create-cname-ok', - 'type': 'CNAME', - 'ttl': 100, - 'account': 'foo', - 'records': [ - { - 'cname': 'cname.' - } - ] - } - MX = { - 'zoneId': None, - 'name': 'test-create-mx-ok', - 'type': 'MX', - 'ttl': 100, - 'account': 'foo', - 'records': [ - { - 'preference': 100, - 'exchange': 'exchange.' - } - ] - } - PTR = { - 'zoneId': None, - 'name': '10.20', - 'type': 'PTR', - 'ttl': 100, - 'account': 'foo', - 'records': [ - { - 'ptrdname': 'ptr.' - } - ] - } - SPF = { - 'zoneId': None, - 'name': 'test-create-spf-ok', - 'type': 'SPF', - 'ttl': 100, - 'account': 'foo', - 'records': [ - { - 'text': 'spf.' - } - ] - } - SRV = { - 'zoneId': None, - 'name': 'test-create-srv-ok', - 'type': 'SRV', - 'ttl': 100, - 'account': 'foo', - 'records': [ - { - 'priority': 1, - 'weight': 2, - 'port': 8000, - 'target': 'srv.' - } - ] - } - SSHFP = { - 'zoneId': None, - 'name': 'test-create-sshfp-ok', - 'type': 'SSHFP', - 'ttl': 100, - 'account': 'foo', - 'records': [ - { - 'algorithm': 1, - 'type': 2, - 'fingerprint': 'fp' - } - ] - } - TXT = { - 'zoneId': None, - 'name': 'test-create-txt-ok', - 'type': 'TXT', - 'ttl': 100, - 'account': 'foo', - 'records': [ - { - 'text': 'some text' - } - ] - } - RECORDS = [('A', A), ('AAAA', AAAA), ('CNAME', CNAME), ('MX', MX), ('PTR', PTR), ('SPF', SPF), ('SRV', SRV), ('SSHFP', SSHFP), ('TXT', TXT)] - FORWARD_RECORDS = [('A', A), ('AAAA', AAAA), ('CNAME', CNAME), ('MX', MX), ('SPF', SPF), ('SRV', SRV), ('SSHFP', SSHFP), ('TXT', TXT)] - REVERSE_RECORDS = [('CNAME', CNAME), ('PTR', PTR), ('TXT', TXT)] diff --git a/modules/api/functional_test/live_tests/zones/create_zone_test.py b/modules/api/functional_test/live_tests/zones/create_zone_test.py deleted file mode 100644 index cf0c888b1..000000000 --- a/modules/api/functional_test/live_tests/zones/create_zone_test.py +++ /dev/null @@ -1,538 +0,0 @@ -import copy -import pytest -import uuid - -from hamcrest import * -from vinyldns_python import VinylDNSClient -from vinyldns_context import VinylDNSTestContext -from utils import * - -records_in_dns = [ - {'name': 'one-time.', - 'type': 'SOA', - 'records': [{u'mname': u'172.17.42.1.', - u'rname': u'admin.test.com.', - u'retry': 3600, - u'refresh': 10800, - u'minimum': 38400, - u'expire': 604800, - u'serial': 1439234395}]}, - {'name': u'one-time.', - 'type': u'NS', - 'records': [{u'nsdname': u'172.17.42.1.'}]}, - {'name': u'jenkins', - 'type': u'A', - 'records': [{u'address': u'10.1.1.1'}]}, - {'name': u'foo', - 'type': u'A', - 'records': [{u'address': u'2.2.2.2'}]}, - {'name': u'test', - 'type': u'A', - 'records': [{u'address': u'3.3.3.3'}, {u'address': u'4.4.4.4'}]}, - {'name': u'one-time.', - 'type': u'A', - 'records': [{u'address': u'5.5.5.5'}]}, - {'name': u'already-exists', - 'type': u'A', - 'records': [{u'address': u'6.6.6.6'}]}] - - -# Defined in docker bind9 conf file -TSIG_KEYS = [ - ('vinyldns-sha1.', '0nIhR1zS/nHUg2n0AIIUyJwXUyQ=', 'HMAC-SHA1'), - ('vinyldns-sha224.', 'yud/F666YjcnfqPSulHaYXrNObNnS1Jv+rX61A==', 'HMAC-SHA224'), - ('vinyldns-sha256.', 'wzLsDGgPRxFaC6z/9Bc0n1W4KrnmaUdFCgCn2+7zbPU=', 'HMAC-SHA256'), - ('vinyldns-sha384.', 'ne9jSUJ7PBGveM37aOX+ZmBXQgz1EqkbYBO1s5l/LNpjEno4OfYvGo1Lv1rnw3pE', 'HMAC-SHA384'), - ('vinyldns-sha512.', 'xfKA0DYb88tiUGND+cWddwUg3/SugYSsdvCfBOJ1jr8MEdgbVRyrlVDEXLsfTUGorQ3ShENdymw2yw+rTr+lwA==', 'HMAC-SHA512'), -] -@pytest.mark.serial -@pytest.mark.parametrize('key_name,key_secret,key_alg', TSIG_KEYS) -def test_create_zone_with_tsigs(shared_zone_test_context, key_name, key_secret, key_alg): - client = shared_zone_test_context.ok_vinyldns_client - - zone_name = 'one-time' - - zone = { - 'name': zone_name, - 'email': 'test@test.com', - 'adminGroupId': shared_zone_test_context.ok_group['id'], - 'connection': { - 'name': key_name, - 'keyName': key_name, - 'key': key_secret, - 'primaryServer': VinylDNSTestContext.dns_ip, - 'algorithm': key_alg - } - } - - try: - zone_change = client.create_zone(zone, status=202) - zone = zone_change['zone'] - client.wait_until_zone_active(zone_change[u'zone'][u'id']) - - # Check that it was internally stored correctly using GET - zone_get = client.get_zone(zone['id'])['zone'] - assert_that(zone_get['name'], is_(zone_name+'.')) - assert_that('connection' in zone_get) - assert_that(zone_get['connection']['keyName'], is_(key_name)) - assert_that(zone_get['connection']['algorithm'], is_(key_alg)) - - finally: - if 'id' in zone: - client.abandon_zones([zone['id']], status=202) - -@pytest.mark.serial -def test_create_zone_success(shared_zone_test_context): - """ - Test successfully creating a zone - """ - client = shared_zone_test_context.ok_vinyldns_client - result_zone = None - try: - zone_name = 'one-time ' - - zone = { - 'name': zone_name, - 'email': 'test@test.com', - 'adminGroupId': shared_zone_test_context.ok_group['id'], - 'backendId': 'func-test-backend' - } - result = client.create_zone(zone, status=202) - result_zone = result['zone'] - client.wait_until_zone_active(result_zone['id']) - - get_result = client.get_zone(result_zone['id']) - - get_zone = get_result['zone'] - assert_that(get_zone['name'], is_(zone['name'].strip()+'.')) - assert_that(get_zone['email'], is_(zone['email'])) - assert_that(get_zone['adminGroupId'], is_(zone['adminGroupId'])) - assert_that(get_zone['latestSync'], is_not(none())) - assert_that(get_zone['status'], is_('Active')) - assert_that(get_zone['backendId'], is_('func-test-backend')) - - # confirm that the recordsets in DNS have been saved in vinyldns - recordsets = client.list_recordsets_by_zone(result_zone['id'])['recordSets'] - - assert_that(len(recordsets), is_(7)) - for rs in recordsets: - small_rs = dict((k, rs[k]) for k in ['name', 'type', 'records']) - small_rs['records'] = sorted(small_rs['records']) - assert_that(records_in_dns, has_item(small_rs)) - - finally: - if result_zone: - client.abandon_zones([result_zone['id']], status=202) - - -@pytest.mark.skip_production -def test_create_zone_without_transfer_connection_leaves_it_empty(shared_zone_test_context): - """ - Test that creating a zone with a valid connection but without a transfer connection leaves the transfer connection empty - """ - client = shared_zone_test_context.ok_vinyldns_client - result_zone = None - try: - zone_name = 'one-time' - - zone = { - 'name': zone_name, - 'email': 'test@test.com', - 'adminGroupId': shared_zone_test_context.ok_group['id'], - 'connection': { - 'name': 'vinyldns.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - } - } - result = client.create_zone(zone, status=202) - result_zone = result['zone'] - client.wait_until_zone_active(result[u'zone'][u'id']) - - get_result = client.get_zone(result_zone['id']) - - get_zone = get_result['zone'] - assert_that(get_zone['name'], is_(zone['name']+'.')) - assert_that(get_zone['email'], is_(zone['email'])) - assert_that(get_zone['adminGroupId'], is_(zone['adminGroupId'])) - - assert_that(get_zone, is_not(has_key('transferConnection'))) - finally: - if result_zone: - client.abandon_zones([result_zone['id']], status=202) - - -def test_create_zone_fails_no_authorization(shared_zone_test_context): - """ - Test creating a new zone without authorization - """ - client = shared_zone_test_context.ok_vinyldns_client - - zone = { - 'name': str(uuid.uuid4()), - 'email': 'test@test.com', - } - client.create_zone(zone, sign_request=False, status=401) - - -def test_create_missing_zone_data(shared_zone_test_context): - """ - Test that creating a zone without providing necessary data (name and email) returns errors - """ - client = shared_zone_test_context.ok_vinyldns_client - - zone = { - 'random_key': 'some_value', - 'another_key': 'meaningless_data' - } - - errors = client.create_zone(zone, status=400)['errors'] - assert_that(errors, contains_inanyorder('Missing Zone.name', 'Missing Zone.email', 'Missing Zone.adminGroupId')) - - -def test_create_invalid_zone_data(shared_zone_test_context): - """ - Test that creating a zone with invalid data returns errors - """ - client = shared_zone_test_context.ok_vinyldns_client - - zone_name = 'test.zone.invalid.' - - zone = { - 'name': zone_name, - 'email': 'test@test.com', - 'shared': 'invalid_value', - 'adminGroupId': 'admin-group-id' - } - - errors = client.create_zone(zone, status=400)['errors'] - assert_that(errors, contains_inanyorder('Do not know how to convert JString(invalid_value) into boolean')) - - -@pytest.mark.serial -def test_create_zone_with_connection_failure(shared_zone_test_context): - """ - Test creating a new zone with a an invalid key and connection info fails - """ - client = shared_zone_test_context.ok_vinyldns_client - - zone_name = 'one-time.' - zone = { - 'name': zone_name, - 'email': 'test@test.com', - 'connection': { - 'name': zone_name, - 'keyName': zone_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - } - } - client.create_zone(zone, status=400) - - -def test_create_zone_returns_409_if_already_exists(shared_zone_test_context): - """ - Test creating a zone returns a 409 Conflict if the zone name already exists - """ - create_conflict = dict(shared_zone_test_context.ok_zone) - create_conflict['connection']['key'] = VinylDNSTestContext.dns_key # necessary because we encrypt the key - create_conflict['transferConnection']['key'] = VinylDNSTestContext.dns_key - - shared_zone_test_context.ok_vinyldns_client.create_zone(create_conflict, status=409) - - -def test_create_zone_returns_400_for_invalid_data(shared_zone_test_context): - """ - Test creating a zone returns a 400 if the request body is invalid - """ - client = shared_zone_test_context.ok_vinyldns_client - - zone = { - 'jim': 'bob', - 'hey': 'you' - } - client.create_zone(zone, status=400) - - -@pytest.mark.skip_production -@pytest.mark.serial -def test_create_zone_no_connection_uses_defaults(shared_zone_test_context): - - client = shared_zone_test_context.ok_vinyldns_client - - zone_name = 'one-time' - - zone = { - 'name': zone_name, - 'email': 'test@test.com', - 'adminGroupId': shared_zone_test_context.ok_group['id'] - } - - try: - zone_change = client.create_zone(zone, status=202) - zone = zone_change['zone'] - client.wait_until_zone_active(zone_change[u'zone'][u'id']) - - # Check response from create - assert_that(zone['name'], is_(zone_name+'.')) - print "'connection' not in zone = " + 'connection' not in zone - - assert_that('connection' not in zone) - assert_that('transferConnection' not in zone) - - # Check that it was internally stored correctly using GET - zone_get = client.get_zone(zone['id'])['zone'] - assert_that(zone_get['name'], is_(zone_name+'.')) - assert_that('connection' not in zone_get) - assert_that('transferConnection' not in zone_get) - - finally: - if 'id' in zone: - client.abandon_zones([zone['id']], status=202) - - -@pytest.mark.serial -def test_zone_connection_only(shared_zone_test_context): - - client = shared_zone_test_context.ok_vinyldns_client - - zone_name = 'one-time' - - zone = { - 'name': zone_name, - 'email': 'test@test.com', - 'adminGroupId': shared_zone_test_context.ok_group['id'], - 'connection': { - 'name': 'vinyldns.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - }, - 'transferConnection': { - 'name': 'vinyldns.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - } - } - - expected_connection = { - 'name': 'vinyldns.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - } - - try: - zone_change = client.create_zone(zone, status=202) - zone = zone_change['zone'] - client.wait_until_zone_active(zone_change[u'zone'][u'id']) - - # Check response from create - assert_that(zone['name'], is_(zone_name+'.')) - assert_that(zone['connection']['name'], is_(expected_connection['name'])) - assert_that(zone['connection']['keyName'], is_(expected_connection['keyName'])) - assert_that(zone['connection']['primaryServer'], is_(expected_connection['primaryServer'])) - assert_that(zone['transferConnection']['name'], is_(expected_connection['name'])) - assert_that(zone['transferConnection']['keyName'], is_(expected_connection['keyName'])) - assert_that(zone['transferConnection']['primaryServer'], is_(expected_connection['primaryServer'])) - - # Check that it was internally stored correctly using GET - zone_get = client.get_zone(zone['id'])['zone'] - assert_that(zone_get['name'], is_(zone_name+'.')) - assert_that(zone['connection']['name'], is_(expected_connection['name'])) - assert_that(zone['connection']['keyName'], is_(expected_connection['keyName'])) - assert_that(zone['connection']['primaryServer'], is_(expected_connection['primaryServer'])) - assert_that(zone['transferConnection']['name'], is_(expected_connection['name'])) - assert_that(zone['transferConnection']['keyName'], is_(expected_connection['keyName'])) - assert_that(zone['transferConnection']['primaryServer'], is_(expected_connection['primaryServer'])) - - finally: - if 'id' in zone: - client.abandon_zones([zone['id']], status=202) - - -@pytest.mark.serial -def test_zone_bad_connection(shared_zone_test_context): - - client = shared_zone_test_context.ok_vinyldns_client - - zone_name = 'one-time' - - zone = { - 'name': zone_name, - 'email': 'test@test.com', - 'connection': { - 'name': zone_name, - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': 'somebadkey', - 'primaryServer': VinylDNSTestContext.dns_ip - } - } - - client.create_zone(zone, status=400) - - -@pytest.mark.serial -def test_zone_bad_transfer_connection(shared_zone_test_context): - - client = shared_zone_test_context.ok_vinyldns_client - - zone_name = 'one-time' - - zone = { - 'name': zone_name, - 'email': 'test@test.com', - 'connection': { - 'name': zone_name, - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - }, - 'transferConnection': { - 'name': zone_name, - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': "bad", - 'primaryServer': VinylDNSTestContext.dns_ip - } - } - - client.create_zone(zone, status=400) - - -@pytest.mark.serial -def test_zone_transfer_connection(shared_zone_test_context): - - client = shared_zone_test_context.ok_vinyldns_client - - zone_name = 'one-time' - - zone = { - 'name': zone_name, - 'email': 'test@test.com', - 'adminGroupId': shared_zone_test_context.ok_group['id'], - 'connection': { - 'name': zone_name, - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - }, - 'transferConnection': { - 'name': zone_name, - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - } - } - - expected_connection = { - 'name': zone_name, - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - } - - try: - zone_change = client.create_zone(zone, status=202) - zone = zone_change['zone'] - client.wait_until_zone_active(zone_change[u'zone'][u'id']) - - # Check response from create - assert_that(zone['name'], is_(zone_name+'.')) - assert_that(zone['connection']['name'], is_(expected_connection['name'])) - assert_that(zone['connection']['keyName'], is_(expected_connection['keyName'])) - assert_that(zone['connection']['primaryServer'], is_(expected_connection['primaryServer'])) - assert_that(zone['transferConnection']['name'], is_(expected_connection['name'])) - assert_that(zone['transferConnection']['keyName'], is_(expected_connection['keyName'])) - assert_that(zone['transferConnection']['primaryServer'], is_(expected_connection['primaryServer'])) - - # Check that it was internally stored correctly using GET - zone_get = client.get_zone(zone['id'])['zone'] - assert_that(zone_get['name'], is_(zone_name+'.')) - assert_that(zone['connection']['name'], is_(expected_connection['name'])) - assert_that(zone['connection']['keyName'], is_(expected_connection['keyName'])) - assert_that(zone['connection']['primaryServer'], is_(expected_connection['primaryServer'])) - assert_that(zone['transferConnection']['name'], is_(expected_connection['name'])) - assert_that(zone['transferConnection']['keyName'], is_(expected_connection['keyName'])) - assert_that(zone['transferConnection']['primaryServer'], is_(expected_connection['primaryServer'])) - - finally: - if 'id' in zone: - client.abandon_zones([zone['id']], status=202) - - -@pytest.mark.serial -def test_user_cannot_create_zone_with_nonmember_admin_group(shared_zone_test_context): - """ - Test user cannot create a zone with an admin group they are not a member of - """ - zone = { - 'name': 'one-time.', - 'email': 'test@test.com', - 'adminGroupId': shared_zone_test_context.dummy_group['id'], - 'connection': { - 'name': 'vinyldns.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - }, - 'transferConnection': { - 'name': 'vinyldns.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - } - } - - shared_zone_test_context.ok_vinyldns_client.create_zone(zone, status=403) - - -def test_user_cannot_create_zone_with_failed_validations(shared_zone_test_context): - """ - Test that a user cannot create a zone that has invalid zone data - """ - zone = { - 'name': 'invalid-zone.', - 'email': 'test@test.com', - 'adminGroupId': shared_zone_test_context.ok_group['id'], - 'connection': { - 'name': 'vinyldns.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - }, - 'transferConnection': { - 'name': 'vinyldns.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - } - } - - result = shared_zone_test_context.ok_vinyldns_client.create_zone(zone, status=400) - assert_that(result['errors'], contains_inanyorder( - contains_string("not-approved.thing.com. is not an approved name server") - )) - -def test_normal_user_cannot_create_shared_zone(shared_zone_test_context): - """ - Test that a normal user cannot create a shared zone - """ - super_zone = copy.deepcopy(shared_zone_test_context.ok_zone) - super_zone['shared'] = True - - shared_zone_test_context.ok_vinyldns_client.create_zone(super_zone, status=403) - -def test_create_zone_bad_backend_id(shared_zone_test_context): - """ - Test that a user cannot create a zone with a backendId that is not in config - """ - zone = { - 'name': "test-create-zone-bad-backend-id", - 'email': 'test@test.com', - 'adminGroupId': shared_zone_test_context.ok_group['id'], - 'backendId': "does-not-exist-id" - } - result = shared_zone_test_context.ok_vinyldns_client.create_zone(zone, status=400) - assert_that(result, contains_string("Invalid backendId")) diff --git a/modules/api/functional_test/live_tests/zones/delete_zone_test.py b/modules/api/functional_test/live_tests/zones/delete_zone_test.py deleted file mode 100644 index 5957b1db0..000000000 --- a/modules/api/functional_test/live_tests/zones/delete_zone_test.py +++ /dev/null @@ -1,108 +0,0 @@ -import pytest -import uuid - -from hamcrest import * -from vinyldns_python import VinylDNSClient -from vinyldns_context import VinylDNSTestContext -from utils import * - - -@pytest.mark.serial -def test_delete_zone_success(shared_zone_test_context): - """ - Test deleting a zone - """ - client = shared_zone_test_context.ok_vinyldns_client - result_zone = None - try: - zone_name = 'one-time' - - zone = { - 'name': zone_name, - 'email': 'test@test.com', - 'adminGroupId': shared_zone_test_context.ok_group['id'], - 'connection': { - 'name': 'vinyldns.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - }, - 'transferConnection': { - 'name': 'vinyldns.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - } - } - result = client.create_zone(zone, status=202) - result_zone = result['zone'] - client.wait_until_zone_active(result_zone['id']) - - client.delete_zone(result_zone['id'], status=202) - client.wait_until_zone_deleted(result_zone['id']) - - client.get_zone(result_zone['id'], status=404) - result_zone = None - - finally: - if result_zone: - client.abandon_zones([result_zone['id']], status=202) - - -@pytest.mark.serial -def test_delete_zone_twice(shared_zone_test_context): - """ - Test deleting a zone with deleted status returns 404 - """ - client = shared_zone_test_context.ok_vinyldns_client - result_zone = None - try: - zone_name = 'one-time' - - zone = { - 'name': zone_name, - 'email': 'test@test.com', - 'adminGroupId': shared_zone_test_context.ok_group['id'], - 'connection': { - 'name': 'vinyldns.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - }, - 'transferConnection': { - 'name': 'vinyldns.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - } - } - result = client.create_zone(zone, status=202) - result_zone = result['zone'] - client.wait_until_zone_active(result_zone['id']) - - client.delete_zone(result_zone['id'], status=202) - client.wait_until_zone_deleted(result_zone['id']) - - client.delete_zone(result_zone['id'], status=404) - result_zone = None - - finally: - if result_zone: - client.abandon_zones([result_zone['id']], status=202) - - -def test_delete_zone_returns_404_if_zone_not_found(shared_zone_test_context): - """ - Test deleting a zone returns a 404 if the zone was not found - """ - client = shared_zone_test_context.ok_vinyldns_client - client.delete_zone('nothere', status=404) - - -def test_delete_zone_no_authorization(shared_zone_test_context): - """ - Test deleting a zone without authorization - """ - client = shared_zone_test_context.ok_vinyldns_client - - client.delete_zone('1234', sign_request=False, status=401) diff --git a/modules/api/functional_test/live_tests/zones/list_zones_test.py b/modules/api/functional_test/live_tests/zones/list_zones_test.py deleted file mode 100644 index a758ff301..000000000 --- a/modules/api/functional_test/live_tests/zones/list_zones_test.py +++ /dev/null @@ -1,166 +0,0 @@ -from hamcrest import * -from utils import * - - -def test_list_zones_success(shared_zone_test_context): - """ - Test that we can retrieve a list of the user's zones - """ - result = shared_zone_test_context.list_zones_client.list_zones(status=200) - retrieved = result['zones'] - - assert_that(retrieved, has_length(5)) - assert_that(retrieved, has_item(has_entry('name', 'list-zones-test-searched-1.'))) - assert_that(retrieved, has_item(has_entry('adminGroupName', 'list-zones-group'))) - assert_that(retrieved, has_item(has_entry('backendId', 'func-test-backend'))) - - -def test_list_zones_max_items_100(shared_zone_test_context): - """ - Test that the default max items for a list zones request is 100 - """ - result = shared_zone_test_context.list_zones_client.list_zones(status=200) - assert_that(result['maxItems'], is_(100)) - -def test_list_zones_ignore_access_default_false(shared_zone_test_context): - """ - Test that the default ignore access value for a list zones request is false - """ - result = shared_zone_test_context.list_zones_client.list_zones(status=200) - assert_that(result['ignoreAccess'], is_(False)) - -def test_list_zones_invalid_max_items_fails(shared_zone_test_context): - """ - Test that passing in an invalid value for max items fails - """ - errors = shared_zone_test_context.list_zones_client.list_zones(max_items=700, status=400) - assert_that(errors, contains_string("maxItems was 700, maxItems must be between 0 and 100")) - - -def test_list_zones_no_authorization(shared_zone_test_context): - """ - Test that we cannot retrieve a list of zones without authorization - """ - shared_zone_test_context.list_zones_client.list_zones(sign_request=False, status=401) - - -def test_list_zones_no_search_first_page(shared_zone_test_context): - """ - Test that the first page of listing zones returns correctly when no name filter is provided - """ - result = shared_zone_test_context.list_zones_client.list_zones(max_items=3) - zones = result['zones'] - - assert_that(zones, has_length(3)) - assert_that(zones[0]['name'], is_('list-zones-test-searched-1.')) - assert_that(zones[1]['name'], is_('list-zones-test-searched-2.')) - assert_that(zones[2]['name'], is_('list-zones-test-searched-3.')) - - assert_that(result['nextId'], is_('list-zones-test-searched-3.')) - assert_that(result['maxItems'], is_(3)) - assert_that(result, is_not(has_key('startFrom'))) - assert_that(result, is_not(has_key('nameFilter'))) - - -def test_list_zones_no_search_second_page(shared_zone_test_context): - """ - Test that the second page of listing zones returns correctly when no name filter is provided - """ - result = shared_zone_test_context.list_zones_client.list_zones(start_from="list-zones-test-searched-2.", max_items=2, status=200) - zones = result['zones'] - - assert_that(zones, has_length(2)) - assert_that(zones[0]['name'], is_('list-zones-test-searched-3.')) - assert_that(zones[1]['name'], is_('list-zones-test-unfiltered-1.')) - - assert_that(result['nextId'], is_("list-zones-test-unfiltered-1.")) - assert_that(result['maxItems'], is_(2)) - assert_that(result['startFrom'], is_("list-zones-test-searched-2.")) - assert_that(result, is_not(has_key('nameFilter'))) - - -def test_list_zones_no_search_last_page(shared_zone_test_context): - """ - Test that the last page of listing zones returns correctly when no name filter is provided - """ - result = shared_zone_test_context.list_zones_client.list_zones(start_from="list-zones-test-searched-3.", max_items=4, status=200) - zones = result['zones'] - - assert_that(zones, has_length(2)) - assert_that(zones[0]['name'], is_('list-zones-test-unfiltered-1.')) - assert_that(zones[1]['name'], is_('list-zones-test-unfiltered-2.')) - - assert_that(result, is_not(has_key('nextId'))) - assert_that(result['maxItems'], is_(4)) - assert_that(result['startFrom'], is_('list-zones-test-searched-3.')) - assert_that(result, is_not(has_key('nameFilter'))) - - -def test_list_zones_with_search_first_page(shared_zone_test_context): - """ - Test that the first page of listing zones returns correctly when a name filter is provided - """ - result = shared_zone_test_context.list_zones_client.list_zones(name_filter='*searched*', max_items=2, status=200) - zones = result['zones'] - - assert_that(zones, has_length(2)) - assert_that(zones[0]['name'], is_('list-zones-test-searched-1.')) - assert_that(zones[1]['name'], is_('list-zones-test-searched-2.')) - - assert_that(result['nextId'], is_('list-zones-test-searched-2.')) - assert_that(result['maxItems'], is_(2)) - assert_that(result['nameFilter'], is_('*searched*')) - assert_that(result, is_not(has_key('startFrom'))) - - -def test_list_zones_with_no_results(shared_zone_test_context): - """ - Test that the response is formed correctly when no results are found - """ - result = shared_zone_test_context.list_zones_client.list_zones(name_filter='this-wont-be-found', max_items=2, status=200) - zones = result['zones'] - - assert_that(zones, has_length(0)) - - assert_that(result['maxItems'], is_(2)) - assert_that(result['nameFilter'], is_('this-wont-be-found')) - assert_that(result, is_not(has_key('startFrom'))) - assert_that(result, is_not(has_key('nextId'))) - - -def test_list_zones_with_search_last_page(shared_zone_test_context): - """ - Test that the second page of listing zones returns correctly when a name filter is provided - """ - result = shared_zone_test_context.list_zones_client.list_zones(name_filter='*test-searched-3', start_from="list-zones-test-searched-2.", max_items=2, status=200) - zones = result['zones'] - - assert_that(zones, has_length(1)) - assert_that(zones[0]['name'], is_('list-zones-test-searched-3.')) - - assert_that(result, is_not(has_key('nextId'))) - assert_that(result['maxItems'], is_(2)) - assert_that(result['nameFilter'], is_('*test-searched-3')) - assert_that(result['startFrom'], is_('list-zones-test-searched-2.')) - -def test_list_zones_ignore_access_success(shared_zone_test_context): - """ - Test that we can retrieve a list of zones regardless of zone access - """ - result = shared_zone_test_context.list_zones_client.list_zones(ignore_access=True, status=200) - retrieved = result['zones'] - - assert_that(result['ignoreAccess'], is_(True)) - assert_that(len(retrieved), greater_than(5)) - - -def test_list_zones_ignore_access_success_with_name_filter(shared_zone_test_context): - """ - Test that we can retrieve a list of all zones with a name filter - """ - result = shared_zone_test_context.list_zones_client.list_zones(name_filter='shared', ignore_access=True, status=200) - retrieved = result['zones'] - - assert_that(result['ignoreAccess'], is_(True)) - assert_that(retrieved, has_item(has_entry('name', 'shared.'))) - assert_that(retrieved, has_item(has_entry('accessLevel', 'NoAccess'))) diff --git a/modules/api/functional_test/live_tests/zones/sync_zone_test.py b/modules/api/functional_test/live_tests/zones/sync_zone_test.py deleted file mode 100644 index 2e64b610b..000000000 --- a/modules/api/functional_test/live_tests/zones/sync_zone_test.py +++ /dev/null @@ -1,246 +0,0 @@ -from hamcrest import * -from vinyldns_python import VinylDNSClient -from vinyldns_context import VinylDNSTestContext -from utils import * -import time - -MAX_RETRIES = 30 -RETRY_WAIT = 0.05 - -records_in_dns = [ - {'name': 'sync-test.', - 'type': 'SOA', - 'records': [{u'mname': u'172.17.42.1.', - u'rname': u'admin.test.com.', - u'retry': 3600, - u'refresh': 10800, - u'minimum': 38400, - u'expire': 604800, - u'serial': 1439234395}]}, - {'name': u'sync-test.', - 'type': u'NS', - 'records': [{u'nsdname': u'172.17.42.1.'}]}, - {'name': u'jenkins', - 'type': u'A', - 'records': [{u'address': u'10.1.1.1'}]}, - {'name': u'foo', - 'type': u'A', - 'records': [{u'address': u'2.2.2.2'}]}, - {'name': u'test', - 'type': u'A', - 'records': [{u'address': u'3.3.3.3'}, {u'address': u'4.4.4.4'}]}, - {'name': u'sync-test.', - 'type': u'A', - 'records': [{u'address': u'5.5.5.5'}]}, - {'name': u'already-exists', - 'type': u'A', - 'records': [{u'address': u'6.6.6.6'}]}, - {'name': u'fqdn', - 'type': u'A', - 'records': [{u'address': u'7.7.7.7'}]}, - {'name': u'_sip._tcp', - 'type': u'SRV', - 'records': [{u'priority': 10, u'weight': 60, u'port': 5060, u'target': u'foo.sync-test.'}]}, - {'name': u'existing.dotted', - 'type': u'A', - 'records': [{u'address': u'9.9.9.9'}]}] - -records_post_update = [ - {'name': 'sync-test.', - 'type': 'SOA', - 'records': [{u'mname': u'172.17.42.1.', - u'rname': u'admin.test.com.', - u'retry': 3600, - u'refresh': 10800, - u'minimum': 38400, - u'expire': 604800, - u'serial': 0}]}, - {'name': u'sync-test.', - 'type': u'NS', - 'records': [{u'nsdname': u'172.17.42.1.'}]}, - {'name': u'foo', - 'type': u'A', - 'records': [{u'address': u'1.2.3.4'}]}, - {'name': u'test', - 'type': u'A', - 'records': [{u'address': u'3.3.3.3'}, {u'address': u'4.4.4.4'}]}, - {'name': u'sync-test.', - 'type': u'A', - 'records': [{u'address': u'5.5.5.5'}]}, - {'name': u'already-exists', - 'type': u'A', - 'records': [{u'address': u'6.6.6.6'}]}, - {'name': u'newrs', - 'type': u'A', - 'records': [{u'address': u'2.3.4.5'}]}, - {'name': u'fqdn', - 'type': u'A', - 'records': [{u'address': u'7.7.7.7'}]}, - {'name': u'_sip._tcp', - 'type': u'SRV', - 'records': [{u'priority': 10, u'weight': 60, u'port': 5060, u'target': u'foo.sync-test.'}]}, - {'name': u'existing.dotted', - 'type': u'A', - 'records': [{u'address': u'9.9.9.9'}]}, - {'name': u'dott.ed', - 'type': u'A', - 'records': [{u'address': u'6.7.8.9'}]}, - {'name': u'dott.ed-two', - 'type': u'A', - 'records': [{u'address': u'6.7.8.9'}]}] - - -@pytest.mark.skip_production -def test_sync_zone_success(shared_zone_test_context): - """ - Test syncing a zone - """ - client = shared_zone_test_context.ok_vinyldns_client - zone_name = 'sync-test' - updated_rs_id = None - check_rs = None - - zone = { - 'name': zone_name, - 'email': 'test@test.com', - 'adminGroupId': shared_zone_test_context.ok_group['id'], - 'isTest': True, - 'connection': { - 'name': 'vinyldns.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - }, - 'transferConnection': { - 'name': 'vinyldns.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - } - } - try: - zone_change = client.create_zone(zone, status=202) - zone = zone_change['zone'] - client.wait_until_zone_active(zone['id']) - - time.sleep(.5) - - # confirm zone has been synced - get_result = client.get_zone(zone['id']) - synced_zone = get_result['zone'] - latest_sync = synced_zone['latestSync'] - assert_that(latest_sync, is_not(none())) - - # confirm that the recordsets in DNS have been saved in vinyldns - recordsets = client.list_recordsets_by_zone(zone['id'])['recordSets'] - - assert_that(len(recordsets), is_(10)) - for rs in recordsets: - if rs['name'] == 'foo': - # get the ID for recordset with name 'foo' - updated_rs_id = rs['id'] - small_rs = dict((k, rs[k]) for k in ['name', 'type', 'records']) - small_rs['records'] = sorted(small_rs['records']) - if small_rs['type'] == 'SOA': - assert_that(small_rs['name'], is_('sync-test.')) - else: - assert_that(records_in_dns, has_item(small_rs)) - - # give the 'foo' record an ownerGroupID to confirm it's still present after the zone sync - foo_rs = client.get_recordset(zone['id'], updated_rs_id)['recordSet'] - foo_rs['ownerGroupId'] = shared_zone_test_context.ok_group['id'] - update_response = client.update_recordset(foo_rs, status=202) - foo_rs_change = client.wait_until_recordset_change_status(update_response, 'Complete') - assert_that(foo_rs_change['recordSet']['ownerGroupId'], is_(shared_zone_test_context.ok_group['id'])) - - # make changes to the dns backend - dns_update(zone, 'foo', 38400, 'A', '1.2.3.4') - dns_add(zone, 'newrs', 38400, 'A', '2.3.4.5') - dns_delete(zone, 'jenkins', 'A') - - # add unknown this should not be synced - dns_add(zone, 'dnametest', 38400, 'DNAME', 'test.com.') - - # add dotted hosts, this should be synced, so we will have 10 records ( +2 ) - dns_add(zone, 'dott.ed', 38400, 'A', '6.7.8.9') - dns_add(zone, 'dott.ed-two', 38400, 'A', '6.7.8.9') - - # wait for next sync - time.sleep(10) - - # sync again - change = client.sync_zone(zone['id'], status=202) - client.wait_until_zone_change_status_synced(change) - - # confirm cannot again sync without waiting - client.sync_zone(zone['id'], status=403) - - # validate zone - get_result = client.get_zone(zone['id']) - synced_zone = get_result['zone'] - assert_that(synced_zone['latestSync'], is_not(latest_sync)) - assert_that(synced_zone['status'], is_('Active')) - assert_that(synced_zone['updated'], is_not(none())) - - # confirm that the updated recordsets in DNS have been saved in vinyldns - recordsets = client.list_recordsets_by_zone(zone['id'])['recordSets'] - assert_that(len(recordsets), is_(12)) - for rs in recordsets: - small_rs = dict((k, rs[k]) for k in ['name', 'type', 'records']) - small_rs['records'] = sorted(small_rs['records']) - if small_rs['type'] == 'SOA': - small_rs['records'][0]['serial'] = 0 - # records_post_update does not contain dnametest - assert_that(records_post_update, has_item(small_rs)) - - changes = client.list_recordset_changes(zone['id']) - for c in changes['recordSetChanges']: - if c['id'] != foo_rs_change['id']: - assert_that(c['systemMessage'], is_('Change applied via zone sync')) - - check_rs = client.get_recordset(zone['id'], updated_rs_id)['recordSet'] - assert_that(check_rs['ownerGroupId'], is_(shared_zone_test_context.ok_group['id'])) - - for rs in recordsets: - # confirm that we can update the dotted host if the name is the same - if rs['name'] == 'dott.ed': - attempt_update = rs - attempt_update['ttl'] = attempt_update['ttl'] + 100 - change = client.update_recordset(attempt_update, status=202) - client.wait_until_recordset_change_status(change, 'Complete') - - # we should be able to delete the record - client.delete_recordset(rs['zoneId'], rs['id'], status=202) - client.wait_until_recordset_deleted(rs['zoneId'], rs['id']) - - # confirm that we cannot update the dotted host if the name changes - if rs['name'] == 'dott.ed-two': - attempt_update = rs - attempt_update['name'] = 'new.dotted' - errors = client.update_recordset(attempt_update, status=422) - assert_that(errors, is_("Cannot update RecordSet's name.")) - - - # we should be able to delete the record - client.delete_recordset(rs['zoneId'], rs['id'], status=202) - client.wait_until_recordset_deleted(rs['zoneId'], rs['id']) - - if rs['name'] == "example.dotted": - # confirm that we can modify the example dotted - good_update = rs - good_update['name'] = "example-dotted" - change = client.update_recordset(good_update, status=202) - client.wait_until_recordset_change_status(change, 'Complete') - - finally: - # reset the ownerGroupId for foo record - if check_rs: - check_rs['ownerGroupId'] = None - update_response = client.update_recordset(check_rs, status=202) - client.wait_until_recordset_change_status(update_response, 'Complete') - if 'id' in zone: - dns_update(zone, 'foo', 38400, 'A', '2.2.2.2') - dns_delete(zone, 'newrs', 'A') - dns_add(zone, 'jenkins', 38400, 'A', '10.1.1.1') - dns_delete(zone, 'example-dotted', 'A') - client.abandon_zones([zone['id']], status=202) diff --git a/modules/api/functional_test/live_tests/zones/update_zone_test.py b/modules/api/functional_test/live_tests/zones/update_zone_test.py deleted file mode 100644 index 2b1aceed7..000000000 --- a/modules/api/functional_test/live_tests/zones/update_zone_test.py +++ /dev/null @@ -1,913 +0,0 @@ -import pytest -import uuid -from hamcrest import * -from utils import * -from vinyldns_context import VinylDNSTestContext - - -@pytest.mark.serial -def test_update_zone_success(shared_zone_test_context): - """ - Test updating a zone - """ - client = shared_zone_test_context.ok_vinyldns_client - result_zone = None - try: - zone_name = 'one-time' - - acl_rule = { - 'accessLevel': 'Read', - 'description': 'test-acl-updated-by-updatezn', - 'userId': 'ok', - 'recordMask': 'www-*', - 'recordTypes': ['A', 'AAAA', 'CNAME'] - } - - zone = { - 'name': zone_name, - 'email': 'test@test.com', - 'adminGroupId': shared_zone_test_context.ok_group['id'], - 'connection': { - 'name': 'vinyldns.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - }, - 'transferConnection': { - 'name': 'vinyldns.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - } - } - result = client.create_zone(zone, status=202) - result_zone = result['zone'] - client.wait_until_zone_active(result_zone['id']) - - result_zone['email'] = 'foo@bar.com' - result_zone['acl']['rules'] = [acl_rule] - update_result = client.update_zone(result_zone, status=202) - client.wait_until_zone_change_status_synced(update_result) - - assert_that(update_result['changeType'], is_('Update')) - assert_that(update_result['userId'], is_('ok')) - assert_that(update_result, has_key('created')) - - get_result = client.get_zone(result_zone['id']) - - uz = get_result['zone'] - assert_that(uz['email'], is_('foo@bar.com')) - assert_that(uz['updated'], is_not(none())) - - acl = uz['acl'] - verify_acl_rule_is_present_once(acl_rule, acl) - - finally: - if result_zone: - client.abandon_zones([result_zone['id']], status=202) - - -def test_update_bad_acl_fails(shared_zone_test_context): - """ - Test that updating a zone with a bad ACL rule fails - """ - client = shared_zone_test_context.ok_vinyldns_client - zone = shared_zone_test_context.ok_zone - - acl_bad_regex = { - 'accessLevel': 'Read', - 'description': 'test-acl-updated-by-updatezn-bad', - 'userId': 'ok', - 'recordMask': '*', - 'recordTypes': ['A', 'AAAA', 'CNAME'] - } - - zone['acl']['rules'] = [acl_bad_regex] - - client.update_zone(zone, status=400) - - -def test_update_acl_no_group_or_user_fails(shared_zone_test_context): - """ - Test that updating a zone with an ACL with no user/group fails - """ - client = shared_zone_test_context.ok_vinyldns_client - zone = shared_zone_test_context.ok_zone - - bad_acl = { - 'accessLevel': 'Read', - 'description': 'test-acl-updated-by-updatezn-bad-ids', - 'recordMask': 'www-*', - 'recordTypes': ['A', 'AAAA', 'CNAME'] - } - - zone['acl']['rules'] = [bad_acl] - - client.update_zone(zone, status=400) - - -@pytest.mark.serial -def test_update_missing_zone_data(shared_zone_test_context): - """ - Test that updating a zone without providing necessary data returns errors and fails the update - """ - - client = shared_zone_test_context.ok_vinyldns_client - result_zone = None - try: - zone_name = 'one-time.' - - zone = { - 'name': zone_name, - 'email': 'test@test.com', - 'adminGroupId': shared_zone_test_context.ok_group['id'], - 'connection': { - 'name': 'vinyldns.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - }, - 'transferConnection': { - 'name': 'vinyldns.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - } - } - result = client.create_zone(zone, status=202) - result_zone = result['zone'] - client.wait_until_zone_active(result[u'zone'][u'id']) - - update_zone = { - 'id': result_zone['id'], - 'name': result_zone['name'], - 'random_key': 'some_value', - 'another_key': 'meaningless_data', - 'adminGroupId': zone['adminGroupId'] - } - - errors = client.update_zone(update_zone, status=400)['errors'] - assert_that(errors, contains_inanyorder('Missing Zone.email')) - - # Check that the failed update didn't go through - zone_get = client.get_zone(result_zone['id'])['zone'] - assert_that(zone_get['name'], is_(zone_name)) - - finally: - if result_zone: - client.abandon_zones([result_zone['id']], status=202) - - -@pytest.mark.serial -def test_update_invalid_zone_data(shared_zone_test_context): - """ - Test that creating a zone with invalid data returns errors and fails the update - """ - client = shared_zone_test_context.ok_vinyldns_client - result_zone = None - try: - zone_name = 'one-time.' - - zone = { - 'name': zone_name, - 'email': 'test@test.com', - 'adminGroupId': shared_zone_test_context.ok_group['id'], - 'connection': { - 'name': 'vinyldns.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - }, - 'transferConnection': { - 'name': 'vinyldns.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - } - } - result = client.create_zone(zone, status=202) - result_zone = result['zone'] - client.wait_until_zone_active(result[u'zone'][u'id']) - - update_zone = { - 'id': result_zone['id'], - 'name': result_zone['name'], - 'email': 'test@test.com', - 'adminGroupId': True - } - - errors = client.update_zone(update_zone, status=400)['errors'] - assert_that(errors, contains_inanyorder('Do not know how to convert JBool(true) into class java.lang.String')) - - # Check that the failed update didn't go through - zone_get = client.get_zone(result_zone['id'])['zone'] - assert_that(zone_get['name'], is_(zone_name)) - - finally: - if result_zone: - client.abandon_zones([result_zone['id']], status=202) - - -@pytest.mark.serial -def test_update_zone_returns_404_if_zone_not_found(shared_zone_test_context): - """ - Test updating a zone returns a 404 if the zone was not found - """ - client = shared_zone_test_context.ok_vinyldns_client - zone = { - 'name': 'one-time.', - 'email': 'test@test.com', - 'id': 'nothere', - 'connection': { - 'name': 'old-shared.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - }, - 'transferConnection': { - 'name': 'old-shared.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - }, - 'adminGroupId': shared_zone_test_context.ok_group['id'] - } - client.update_zone(zone, status=404) - - -@pytest.mark.serial -def test_create_acl_group_rule_success(shared_zone_test_context): - """ - Test creating an acl rule successfully - """ - client = shared_zone_test_context.ok_vinyldns_client - - acl_rule = { - 'accessLevel': 'Read', - 'description': 'test-acl-group-id', - 'groupId': shared_zone_test_context.ok_group['id'], - 'recordMask': 'www-*', - 'recordTypes': ['A', 'AAAA', 'CNAME'] - } - result = client.add_zone_acl_rule_with_wait(shared_zone_test_context.system_test_zone['id'], acl_rule, status=202) - - # This is async, we get a zone change back - acl = result['zone']['acl'] - - verify_acl_rule_is_present_once(acl_rule, acl) - - # make sure that our acl rule appears on the zone - zone = client.get_zone(result['zone']['id'])['zone'] - - acl = zone['acl'] - - verify_acl_rule_is_present_once(acl_rule, acl) - - -@pytest.mark.serial -def test_create_acl_user_rule_success(shared_zone_test_context): - """ - Test creating an acl rule successfully - """ - client = shared_zone_test_context.ok_vinyldns_client - - acl_rule = { - 'accessLevel': 'Read', - 'description': 'test-acl-user-id', - 'userId': 'ok', - 'recordMask': 'www-*', - 'recordTypes': ['A', 'AAAA', 'CNAME'] - } - result = client.add_zone_acl_rule_with_wait(shared_zone_test_context.system_test_zone['id'], acl_rule, status=202) - - # This is async, we get a zone change back - acl = result['zone']['acl'] - - verify_acl_rule_is_present_once(acl_rule, acl) - - # make sure that our acl rule appears on the zone - zone = client.get_zone(result['zone']['id'])['zone'] - - acl = zone['acl'] - - verify_acl_rule_is_present_once(acl_rule, acl) - - -def test_create_acl_user_rule_invalid_regex_failure(shared_zone_test_context): - """ - Test creating an acl rule with an invalid regex mask fails - """ - client = shared_zone_test_context.ok_vinyldns_client - - acl_rule = { - 'accessLevel': 'Read', - 'description': 'test-acl-user-id', - 'userId': '789', - 'recordMask': 'x{5,-3}', - 'recordTypes': ['A', 'AAAA', 'CNAME'] - } - - errors = client.add_zone_acl_rule(shared_zone_test_context.system_test_zone['id'], acl_rule, status=400) - assert_that(errors, contains_string("record mask x{5,-3} is an invalid regex")) - - -def test_create_acl_user_rule_invalid_cidr_failure(shared_zone_test_context): - """ - Test creating an acl rule with an invalid cidr mask fails - """ - client = shared_zone_test_context.ok_vinyldns_client - - acl_rule = { - 'accessLevel': 'Read', - 'description': 'test-acl-user-id', - 'userId': '789', - 'recordMask': '10.0.0.0/50', - 'recordTypes': ['PTR'] - } - - errors = client.add_zone_acl_rule(shared_zone_test_context.ip4_reverse_zone['id'], acl_rule, status=400) - assert_that(errors, - contains_string("PTR types must have no mask or a valid CIDR mask: IPv4 mask must be between 0 and 32")) - - -@pytest.mark.serial -def test_create_acl_user_rule_valid_cidr_success(shared_zone_test_context): - """ - Test creating an acl rule with a valid cidr mask passes - """ - client = shared_zone_test_context.ok_vinyldns_client - - acl_rule = { - 'accessLevel': 'Read', - 'description': 'test-acl-user-id', - 'userId': 'ok', - 'recordMask': '10.0.0.0/20', - 'recordTypes': ['PTR'] - } - - result = client.add_zone_acl_rule_with_wait(shared_zone_test_context.ip4_reverse_zone['id'], acl_rule, status=202) - - # This is async, we get a zone change back - acl = result['zone']['acl'] - - verify_acl_rule_is_present_once(acl_rule, acl) - - # make sure that our acl rule appears on the zone - zone = client.get_zone(result['zone']['id'])['zone'] - - acl = zone['acl'] - - verify_acl_rule_is_present_once(acl_rule, acl) - - -def test_create_acl_user_rule_multiple_cidr_failure(shared_zone_test_context): - """ - Test creating an acl rule with multiple record types including PTR and a cidr mask fails - """ - client = shared_zone_test_context.ok_vinyldns_client - - acl_rule = { - 'accessLevel': 'Read', - 'description': 'test-acl-user-id', - 'userId': '789', - 'recordMask': '10.0.0.0/20', - 'recordTypes': ['PTR', 'A', 'AAAA'] - } - - errors = client.add_zone_acl_rule(shared_zone_test_context.ip4_reverse_zone['id'], acl_rule, status=400) - assert_that(errors, contains_string("Multiple record types including PTR must have no mask")) - - -@pytest.mark.serial -def test_create_acl_user_rule_multiple_none_success(shared_zone_test_context): - """ - Test creating an acl rule with multiple record types and no mask passes - """ - client = shared_zone_test_context.ok_vinyldns_client - - acl_rule = { - 'accessLevel': 'Read', - 'description': 'test-acl-user-id', - 'userId': 'ok', - 'recordTypes': ['PTR', 'A', 'AAAA'] - } - - result = client.add_zone_acl_rule_with_wait(shared_zone_test_context.ip4_reverse_zone['id'], acl_rule, status=202) - - # This is async, we get a zone change back - acl = result['zone']['acl'] - - verify_acl_rule_is_present_once(acl_rule, acl) - - # make sure that our acl rule appears on the zone - zone = client.get_zone(result['zone']['id'])['zone'] - - acl = zone['acl'] - - verify_acl_rule_is_present_once(acl_rule, acl) - - -def test_create_acl_user_rule_multiple_non_cidr_failure(shared_zone_test_context): - """ - Test creating an acl rule with multiple record types including PTR and non cidr mask fails - """ - client = shared_zone_test_context.ok_vinyldns_client - - acl_rule = { - 'accessLevel': 'Read', - 'description': 'test-acl-user-id', - 'userId': '789', - 'recordMask': 'www-*', - 'recordTypes': ['PTR', 'A', 'AAAA'] - } - - errors = client.add_zone_acl_rule(shared_zone_test_context.ip4_reverse_zone['id'], acl_rule, status=400) - assert_that(errors, contains_string("Multiple record types including PTR must have no mask")) - - -@pytest.mark.serial -def test_create_acl_idempotent(shared_zone_test_context): - """ - Test creating the same acl rule multiple times results in only one rule added - """ - client = shared_zone_test_context.ok_vinyldns_client - - acl_rule = { - 'accessLevel': 'Write', - 'description': 'test-acl-idempotent', - 'userId': 'ok', - 'recordMask': 'www-*', - 'recordTypes': ['A', 'AAAA', 'CNAME'] - } - result1 = client.add_zone_acl_rule_with_wait(shared_zone_test_context.system_test_zone['id'], acl_rule, status=202) - result2 = client.add_zone_acl_rule_with_wait(shared_zone_test_context.system_test_zone['id'], acl_rule, status=202) - result3 = client.add_zone_acl_rule_with_wait(shared_zone_test_context.system_test_zone['id'], acl_rule, status=202) - - zone = client.get_zone(shared_zone_test_context.system_test_zone['id'])['zone'] - - acl = zone['acl'] - - # we should only have one rule that we created - verify_acl_rule_is_present_once(acl_rule, acl) - - -@pytest.mark.serial -def test_delete_acl_group_rule_success(shared_zone_test_context): - """ - Test deleting an acl rule successfully - """ - client = shared_zone_test_context.ok_vinyldns_client - - acl_rule = { - 'accessLevel': 'Read', - 'description': 'test-acl-delete-group-id', - 'groupId': shared_zone_test_context.ok_group['id'], - 'recordMask': 'www-*', - 'recordTypes': ['A', 'AAAA', 'CNAME'] - } - result = client.add_zone_acl_rule_with_wait(shared_zone_test_context.system_test_zone['id'], acl_rule, status=202) - - # make sure that our acl rule appears on the zone - zone = client.get_zone(result['zone']['id'])['zone'] - - acl = zone['acl'] - - verify_acl_rule_is_present_once(acl_rule, acl) - - # delete the rule - result = client.delete_zone_acl_rule_with_wait(shared_zone_test_context.system_test_zone['id'], acl_rule, - status=202) - - # make sure that our acl is not on the zone - zone = client.get_zone(result['zone']['id'])['zone'] - - verify_acl_rule_is_not_present(acl_rule, zone['acl']) - - -@pytest.mark.serial -def test_delete_acl_user_rule_success(shared_zone_test_context): - """ - Test deleting an acl rule successfully - """ - client = shared_zone_test_context.ok_vinyldns_client - - acl_rule = { - 'accessLevel': 'Read', - 'description': 'test-acl-delete-user-id', - 'userId': 'ok', - 'recordMask': 'www-*', - 'recordTypes': ['A', 'AAAA', 'CNAME'] - } - result = client.add_zone_acl_rule_with_wait(shared_zone_test_context.system_test_zone['id'], acl_rule, status=202) - - # make sure that our acl rule appears on the zone - zone = client.get_zone(result['zone']['id'])['zone'] - - acl = zone['acl'] - - verify_acl_rule_is_present_once(acl_rule, acl) - - # delete the rule - result = client.delete_zone_acl_rule_with_wait(shared_zone_test_context.system_test_zone['id'], acl_rule, - status=202) - - # make sure that our acl is not on the zone - zone = client.get_zone(result['zone']['id'])['zone'] - - verify_acl_rule_is_not_present(acl_rule, zone['acl']) - - -def test_delete_non_existent_acl_rule_success(shared_zone_test_context): - """ - Test deleting an acl rule that doesn't exist still returns successfully - """ - client = shared_zone_test_context.ok_vinyldns_client - - acl_rule = { - 'accessLevel': 'Read', - 'description': 'test-acl-delete-non-existent-user-id', - 'userId': '789', - 'recordMask': 'www-*', - 'recordTypes': ['A', 'AAAA', 'CNAME'] - } - # delete the rule - result = client.delete_zone_acl_rule_with_wait(shared_zone_test_context.system_test_zone['id'], acl_rule, - status=202) - - # make sure that our acl is not on the zone - zone = client.get_zone(result['zone']['id'])['zone'] - - verify_acl_rule_is_not_present(acl_rule, zone['acl']) - - -@pytest.mark.serial -def test_delete_acl_idempotent(shared_zone_test_context): - """ - Test deleting the same acl rule multiple times results in only one rule remomved - """ - client = shared_zone_test_context.ok_vinyldns_client - - acl_rule = { - 'accessLevel': 'Write', - 'description': 'test-delete-acl-idempotent', - 'userId': 'ok', - 'recordMask': 'www-*', - 'recordTypes': ['A', 'AAAA', 'CNAME'] - } - result = client.add_zone_acl_rule_with_wait(shared_zone_test_context.system_test_zone['id'], acl_rule, status=202) - - zone = client.get_zone(shared_zone_test_context.system_test_zone['id'])['zone'] - - acl = zone['acl'] - - # we should only have one rule that we created - verify_acl_rule_is_present_once(acl_rule, acl) - - result1 = client.delete_zone_acl_rule_with_wait(shared_zone_test_context.system_test_zone['id'], acl_rule, - status=202) - result2 = client.delete_zone_acl_rule_with_wait(shared_zone_test_context.system_test_zone['id'], acl_rule, - status=202) - result3 = client.delete_zone_acl_rule_with_wait(shared_zone_test_context.system_test_zone['id'], acl_rule, - status=202) - - zone = client.get_zone(result['zone']['id'])['zone'] - - verify_acl_rule_is_not_present(acl_rule, zone['acl']) - - -@pytest.mark.serial -def test_delete_acl_removes_permissions(shared_zone_test_context): - """ - Test that a user (who previously had permissions to view a zone via acl rules) can still view the zone once - the acl rule is deleted - """ - - ok_client = shared_zone_test_context.ok_vinyldns_client # ok adds and deletes acl rule - dummy_client = shared_zone_test_context.dummy_vinyldns_client # dummy should not be able to see ok_zone once acl rule is deleted - ok_zone = ok_client.get_zone(shared_zone_test_context.ok_zone['id'])['zone'] - - ok_view = ok_client.list_zones()['zones'] - assert_that(ok_view, has_item(ok_zone)) # ok can see ok_zone - - # verify dummy cannot see ok_zone - dummy_view = dummy_client.list_zones()['zones'] - assert_that(dummy_view, is_not(has_item(ok_zone))) # cannot view zone - - # add acl rule - acl_rule = { - 'accessLevel': 'Read', - 'description': 'test_delete_acl_removes_permissions', - 'userId': 'dummy', # give dummy permission to see ok_zone - 'recordMask': 'www-*', - 'recordTypes': ['A', 'AAAA', 'CNAME'] - } - result = ok_client.add_zone_acl_rule_with_wait(shared_zone_test_context.ok_zone['id'], acl_rule, status=202) - ok_zone = ok_client.get_zone(shared_zone_test_context.ok_zone['id'])['zone'] - verify_acl_rule_is_present_once(acl_rule, ok_zone['acl']) - - ok_view = ok_client.list_zones()['zones'] - assert_that(ok_view, has_item(ok_zone)) # ok can still see ok_zone - - # verify dummy can see ok_zone - dummy_view = dummy_client.list_zones()['zones'] - ok_zone_dummy_view = dummy_client.list_zones(name_filter=ok_zone['name'])['zones'][0] - assert_that(dummy_view, has_item(has_entries(ok_zone_dummy_view))) # can view zone - - # delete acl rule - result = ok_client.delete_zone_acl_rule_with_wait(shared_zone_test_context.ok_zone['id'], acl_rule, status=202) - ok_zone = ok_client.get_zone(shared_zone_test_context.ok_zone['id'])['zone'] - verify_acl_rule_is_not_present(acl_rule, ok_zone['acl']) - - ok_view = ok_client.list_zones()['zones'] - assert_that(ok_view, has_item(ok_zone)) # ok can still see ok_zone - - # verify dummy can not see ok_zone - dummy_view = dummy_client.list_zones()['zones'] - assert_that(dummy_view, is_not(has_item(ok_zone_dummy_view))) # can still view zone - - -def test_update_reverse_v4_zone(shared_zone_test_context): - """ - Test updating a reverse IPv4 zone - """ - client = shared_zone_test_context.ok_vinyldns_client - - zone = shared_zone_test_context.ip4_reverse_zone - zone['email'] = 'update-test@bar.com' - - update_result = client.update_zone(zone, status=202) - client.wait_until_zone_change_status_synced(update_result) - - assert_that(update_result['changeType'], is_('Update')) - assert_that(update_result['userId'], is_('ok')) - assert_that(update_result, has_key('created')) - - get_result = client.get_zone(zone['id']) - - uz = get_result['zone'] - assert_that(uz['email'], is_('update-test@bar.com')) - assert_that(uz['updated'], is_not(none())) - - -def test_update_reverse_v6_zone(shared_zone_test_context): - """ - Test updating a reverse IPv6 zone - """ - client = shared_zone_test_context.ok_vinyldns_client - - zone = shared_zone_test_context.ip6_reverse_zone - zone['email'] = 'update-test@bar.com' - - update_result = client.update_zone(zone, status=202) - client.wait_until_zone_change_status_synced(update_result) - - assert_that(update_result['changeType'], is_('Update')) - assert_that(update_result['userId'], is_('ok')) - assert_that(update_result, has_key('created')) - - get_result = client.get_zone(zone['id']) - - uz = get_result['zone'] - assert_that(uz['email'], is_('update-test@bar.com')) - assert_that(uz['updated'], is_not(none())) - - -def test_activate_reverse_v4_zone_with_bad_key_fails(shared_zone_test_context): - """ - Test activating a reverse IPv4 zone when using a bad tsig key fails - """ - client = shared_zone_test_context.ok_vinyldns_client - - update = dict(shared_zone_test_context.ip4_reverse_zone) - update['connection']['key'] = 'f00sn+4G2ldMn0q1CV3vsg==' - client.update_zone(update, status=400) - - -def test_activate_reverse_v6_zone_with_bad_key_fails(shared_zone_test_context): - """ - Test activating a reverse IPv6 zone with an invalid key fails - """ - client = shared_zone_test_context.ok_vinyldns_client - - update = dict(shared_zone_test_context.ip6_reverse_zone) - update['connection']['key'] = 'f00sn+4G2ldMn0q1CV3vsg==' - client.update_zone(update, status=400) - - -def test_user_cannot_update_zone_to_nonexisting_admin_group(shared_zone_test_context): - """ - Test user cannot update a zone adminGroupId to a group that does not exist - """ - - zone_update = shared_zone_test_context.ok_zone - zone_update['adminGroupId'] = "some-bad-id" - zone_update['connection']['key'] = VinylDNSTestContext.dns_key - - shared_zone_test_context.ok_vinyldns_client.update_zone(zone_update, status=400) - - -@pytest.mark.serial -def test_user_can_update_zone_to_another_admin_group(shared_zone_test_context): - """ - Test user can update a zone with an admin group they are a member of - """ - - client = shared_zone_test_context.dummy_vinyldns_client - group = None - - try: - result = client.create_zone( - { - 'name': 'one-time.', - 'email': 'test@test.com', - 'adminGroupId': shared_zone_test_context.dummy_group['id'], - 'connection': { - 'name': 'vinyldns.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - }, - 'transferConnection': { - 'name': 'vinyldns.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - } - }, status=202 - ) - zone = result['zone'] - client.wait_until_zone_active(result[u'zone'][u'id']) - - import json - print json.dumps(zone, indent=3) - - new_joint_group = { - 'name': 'new-ok-group', - 'email': 'test@test.com', - 'description': 'this is a description', - 'members': [{'id': 'ok', 'id': 'dummy'}], - 'admins': [{'id': 'ok'}] - } - - group = client.create_group(new_joint_group, status=200) - - # changing the zone - zone_update = dict(zone) - zone_update['adminGroupId'] = group['id'] - - result = client.update_zone(zone_update, status=202) - client.wait_until_zone_change_status_synced(result) - finally: - if zone: - client.delete_zone(zone['id'], status=202) - client.wait_until_zone_deleted(zone['id']) - if group: - shared_zone_test_context.ok_vinyldns_client.delete_group(group['id'], status=(200, 404)) - - -@pytest.mark.serial -def test_user_cannot_update_zone_to_nonmember_admin_group(shared_zone_test_context): - """ - Test user cannot update a zone adminGroupId to a group they are not a member of - """ - # TODO: I don't know why this consistently fails but marking serial - # TODO: STRANGE! When doing ALL serially it returns 400, when separating PAR from SER it returns a 403 - # TODO: somehow changing the order of when this run changes the status code! Who is messing with the ok_zone? - zone_update = shared_zone_test_context.ok_zone - zone_update['adminGroupId'] = shared_zone_test_context.history_group['id'] - - shared_zone_test_context.ok_vinyldns_client.update_zone(zone_update, status=403) - - -@pytest.mark.serial -def test_acl_rule_missing_access_level(shared_zone_test_context): - """ - Tests that missing the access level when creating an acl rule returns a 400 - """ - client = shared_zone_test_context.ok_vinyldns_client - acl_rule = { - 'description': 'test-acl-no-access-level', - 'groupId': '456', - 'recordMask': 'www-*', - 'recordTypes': ['A', 'AAAA', 'CNAME'] - } - errors = client.add_zone_acl_rule(shared_zone_test_context.system_test_zone['id'], acl_rule, status=400)['errors'] - assert_that(errors, has_length(1)) - assert_that(errors, contains_inanyorder('Missing ACLRule.accessLevel')) - - -@pytest.mark.serial -def test_acl_rule_both_user_and_group(shared_zone_test_context): - """ - Tests that including the user id and the group id when creating an acl rule returns a 400 - """ - client = shared_zone_test_context.ok_vinyldns_client - acl_rule = { - 'accessLevel': 'Read', - 'userId': '789', - 'groupId': '456', - 'description': 'test-acl-no-user-or-group-level', - 'recordMask': 'www-*', - 'recordTypes': ['A', 'AAAA', 'CNAME'] - } - errors = client.add_zone_acl_rule(shared_zone_test_context.system_test_zone['id'], acl_rule, status=400)['errors'] - assert_that(errors, has_length(1)) - assert_that(errors, contains_inanyorder('Cannot specify both a userId and a groupId')) - - -def test_update_zone_no_authorization(shared_zone_test_context): - """ - Test updating a zone without authorization - """ - client = shared_zone_test_context.ok_vinyldns_client - - zone = { - 'id': '12345', - 'name': str(uuid.uuid4()), - 'email': 'test@test.com', - } - - client.update_zone(zone, sign_request=False, status=401) - - -def test_normal_user_cannot_update_shared_zone_flag(shared_zone_test_context): - """ - Test updating a zone shared status as a normal user fails - """ - client = shared_zone_test_context.ok_vinyldns_client - - result = client.get_zone(shared_zone_test_context.ok_zone['id'], status=200) - zone_update = result['zone'] - zone_update['shared'] = True - - error = shared_zone_test_context.ok_vinyldns_client.update_zone(zone_update, status=403) - assert_that(error, contains_string('Not authorized to update zone shared status from false to true.')) - - -def test_toggle_test_flag(shared_zone_test_context): - """ - Test the isTest flag is ignored in update requests - """ - client = shared_zone_test_context.shared_zone_vinyldns_client - zone_update = shared_zone_test_context.non_test_shared_zone - zone_update['isTest'] = True - - change = client.update_zone(zone_update, status=202) - client.wait_until_zone_change_status_synced(change) - - assert_that(change['zone']['isTest'], is_(False)) - - -@pytest.mark.serial -def test_update_connection_info_success(shared_zone_test_context): - """ - Test user can update zone to backendId instead of connection info - """ - client = shared_zone_test_context.ok_vinyldns_client - zone = shared_zone_test_context.system_test_zone - - # validating current zone state - to_update = client.get_zone(zone['id'])['zone'] - assert_that(to_update, has_key('connection')) - assert_that(to_update, has_key('transferConnection')) - - to_update.pop('connection') - to_update.pop('transferConnection') - to_update['backendId'] = 'func-test-backend' - test_rs = None - try: - change = client.update_zone(to_update, status=202) - client.wait_until_zone_change_status_synced(change) - new_zone = change['zone'] - - assert_that(new_zone, is_not(has_key('connection'))) - assert_that(new_zone, is_not(has_key('transferConnection'))) - assert_that(new_zone['backendId'], is_('func-test-backend')) - - # test adding a recordset - validates the key - new_rs = get_recordset_json(new_zone, 'test-update-connection-info-success', 'CNAME', - [{'cname': 'test-cname.'}]) - create_rs = client.create_recordset(new_rs, status=202) - test_rs = client.wait_until_recordset_change_status(create_rs, 'Complete')['recordSet'] - finally: - revert = client.update_zone(zone, status=202) - client.wait_until_zone_change_status_synced(revert) - if test_rs: - delete_result = client.delete_recordset(test_rs['zoneId'], test_rs['id'], status=202) - client.wait_until_recordset_change_status(delete_result, 'Complete') - - -def test_update_connection_info_invalid_backendid(shared_zone_test_context): - """ - Test user can update zone to bad backendId fails - """ - client = shared_zone_test_context.ok_vinyldns_client - zone = shared_zone_test_context.ok_zone - - to_update = client.get_zone(zone['id'])['zone'] - to_update.pop('connection') - to_update.pop('transferConnection') - to_update['backendId'] = 'bad-backend-id' - - result = client.update_zone(to_update, status=400) - assert_that(result, contains_string("Invalid backendId")) diff --git a/modules/api/functional_test/perf_tests/uat_sync_test.py b/modules/api/functional_test/perf_tests/uat_sync_test.py deleted file mode 100644 index 3bb6fe863..000000000 --- a/modules/api/functional_test/perf_tests/uat_sync_test.py +++ /dev/null @@ -1,63 +0,0 @@ -from hamcrest import * -from vinyldns_client import VinylDNSClient -from vinyldns_context import VinylDNSTestContext -import time - -def test_sync_zone_success(): - """ - Test syncing a zone - """ - zone_name = 'small' - client = VinylDNSClient() - - zones = client.list_zones()['zones'] - zone = [z for z in zones if z['name'] == zone_name + "."] - - lastLatestSync = [] - new = True - if zone: - zone = zone[0] - lastLatestSync = zone['latestSync'] - new = False - - else: - # create zone if it doesnt exist - zone = { - 'name': zone_name, - 'email': 'test@test.com', - 'connection': { - 'name': 'vinyldns.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - }, - 'transferConnection': { - 'name': 'vinyldns.', - 'keyName': VinylDNSTestContext.dns_key_name, - 'key': VinylDNSTestContext.dns_key, - 'primaryServer': VinylDNSTestContext.dns_ip - } - } - zone_change = client.create_zone(zone, status=202) - zone = zone_change['zone'] - client.wait_until_zone_active(zone_change[u'zone'][u'id']) - - zone_id = zone['id'] - - # run sync - change = client.sync_zone(zone_id, status=202) - - # brief wait for zone status change. Can't use getZoneHistory here to check on the changeset itself, - # the action times out (presumably also querying the same record change table that the sync itself - # is interacting with) - time.sleep(0.5) - client.wait_until_zone_status(zone_id, 'Active') - - # confirm zone has been updated - get_result = client.get_zone(zone_id) - synced_zone = get_result['zone'] - latestSync = synced_zone['latestSync'] - assert_that(synced_zone['updated'], is_not(none())) - assert_that(latestSync, is_not(none())) - if not new: - assert_that(latestSync, is_not(lastLatestSync)) diff --git a/modules/api/functional_test/requirements.txt b/modules/api/functional_test/requirements.txt deleted file mode 100644 index ee3576feb..000000000 --- a/modules/api/functional_test/requirements.txt +++ /dev/null @@ -1,15 +0,0 @@ -# requirements.txt v1.0 -# --------------------- -# Add project specific python requirements to this file. -# Do not commit them in the project! -# Make sure they exist on our corporate PyPi server. - -pyhamcrest==1.8.0 -pytz>=2014 -pytest==4.4.1 -mock==1.0.1 -dnspython==1.14.0 -boto==2.48.0 -future==0.17.0 -requests==2.20.0 -pytest-xdist==1.29.0 diff --git a/modules/api/functional_test/run.py b/modules/api/functional_test/run.py deleted file mode 100755 index 10b4ed671..000000000 --- a/modules/api/functional_test/run.py +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env python -import os -import sys - -basedir = os.path.dirname(os.path.realpath(__file__)) -vedir = os.path.join(basedir, '.virtualenv') -os.system('./bootstrap.sh') - -activate_virtualenv = os.path.join(vedir, 'bin', 'activate_this.py') -print('Activating virtualenv at ' + activate_virtualenv) - -report_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), '../target/pytest_reports') -if not os.path.exists(report_dir): - os.system('mkdir -p ' + report_dir) - -execfile(activate_virtualenv, dict(__file__=activate_virtualenv)) - -import pytest -result = pytest.main(list(sys.argv[1:])) - -sys.exit(result) - - diff --git a/modules/api/functional_test/vinyldns_context.py b/modules/api/functional_test/vinyldns_context.py deleted file mode 100644 index b9308add9..000000000 --- a/modules/api/functional_test/vinyldns_context.py +++ /dev/null @@ -1,18 +0,0 @@ -class VinylDNSTestContext: - dns_ip = 'localhost' - dns_zone_name = 'vinyldns.' - dns_rev_v4_zone_name = '10.10.in-addr.arpa.' - dns_rev_v6_zone_name = '1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa.' - dns_key_name = 'vinyldns.' - dns_key = 'nzisn+4G2ldMn0q1CV3vsg==' - vinyldns_url = 'http://localhost:9000' - teardown = True - - @staticmethod - def configure(ip, zone, key_name, key, url, teardown): - VinylDNSTestContext.dns_ip = ip - VinylDNSTestContext.dns_zone_name = zone - VinylDNSTestContext.dns_key_name = key_name - VinylDNSTestContext.dns_key = key - VinylDNSTestContext.vinyldns_url = url - VinylDNSTestContext.teardown = teardown.lower() == 'true' diff --git a/modules/api/functional_test/zone_inject.py b/modules/api/functional_test/zone_inject.py deleted file mode 100644 index 111058e17..000000000 --- a/modules/api/functional_test/zone_inject.py +++ /dev/null @@ -1,48 +0,0 @@ -import requests -import json - -newzone = "http://localhost:9000/zones" - - -names = ["cap", "video", "aae", "papi", "dns-ops", "ios", "home", "android", "games", "viper", "headwaters", "xtv", "consec", "media", "accounts"]; - -records = ["10.25.3.2","155.65.10.3", "10.1.1.1", "168.82.76.5", "192.168.99.88", "FE80:0000:0000:0000:0202:B3FF:FE1E:8329", "GF77:0000:0000:0000:0411:B3DF:FE2E:4444", "CC42:0000:0000:0000:0509:B3FF:FE3E:6543", "BG50:0000:0000:0000:0203:C2EE:G3F4:9823","AA90:0000:0000:0000:0608:C2EE:FE4E:1234", "staging", "test", "admin", "assets", "admin"]; - -for x in range(0, 15): - zonename = names[x] - zoneemail = 'testuser'+ str(x) +'@example.com' - payload = {"name": zonename, "origin": "vinyldns", "email": zoneemail} - headers = {'Content-type': 'application/json'} - r = requests.post(newzone, data=json.dumps(payload),headers=headers) - print(r.text) - - -zones = requests.get(newzone) -zone_data = zones.json() - -z=0 -for i in zone_data['zones']: - if z<5: - z=z+1 - recurl = newzone + '/' + str(i['id']) + '/recordsets' - print recurl - payload = {"zoneId":i['id'],"name":"record."+i['name'],"type":"A","ttl":300,"records":[{"address":records[z-1]}]} - headers = {'Content-type': 'application/json'} - r = requests.post(recurl, data=json.dumps(payload),headers=headers) - print(r.text) - elif 4 -``` +```json [ { "changeType": "Add", @@ -46,7 +46,7 @@ in the DNS backend. "cname": "test.example.com." }, "errors": [ - "Record with name "duplicate.example.com." is not unique in the batch change. CNAME record cannot use duplicate name." + "Record with name \"duplicate.example.com.\" is not unique in the batch change. CNAME record cannot use duplicate name." ] }, { @@ -60,7 +60,7 @@ in the DNS backend. }, { "changeType": "Add", - "inputName": "bad-ttl-and-invalid-name$.sample.com.”, + "inputName": "bad-ttl-and-invalid-name$.sample.com.", "type": "A", "ttl": 29, "record": { @@ -127,14 +127,14 @@ the VinylDNS instance is configured to have manual review disabled. - [Missing Owner Group Id](#MissingOwnerGroupId) - [Not a Member of Owner Group](#NotAMemberOfOwnerGroup) - [High Value Domain](#HighValueDomain) -- [CNAME Cannot be the Same Name as Zone Name]("CnameApexError") +- [CNAME Cannot be the Same Name as Zone Name](#CnameApexError) ### Non-Fatal Errors #### Zone Discovery Failed ##### Error Message: -``` +```plaintext Zone Discovery Failed: zone for "" does not exist in VinylDNS. If zone exists, then it must be connected to in VinylDNS. ``` @@ -143,7 +143,7 @@ Zone Discovery Failed: zone for "" does not exist in VinylDNS. If zone ex Given an inputName, VinylDNS will determine the record and zone name for the requested change. For most records, the record names are the same as the zone name (apex), or split at at the first '.', so the inputName 'rname.zone.name.com' will be split into record name 'rname' and zone name 'zone.name.com' (or 'rname.zone.name.com' for both the record and zone name if it's an apex record). -For PTR records, there is logic to determine the appropriate reverse zone from the given IP address. +For `PTR` records, there is logic to determine the appropriate reverse zone from the given IP address. If this logic cannot find a matching zone in VinylDNS, you will see this error. In that case, you need to connect to the zone in VinylDNS. @@ -155,7 +155,7 @@ this error could indicate that a zone needs to be created outside of VinylDNS an ##### Error Message: -``` +```plaintext Record set with name requires manual review. ``` @@ -168,7 +168,7 @@ Based on a [configurable list](../operator/config-api.html#manual-review-domains ##### Error Message: -``` +```plaintext Invalid domain name: "", valid domain names must be letters, numbers, underscores, and hyphens, joined by dots, and terminate with a dot. ``` @@ -180,7 +180,7 @@ They must also be absolute, which means they end with a dot. Syntax: -``` +```bnf ::= | " " ::=

- +
@@ -142,65 +139,22 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + @pagePlugins diff --git a/modules/portal/app/views/recordsets/recordSets.scala.html b/modules/portal/app/views/recordsets/recordSets.scala.html index a822b7573..cc55d54c7 100644 --- a/modules/portal/app/views/recordsets/recordSets.scala.html +++ b/modules/portal/app/views/recordsets/recordSets.scala.html @@ -374,9 +374,7 @@ } @plugins = { - - - + } @main(rootAccountName)("RecordSetsController")("RecordSets")(content)(plugins) diff --git a/modules/portal/app/views/setOidcSession.scala.html b/modules/portal/app/views/setOidcSession.scala.html index a22304352..43ef9f1f1 100644 --- a/modules/portal/app/views/setOidcSession.scala.html +++ b/modules/portal/app/views/setOidcSession.scala.html @@ -1,17 +1,25 @@ @(setSessionUrl: String)(implicit requestHeader: RequestHeader) - - + + Login - - + + + Finishing login, if not redirected, click this link - - + + diff --git a/modules/portal/app/views/systemMessage.scala.html b/modules/portal/app/views/systemMessage.scala.html index 8a87b34e0..687fcddc3 100644 --- a/modules/portal/app/views/systemMessage.scala.html +++ b/modules/portal/app/views/systemMessage.scala.html @@ -12,8 +12,9 @@ - - + + + diff --git a/modules/portal/app/views/zones/zoneDetail.scala.html b/modules/portal/app/views/zones/zoneDetail.scala.html index de9a53dcc..dc8b06c33 100644 --- a/modules/portal/app/views/zones/zoneDetail.scala.html +++ b/modules/portal/app/views/zones/zoneDetail.scala.html @@ -68,10 +68,7 @@ } @plugins = { - - - - + } @main(rootAccountName)("RecordsController")("Zone")(content)(plugins) diff --git a/modules/portal/app/views/zones/zones.scala.html b/modules/portal/app/views/zones/zones.scala.html index ed0cee221..52ab8b759 100644 --- a/modules/portal/app/views/zones/zones.scala.html +++ b/modules/portal/app/views/zones/zones.scala.html @@ -267,9 +267,7 @@ } @plugins = { - - - + } @main(rootAccountName)("ZonesController")("Zones")(content)(plugins) diff --git a/modules/portal/conf/application.conf b/modules/portal/conf/application.conf index f6d6c77b6..f6324fd54 100644 --- a/modules/portal/conf/application.conf +++ b/modules/portal/conf/application.conf @@ -1,23 +1,62 @@ -http.port = 9001 +LDAP { + # For OpenLDAP, this would be a full DN to the admin for LDAP / user that can see all users + user = "cn=admin,dc=planetexpress,dc=com" -crypto { - type = "vinyldns.core.crypto.JavaCrypto" - secret = "8B06A7F3BC8A2497736F1916A123AA40E88217BE9264D8872597EF7A6E5DCE61" -} + # Password for the admin account + password = "GoodNewsEveryone" -data-stores = ["mysql"] -data-stores = ${?DATA_STORES} + # Keep this as an empty string for OpenLDAP + domain = "" -mysql { - repositories { - user { - } - task { - } - user-change { - } + # This will be the name of the LDAP field that carries the user's login id (what they enter in the username in login form) + userNameAttribute = "uid" + + # For organization, leave empty for this demo, the domainName is what matters, and that is the LDAP structure + # to search for users that require login + searchBase = [ + {organization = "", domainName = "ou=people,dc=planetexpress,dc=com"}, + ] + context { + initialContextFactory = "com.sun.jndi.ldap.LdapCtxFactory" + initialContextFactory = ${?LDAP_INITIAL_CONTEXT_CLASS} + securityAuthentication = "simple" + securityAuthentication = ${?LDAP_SECURITY_AUTH} + + # Note: The following assumes a purely docker setup, using container_name = vinyldns-ldap + providerUrl = "ldap://localhost:19004" + providerUrl = ${?LDAP_PROVIDER_URL} + } + + # This is only needed if keeping vinyldns user store in sync with ldap (to auto lock out users who left your + # company for example) + user-sync { + enabled = false + enabled = ${?USER_SYNC_ENABLED} + hours-polling-interval = 1 + hours-polling-interval = ${?USER_SYNC_POLL_INTERVAL} } } -// Local.conf has files specific to your environment, for example your own LDAP settings +# Note: This MUST match the API or strange errors will ensue, NoOpCrypto should not be used for production +crypto { + type = "vinyldns.core.crypto.NoOpCrypto" + type = ${?CRYPTO_TYPE} + secret = ${?CRYPTO_SECRET} +} + +http.port = 9001 +http.port = ${?PORTAL_PORT} + +data-stores = ["mysql"] + +# Must be true to manage shared zones through the portal +shared-display-enabled = true +shared-display-enabled = ${?SHARED_ZONES_ENABLED} + +# You generate this yourself following https://www.playframework.com/documentation/2.7.x/ApplicationSecret +play.http.secret.key = "changeme" +play.http.secret.key = ${?PLAY_HTTP_SECRET_KEY} + +# You can provide configuration overrides via local.conf if you don't want to replace everything in +# this configuration file include "local.conf" diff --git a/modules/portal/dist/wait-for-dependencies.sh b/modules/portal/dist/wait-for-dependencies.sh deleted file mode 100755 index 4222ff00c..000000000 --- a/modules/portal/dist/wait-for-dependencies.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env bash - -# allow skipping with env var -if [ "$SKIP_MYSQL_WAIT" -eq "1" ]; then - exit 0 -fi - -# the mysql address, default to a local docker setup -MYSQL_ADDRESS=${MYSQL_ADDRESS:-vinyldns-mysql} -MYSQL_PORT=${MYSQL_PORT:-3306} -echo "Waiting for MYSQL to be ready on ${MYSQL_ADDRESS}:${MYSQL_PORT}" -DATA="" -RETRY=30 -while [ "$RETRY" -gt 0 ] -do - DATA=$(nc -vzw1 "$MYSQL_ADDRESS" "$MYSQL_PORT") - if [ $? -eq 0 ] - then - break - else - echo "Retrying" >&2 - - let RETRY-=1 - sleep .5 - - if [ "$RETRY" -eq 0 ] - then - echo "Exceeded retries waiting for MYSQL to be ready on ${MYSQL_ADDRESS}:${MYSQL_PORT}, failing" - return 1 - fi - fi -done diff --git a/modules/portal/karma.conf.js b/modules/portal/karma.conf.js index f0e1f2342..6f18b11c1 100644 --- a/modules/portal/karma.conf.js +++ b/modules/portal/karma.conf.js @@ -5,71 +5,76 @@ const puppeteer = require('puppeteer'); process.env.CHROME_BIN = puppeteer.executablePath(); module.exports = function(config) { - config.set({ - // base path, that will be used to resolve files and exclude - basePath: 'public/', + config.set({ + // base path, that will be used to resolve files and exclude + basePath: 'public/', - // testing framework to use (jasmine/mocha/qunit/...) - frameworks: ['jasmine'], + // testing framework to use (jasmine/mocha/qunit/...) + frameworks: ['jasmine'], - // list of files / patterns to load in the browser - files: [ - 'javascripts/moment.min.js', - 'gentelella/vendors/jquery/dist/jquery.min.js', - 'gentelella/vendors/bootstrap/dist/js/bootstrap.min.js', - 'gentelella/vendors/bootstrap-daterangepicker/daterangepicker.js', - 'javascripts/angular.min.js', - 'test_frameworks/*.js', - 'lib/services/**/*.js', - 'lib/controllers/**/*.js', - 'lib/directives/**/*.js', - 'lib/batch-change/batch-change.module.js', - 'lib/*.js', - 'lib/batch-change/*.js', - //fixtures - {pattern: 'mocks/*.json', watched: true, served: true, included: false} - ], + // list of files / patterns to load in the browser + files: [ + 'js/jquery.min.js', + 'js/bootstrap.min.js', + 'js/angular.min.js', + 'js/moment.min.js', + 'js/ui.js', + 'test_frameworks/*.js', + 'js/vinyldns.js', + 'lib/services/**/*.spec.js', + 'lib/controllers/**/*.spec.js', + 'lib/directives/**/*.spec.js', + 'lib/*.js', + //fixtures + {pattern: 'mocks/*.json', watched: true, served: true, included: false}, + ], - // list of files / patterns to exclude - exclude: [], + // list of files / patterns to exclude + exclude: [], - // web server port - port: 8080, + // web server port + port: 8080, - // level of logging - // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG - logLevel: config.LOG_INFO, - - plugins: [ - 'karma-jasmine', - 'karma-chrome-launcher', - 'karma-mocha-reporter' - ], + // level of logging + // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG + logLevel: config.LOG_INFO, - // reporter types: - // - dots - // - progress (default) - // - spec (karma-spec-reporter) - // - junit - // - growl - // - coverage - reporters: ['mocha'], + plugins: [ + 'karma-jasmine', + 'karma-chrome-launcher', + 'karma-mocha-reporter', + ], - // enable / disable watching file and executing tests whenever any file changes - autoWatch: true, + // reporter types: + // - dots + // - progress (default) + // - spec (karma-spec-reporter) + // - junit + // - growl + // - coverage + reporters: ['mocha'], - // Start these browsers, currently available: - // - Chrome - // - ChromeCanary - // - Firefox - // - Opera - // - Safari (only Mac) - // - PhantomJS - // - IE (only Windows) - browsers: ['ChromeHeadless'], + // enable / disable watching file and executing tests whenever any file changes + autoWatch: true, - // Continuous Integration mode - // if true, it capture browsers, run tests and exit - singleRun: true - }); + // Start these browsers, currently available: + // - Chrome + // - ChromeCanary + // - Firefox + // - Opera + // - Safari (only Mac) + // - PhantomJS + // - IE (only Windows) + browsers: ['ChromeHeadlessNoSandbox'], + customLaunchers: { + ChromeHeadlessNoSandbox: { + base: 'ChromeHeadless', + flags: ['--no-sandbox'], + }, + }, + + // Continuous Integration mode + // if true, it capture browsers, run tests and exit + singleRun: true, + }); }; diff --git a/modules/portal/package.json b/modules/portal/package.json index a6cc2fedc..dbe985fe7 100644 --- a/modules/portal/package.json +++ b/modules/portal/package.json @@ -1,27 +1,21 @@ { "name": "vinyl-portal", "version": "1.0.0", - "description": "Self-service DNS offering", "main": "index.js", "directories": { "test": "test" }, "dependencies": { - "@uirouter/angularjs": "0.3.2", - "angular": ">=1.6.0", - "angular-animate": "1.6.1", - "angular-ui-bootstrap": "2.5.6", - "bootstrap": "^4.3.1", - "font-awesome": "4.7.0", - "gentelella": "https://github.com/colorlibhq/gentelella.git#eea0150c65d51cb1f1a03f18bcc3bfa2a8db9312", + "angular": "^1.8.2", + "bootstrap": "^3.4.1", + "font-awesome": "^4.7.0", + "gentelella": "git+https://github.com/colorlibhq/gentelella.git#eea0150c65d51cb1f1a03f18bcc3bfa2a8db9312", "grunt": "^1.0.4", - "grunt-angular-templates": "^1.1.0", "grunt-contrib-clean": "^1.0.0", "grunt-contrib-copy": "^1.0.0", - "grunt-copy": "^0.1.0", - "grunt-injector": "^1.1.0", + "grunt-contrib-concat": "^2.0.0", "moment": "^2.24.0", - "puppeteer": "^1.11.0" + "puppeteer": "^3.0.0" }, "devDependencies": { "angular-mocks": "1.6.1", @@ -29,7 +23,7 @@ "grunt-mocha-phantomjs": "^3.0.0", "jasmine-core": "^2.99.1", "jasmine-jquery": "2.1.1", - "jquery": "^3.4.1", + "jquery": "^2.2.4", "karma": "^2.0.5", "karma-chrome-launcher": "^2.2.0", "karma-jasmine": "^1.0.2", diff --git a/modules/portal/prepare-portal.sh b/modules/portal/prepare-portal.sh index 757d3e114..316dfcddd 100755 --- a/modules/portal/prepare-portal.sh +++ b/modules/portal/prepare-portal.sh @@ -1,12 +1,10 @@ #!/usr/bin/env bash -DIR=$( cd $(dirname $0) ; pwd -P ) +set -euo pipefail +DIR=$( cd "$(dirname "$0")" ; pwd -P ) -cd $DIR - -npm install -f +cd "${DIR}" +npm install -f --no-audit --no-fund npm install grunt -g -f -grunt default -$DIR/../../bin/add-license-headers.sh -d=$DIR/public/lib -f=js -cd - +grunt default diff --git a/modules/portal/public/app.js b/modules/portal/public/app.js index 0a4e7105e..98cd98de0 100644 --- a/modules/portal/public/app.js +++ b/modules/portal/public/app.js @@ -45,8 +45,12 @@ angular.module('vinyldns', [ }; }); -var regexIso8601 = /(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))/; +// Workaround for jQuery SECVULN (https://github.com/advisories/GHSA-gxr4-xjj5-5px2) +jQuery.htmlPrefilter = function( html ) { + return html; +}; +var regexIso8601 = /(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))/; function convertDateStringsToDates(input) { if (typeof input !== "object") return input; diff --git a/modules/portal/public/css/theme-overrides.css b/modules/portal/public/css/theme-overrides.css index 136ac2214..b1742a8d9 100644 --- a/modules/portal/public/css/theme-overrides.css +++ b/modules/portal/public/css/theme-overrides.css @@ -1,3 +1,18 @@ +/* +* Copyright 2018 Comcast Cable Communications Management, LLC +* +* Licensed under the Apache License, Version 2.0 (the \"License\"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an \"AS IS\" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ body { color: #000; } diff --git a/modules/portal/public/css/vinyldns.css b/modules/portal/public/css/vinyldns.css index e0100d93f..88768b9a2 100644 --- a/modules/portal/public/css/vinyldns.css +++ b/modules/portal/public/css/vinyldns.css @@ -1,3 +1,18 @@ +/* +* Copyright 2018 Comcast Cable Communications Management, LLC +* +* Licensed under the Apache License, Version 2.0 (the \"License\"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an \"AS IS\" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { display: none !important; } diff --git a/modules/portal/public/js/custom.js b/modules/portal/public/js/custom.js index f560e432e..cec2a53c0 100644 --- a/modules/portal/public/js/custom.js +++ b/modules/portal/public/js/custom.js @@ -1,35 +1,39 @@ -var CURRENT_URL = window.location.href.split('#')[0].split('?')[0], - $MENU_INDENT = $('#menu_indent'), +/* +* Copyright 2018 Comcast Cable Communications Management, LLC +* +* Licensed under the Apache License, Version 2.0 (the \"License\"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an \"AS IS\" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +const $MENU_INDENT = $('#menu_indent'), $MENU_DEDENT = $('#menu_dedent'), $MENU_MOBILE = $('#menu_mobile'), $BODY = $('body'), $SIDEBAR_MENU = $('#sidebar-menu'); $MENU_INDENT.on('click', function() { - console.log('clicked - menu indent'); - console.log("HEEEEEEY!") + $SIDEBAR_MENU.find('li.active-sm ul').show(); + $SIDEBAR_MENU.find('li.active-sm').addClass('active').removeClass('active-sm'); - $SIDEBAR_MENU.find('li.active-sm ul').show(); - $SIDEBAR_MENU.find('li.active-sm').addClass('active').removeClass('active-sm'); - - - $BODY.addClass('nav-md').removeClass('nav-sm'); + $BODY.addClass('nav-md').removeClass('nav-sm'); }); $MENU_DEDENT.on('click', function() { - console.log('clicked - menu dedent'); - console.log("HEEEEEEY!") + $SIDEBAR_MENU.find('li.active ul').hide(); + $SIDEBAR_MENU.find('li.active').addClass('active-sm').removeClass('active'); - $SIDEBAR_MENU.find('li.active ul').hide(); - $SIDEBAR_MENU.find('li.active').addClass('active-sm').removeClass('active'); - - $BODY.addClass('nav-sm').removeClass('nav-md'); + $BODY.addClass('nav-sm').removeClass('nav-md'); }); $MENU_MOBILE.on('click', function() { - console.log('clicked - menu indent'); - console.log("HEEEEEEY!") - if ($BODY.hasClass('nav-md')) { $SIDEBAR_MENU.find('li.active ul').hide(); $SIDEBAR_MENU.find('li.active').addClass('active-sm').removeClass('active'); diff --git a/modules/portal/public/lib/controllers/controller.zones.js b/modules/portal/public/lib/controllers/controller.zones.js index 6813cdfb6..8159be547 100644 --- a/modules/portal/public/lib/controllers/controller.zones.js +++ b/modules/portal/public/lib/controllers/controller.zones.js @@ -67,7 +67,7 @@ angular.module('controller.zones', []) }); $scope.canAccessGroup = function(groupId) { - return $scope.myGroupIds.indexOf(groupId) > -1; + return $scope.myGroupIds !== "undefined" && $scope.myGroupIds.indexOf(groupId) > -1; }; $scope.canAccessZone = function(accessLevel) { diff --git a/modules/portal/public/lib/dns-change/dns-change-new.controller.js b/modules/portal/public/lib/dns-change/dns-change-new.controller.js index 70848ee76..5f0e6c842 100644 --- a/modules/portal/public/lib/dns-change/dns-change-new.controller.js +++ b/modules/portal/public/lib/dns-change/dns-change-new.controller.js @@ -56,7 +56,6 @@ }; $scope.confirmSubmit = function(form) { - console.log(form.$error) if(form.$invalid){ form.$setSubmitted(); $scope.formStatus = "pendingSubmit"; @@ -93,7 +92,6 @@ if(entry.changeType == 'DeleteRecordSet' && entry.record) { var recordDataEmpty = true; for (var attr in entry.record) { - console.log(entry.record[attr]) if (entry.record[attr] != undefined && entry.record[attr].toString().length > 0) { recordDataEmpty = false } @@ -177,17 +175,30 @@ $scope.$apply() resolve($scope.newBatch.changes.length); } else { - reject("Import failed. Not a valid file."); + reject("Import failed. Not a valid file. File should be of ‘.csv’ type."); } } reader.readAsText(file); }); } + function decode(str) { + // regex from: + // https://www.bennadel.com/blog/1504-ask-ben-parsing-csv-strings-with-javascript-exec-regular-expression-command.htm + // matches[0] is full match text with delimiter if any + // matches[1] is delimiter (usually ',') + // matches[2] is quoted field or undefined, internal quotes are doubled by convention + // matches[3] is standard field or undefined + // one of [2] or [3] will be undefined + const regex = /(,|\r?\n|\r|^)(?:"([^"]*(?:""[^"]*)*)"|([^,\r\n]*))/gi; + const matches = [...str.matchAll(regex)]; + return matches.map(match => match[2] !== undefined ? match[2].replace(/""/g, '"') : match[3]); + } + function parseRow(row) { var change = {}; var headers = ["changeType", "type", "inputName", "ttl", "record"]; - var rowContent = row.split(","); + var rowContent = decode(row); for (var j = 0; j < rowContent.length; j++) { if (headers[j] == "changeType") { if (rowContent[j].match(/add/i)) { @@ -206,6 +217,8 @@ change[headers[j]] = {"cname": rowContent[j].trim()} } else if (change["type"] == "PTR") { change[headers[j]] = {"ptrdname": rowContent[j].trim()} + } else if (change["type"] == "TXT") { + change[headers[j]] = {"text": rowContent[j].trim()} } } else { change[headers[j]] = rowContent[j].trim() diff --git a/modules/portal/public/lib/dns-change/dns-change.spec.js b/modules/portal/public/lib/dns-change/dns-change.spec.js index c626d8e7d..b6dfab9d9 100644 --- a/modules/portal/public/lib/dns-change/dns-change.spec.js +++ b/modules/portal/public/lib/dns-change/dns-change.spec.js @@ -549,7 +549,7 @@ describe('BatchChange', function(){ expect(this.scope.change.cname).toBeUndefined(); expect(form.cname.$valid).toBe(false); }); - } + }); describe('Directive: IPv4 validation', function(){ var form; diff --git a/modules/portal/public/lib/recordset/recordsets.controller.js b/modules/portal/public/lib/recordset/recordsets.controller.js index 431f77fa8..b23ccb9a4 100644 --- a/modules/portal/public/lib/recordset/recordsets.controller.js +++ b/modules/portal/public/lib/recordset/recordsets.controller.js @@ -37,7 +37,6 @@ function success(response) { recordsPaging.next = response.data.nextId; updateRecordDisplay(response.data['recordSets']); - console.log($scope.records); } return recordsService @@ -57,7 +56,6 @@ }); function handleError(error, type) { - console.log(error); var alert = utilityService.failure(error, type); $scope.alerts.push(alert); $scope.processing = false; diff --git a/modules/portal/public/lib/services/records/service.records.spec.js b/modules/portal/public/lib/services/records/service.records.spec.js index 4538c0178..4ba958fb8 100644 --- a/modules/portal/public/lib/services/records/service.records.spec.js +++ b/modules/portal/public/lib/services/records/service.records.spec.js @@ -101,16 +101,16 @@ describe('Service: recordsService', function () { "name": 'recordName', "type": 'SSHFP', "ttl": '300', - "sshfpItems": [{algorithm: '1', type: '1', fingerprint: 'foo'}, - {algorithm: '2', type: '1', fingerprint: 'bar'}] + "sshfpItems": [{algorithm: '1', type: '1', fingerprint: '123456789ABCDEF67890123456789ABCDEF67890'}, + {algorithm: '2', type: '1', fingerprint: '123456789ABCDEF67890123456789ABCDEF67890'}] }; expectedRecord = { "id": 'recordId', "name": 'recordName', "type": 'SSHFP', "ttl": 300, - "records": [{algorithm: 1, type: 1, fingerprint: 'foo'}, - {algorithm: 2, type: 1, fingerprint: 'bar'}] + "records": [{algorithm: 1, type: 1, fingerprint: '123456789ABCDEF67890123456789ABCDEF67890'}, + {algorithm: 2, type: 1, fingerprint: '123456789ABCDEF67890123456789ABCDEF67890'}] }; var actualRecord = this.recordsService.toVinylRecord(sentRecord); @@ -123,8 +123,8 @@ describe('Service: recordsService', function () { "name": 'recordName', "type": 'SSHFP', "ttl": 300, - "records": [{algorithm: 1, type: 1, fingerprint: 'foo'}, - {algorithm: 2, type: 1, fingerprint: 'bar'}] + "records": [{algorithm: 1, type: 1, fingerprint: '123456789ABCDEF67890123456789ABCDEF67890'}, + {algorithm: 2, type: 1, fingerprint: 'F23456789ABCDEF67890123456789ABCDEF67890'}] }; displayRecord = { @@ -133,8 +133,8 @@ describe('Service: recordsService', function () { "type": 'SSHFP', "ttl": 300, "records": undefined, - "sshfpItems": [{algorithm: 1, type: 1, fingerprint: 'foo'}, - {algorithm: 2, type: 1, fingerprint: 'bar'}], + "sshfpItems": [{algorithm: 1, type: 1, fingerprint: '123456789ABCDEF67890123456789ABCDEF67890'}, + {algorithm: 2, type: 1, fingerprint: 'F23456789ABCDEF67890123456789ABCDEF67890'}], "onlyFour": true, "isDotted": false, "canBeEdited": true @@ -150,8 +150,8 @@ describe('Service: recordsService', function () { "name": 'recordName.with.dot', "type": 'SSHFP', "ttl": 300, - "records": [{algorithm: 1, type: 1, fingerprint: 'foo'}, - {algorithm: 2, type: 1, fingerprint: 'bar'}] + "records": [{algorithm: 1, type: 1, fingerprint: '123456789ABCDEF67890123456789ABCDEF67890'}, + {algorithm: 2, type: 1, fingerprint: 'F23456789ABCDEF67890123456789ABCDEF67890'}] }; displayRecord = { @@ -160,8 +160,8 @@ describe('Service: recordsService', function () { "type": 'SSHFP', "ttl": 300, "records": undefined, - "sshfpItems": [{algorithm: 1, type: 1, fingerprint: 'foo'}, - {algorithm: 2, type: 1, fingerprint: 'bar'}], + "sshfpItems": [{algorithm: 1, type: 1, fingerprint: '123456789ABCDEF67890123456789ABCDEF67890'}, + {algorithm: 2, type: 1, fingerprint: 'F23456789ABCDEF67890123456789ABCDEF67890'}], "onlyFour": true, "isDotted": true, "canBeEdited": true @@ -177,8 +177,8 @@ describe('Service: recordsService', function () { "name": 'apex.with.dot', "type": 'SSHFP', "ttl": 300, - "records": [{algorithm: 1, type: 1, fingerprint: 'foo'}, - {algorithm: 2, type: 1, fingerprint: 'bar'}] + "records": [{algorithm: 1, type: 1, fingerprint: '123456789ABCDEF67890123456789ABCDEF67890'}, + {algorithm: 2, type: 1, fingerprint: 'F23456789ABCDEF67890123456789ABCDEF67890'}] }; displayRecord = { @@ -187,8 +187,8 @@ describe('Service: recordsService', function () { "type": 'SSHFP', "ttl": 300, "records": undefined, - "sshfpItems": [{algorithm: 1, type: 1, fingerprint: 'foo'}, - {algorithm: 2, type: 1, fingerprint: 'bar'}], + "sshfpItems": [{algorithm: 1, type: 1, fingerprint: '123456789ABCDEF67890123456789ABCDEF67890'}, + {algorithm: 2, type: 1, fingerprint: 'F23456789ABCDEF67890123456789ABCDEF67890'}], "onlyFour": true, "isDotted": false, "canBeEdited": true @@ -229,8 +229,8 @@ describe('Service: recordsService', function () { "name": 'apex.with.dot', "type": 'SSHFP', "ttl": 300, - "records": [{algorithm: 1, type: 1, fingerprint: 'foo'}, - {algorithm: 2, type: 1, fingerprint: 'bar'}] + "records": [{algorithm: 1, type: 1, fingerprint: '123456789ABCDEF67890123456789ABCDEF67890'}, + {algorithm: 2, type: 1, fingerprint: 'F23456789ABCDEF67890123456789ABCDEF67890'}] }; displayRecord = { @@ -239,8 +239,8 @@ describe('Service: recordsService', function () { "type": 'SSHFP', "ttl": 300, "records": undefined, - "sshfpItems": [{algorithm: 1, type: 1, fingerprint: 'foo'}, - {algorithm: 2, type: 1, fingerprint: 'bar'}], + "sshfpItems": [{algorithm: 1, type: 1, fingerprint: '123456789ABCDEF67890123456789ABCDEF67890'}, + {algorithm: 2, type: 1, fingerprint: 'F23456789ABCDEF67890123456789ABCDEF67890'}], "onlyFour": true, "isDotted": false, "canBeEdited": true diff --git a/modules/portal/run_all_tests.sh b/modules/portal/run_all_tests.sh deleted file mode 100755 index 808512f0a..000000000 --- a/modules/portal/run_all_tests.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash - -function check_for() { - which $1 >/dev/null 2>&1 - EXIT_CODE=$? - if [ ${EXIT_CODE} != 0 ] - then - echo "$1 is not installed" - exit ${EXIT_CODE} - fi -} - -check_for python -check_for npm - -# if the program exits before this has been captured then there must have been an error -EXIT_CODE=1 - -cd $(dirname $0) - -# javascript code generate -bower install -grunt default - -TEST_SUITES=('sbt clean coverage test' - 'grunt unit' - ) - -for TEST in "${TEST_SUITES[@]}" -do - echo "##### Running test: [$TEST]" - $TEST - EXIT_CODE=$? - echo "##### Test [$TEST] ended with status [$EXIT_CODE]" - if [ ${EXIT_CODE} != 0 ] - then - exit ${EXIT_CODE} - fi -done diff --git a/modules/portal/test/controllers/FrontendControllerSpec.scala b/modules/portal/test/controllers/FrontendControllerSpec.scala index da7cc5c97..2e97f589a 100644 --- a/modules/portal/test/controllers/FrontendControllerSpec.scala +++ b/modules/portal/test/controllers/FrontendControllerSpec.scala @@ -45,7 +45,7 @@ class FrontendControllerSpec extends Specification with Mockito with TestApplica val mockOidcAuthenticator: OidcAuthenticator = mock[OidcAuthenticator] val enabledOidcAuthenticator: OidcAuthenticator = mock[OidcAuthenticator] enabledOidcAuthenticator.oidcEnabled.returns(true) - enabledOidcAuthenticator.getCodeCall.returns(Uri("http://test.com")) + enabledOidcAuthenticator.getCodeCall(anyString).returns(Uri("http://test.com")) enabledOidcAuthenticator.oidcLogoutUrl.returns("http://logout-test.com") enabledOidcAuthenticator.getValidUsernameFromToken(any[String]).returns(Some("test")) @@ -84,7 +84,7 @@ class FrontendControllerSpec extends Specification with Mockito with TestApplica "redirect to the login page when a user is not logged in" in new WithApplication(app) { val result = underTest.index()(FakeRequest(GET, "/")) status(result) must equalTo(SEE_OTHER) - headers(result) must contain("Location" -> "/login") + headers(result) must contain("Location" -> "/login?target=/") } "render the index page when the user is logged in" in new WithApplication(app) { val result = @@ -100,7 +100,7 @@ class FrontendControllerSpec extends Specification with Mockito with TestApplica "redirect to the login page when a user is not logged in" in new WithApplication(app) { val result = underTest.index()(FakeRequest(GET, "/index")) status(result) must equalTo(SEE_OTHER) - headers(result) must contain("Location" -> "/login") + headers(result) must contain("Location" -> "/login?target=/index") } "render the DNS Changes page when the user is logged in" in new WithApplication(app) { val result = @@ -124,7 +124,7 @@ class FrontendControllerSpec extends Specification with Mockito with TestApplica "redirect to the login page when a user is not logged in" in new WithApplication(app) { val result = oidcUnderTest.index()(FakeRequest(GET, "/index").withCSRFToken) status(result) must equalTo(SEE_OTHER) - headers(result) must contain("Location" -> "/login") + headers(result) must contain("Location" -> "/login?target=/index") } "render the DNS Changes page when the user is logged in" in new WithApplication(app) { val result = @@ -144,7 +144,7 @@ class FrontendControllerSpec extends Specification with Mockito with TestApplica "redirect to the login page when a user is not logged in" in new WithApplication(app) { val result = underTest.viewAllGroups()(FakeRequest(GET, "/groups")) status(result) must equalTo(SEE_OTHER) - headers(result) must contain("Location" -> "/login") + headers(result) must contain("Location" -> "/login?target=/groups") } "render the groups view page when the user is logged in" in new WithApplication(app) { val result = @@ -168,7 +168,7 @@ class FrontendControllerSpec extends Specification with Mockito with TestApplica "redirect to the login page when a user is not logged in" in new WithApplication(app) { val result = underTest.viewGroup("some-id")(FakeRequest(GET, "/groups/some-id")) status(result) must equalTo(SEE_OTHER) - headers(result) must contain("Location" -> "/login") + headers(result) must contain("Location" -> "/login?target=/groups/some-id") } "render the groups view page when the user is logged in" in new WithApplication(app) { val result = @@ -192,7 +192,7 @@ class FrontendControllerSpec extends Specification with Mockito with TestApplica "redirect to the login page when a user is not logged in" in new WithApplication(app) { val result = underTest.viewAllZones()(FakeRequest(GET, "/zones")) status(result) must equalTo(SEE_OTHER) - headers(result) must contain("Location" -> "/login") + headers(result) must contain("Location" -> "/login?target=/zones") } "render the zone view page when the user is logged in" in new WithApplication(app) { val result = @@ -216,7 +216,7 @@ class FrontendControllerSpec extends Specification with Mockito with TestApplica "redirect to the login page when a user is not logged in" in new WithApplication(app) { val result = underTest.viewZone("some-id")(FakeRequest(GET, "/zones/some-id")) status(result) must equalTo(SEE_OTHER) - headers(result) must contain("Location" -> "/login") + headers(result) must contain("Location" -> "/login?target=/zones/some-id") } "render the zones view page when the user is logged in" in new WithApplication(app) { val result = @@ -336,7 +336,7 @@ class FrontendControllerSpec extends Specification with Mockito with TestApplica "redirect to the login page when a user is not logged in" in new WithApplication(app) { val result = underTest.viewAllBatchChanges()(FakeRequest(GET, "/dnschanges")) status(result) must equalTo(SEE_OTHER) - headers(result) must contain("Location" -> "/login") + headers(result) must contain("Location" -> "/login?target=/dnschanges") } "render the batch changes view page when the user is logged in" in new WithApplication(app) { val result = @@ -362,7 +362,7 @@ class FrontendControllerSpec extends Specification with Mockito with TestApplica "redirect to the login page when a user is not logged in" in new WithApplication(app) { val result = underTest.viewBatchChange("some-id")(FakeRequest(GET, "/dnschanges/some-id")) status(result) must equalTo(SEE_OTHER) - headers(result) must contain("Location" -> "/login") + headers(result) must contain("Location" -> "/login?target=/dnschanges/some-id") } "render the DNS change view page when the user is logged in" in new WithApplication(app) { val result = @@ -390,7 +390,7 @@ class FrontendControllerSpec extends Specification with Mockito with TestApplica "redirect to the login page when a user is not logged in" in new WithApplication(app) { val result = underTest.viewNewBatchChange()(FakeRequest(GET, "/dnschanges/new")) status(result) must equalTo(SEE_OTHER) - headers(result) must contain("Location" -> "/login") + headers(result) must contain("Location" -> "/login?target=/dnschanges/new") } "render the new batch change view page when the user is logged in" in new WithApplication(app) { val result = diff --git a/modules/portal/test/controllers/OidcAuthenticatorSpec.scala b/modules/portal/test/controllers/OidcAuthenticatorSpec.scala index 38b7833e2..1dd4f36f5 100644 --- a/modules/portal/test/controllers/OidcAuthenticatorSpec.scala +++ b/modules/portal/test/controllers/OidcAuthenticatorSpec.scala @@ -92,7 +92,7 @@ class OidcAuthenticatorSpec extends Specification with Mockito { "OidcAuthenticator" should { "Initial code call" should { "properly generate the code call" in { - val codeCall = testOidcAuthenticator.getCodeCall + val codeCall = testOidcAuthenticator.getCodeCall("/abcd") val query = codeCall.queryString().get codeCall.toString must startWith("http://test.authorization.url") diff --git a/modules/portal/test/controllers/VinylDNSSpec.scala b/modules/portal/test/controllers/VinylDNSSpec.scala index 43af81938..7371dbd1d 100644 --- a/modules/portal/test/controllers/VinylDNSSpec.scala +++ b/modules/portal/test/controllers/VinylDNSSpec.scala @@ -573,17 +573,6 @@ class VinylDNSSpec extends Specification with Mockito with TestApplicationData w } } - ".oidcCallback" should { - "redirect to set session view" in new WithApplication(app) { - val response = vinyldnsPortal - .oidcCallback("id") - .apply(FakeRequest("GET", "id?query=q")) - - status(response) mustEqual 200 - contentAsString(response) must contain("/public/lib/oidc-finish.js") - } - } - ".newGroup" should { tag("slow") "return the group description on create - status ok (200)" in new WithApplication(app) { @@ -1298,11 +1287,11 @@ class VinylDNSSpec extends Specification with Mockito with TestApplicationData w TestVinylDNS(config, mockLdapAuthenticator, mockUserAccessor, ws, components, crypto) val result: Future[Result] = underTest.serveCredsFile("credsfile.csv")( - FakeRequest(GET, s"/download-creds-file/credsfile.csv") + FakeRequest(GET, "/download-creds-file/credsfile.csv") ) status(result) mustEqual 303 - redirectLocation(result) must beSome("/login") + redirectLocation(result) must beSome("/login?target=/download-creds-file/credsfile.csv") flash(result).get("alertType") must beSome("danger") flash(result).get("alertMessage") must beSome( "You are not logged in. Please login to continue." diff --git a/modules/r53/src/it/scala/vinyldns/route53/backend/Route53IntegrationSpec.scala b/modules/r53/src/it/scala/vinyldns/route53/backend/Route53IntegrationSpec.scala index 3dbb75589..cd799f182 100644 --- a/modules/r53/src/it/scala/vinyldns/route53/backend/Route53IntegrationSpec.scala +++ b/modules/r53/src/it/scala/vinyldns/route53/backend/Route53IntegrationSpec.scala @@ -30,7 +30,7 @@ import vinyldns.core.domain.{Fqdn, record} import vinyldns.core.domain.record.{RecordSet, RecordType} class Route53IntegrationSpec - extends AnyWordSpec + extends AnyWordSpec with BeforeAndAfterAll with BeforeAndAfterEach with Matchers { @@ -52,7 +52,7 @@ class Route53IntegrationSpec "test", Option("access"), Option("secret"), - "http://127.0.0.1:19009", + sys.env.getOrElse("R53_SERVICE_ENDPOINT", "http://localhost:19003"), "us-east-1" ) ) diff --git a/modules/sqs/src/it/resources/application.conf b/modules/sqs/src/it/resources/application.conf index b579eb937..b235d0f8c 100644 --- a/modules/sqs/src/it/resources/application.conf +++ b/modules/sqs/src/it/resources/application.conf @@ -4,10 +4,11 @@ sqs { messages-per-poll = 10 max-retries = 100 settings = { - access-key = "x" - secret-key = "x" - signing-region = "x" - service-endpoint = "http://localhost:19007/" + access-key = "test" + secret-key = "test" + signing-region = "us-east-1" + service-endpoint = "http://localhost:19003/" + service-endpoint = ${?SQS_SERVICE_ENDPOINT} queue-name = "sqs-override-name" } } diff --git a/modules/sqs/src/it/scala/vinyldns/sqs/queue/SqsMessageQueueIntegrationSpec.scala b/modules/sqs/src/it/scala/vinyldns/sqs/queue/SqsMessageQueueIntegrationSpec.scala index fd04d05d4..09585e44d 100644 --- a/modules/sqs/src/it/scala/vinyldns/sqs/queue/SqsMessageQueueIntegrationSpec.scala +++ b/modules/sqs/src/it/scala/vinyldns/sqs/queue/SqsMessageQueueIntegrationSpec.scala @@ -147,13 +147,6 @@ class SqsMessageQueueIntegrationSpec result shouldBe empty } - "succeed when attempting to remove item from empty queue" in { - queue - .remove(SqsMessage(MessageId("does-not-exist"), rsAddChange)) - .attempt - .unsafeRunSync() should beRight(()) - } - "succeed when attempting to remove item from queue" in { queue.send(rsAddChange).unsafeRunSync() val result = queue.receive(MessageCount(1).right.value).unsafeRunSync() diff --git a/modules/sqs/src/it/scala/vinyldns/sqs/queue/SqsMessageQueueProviderIntegrationSpec.scala b/modules/sqs/src/it/scala/vinyldns/sqs/queue/SqsMessageQueueProviderIntegrationSpec.scala index 6e3282c0b..561d7936b 100644 --- a/modules/sqs/src/it/scala/vinyldns/sqs/queue/SqsMessageQueueProviderIntegrationSpec.scala +++ b/modules/sqs/src/it/scala/vinyldns/sqs/queue/SqsMessageQueueProviderIntegrationSpec.scala @@ -15,6 +15,7 @@ */ package vinyldns.sqs.queue + import com.typesafe.config.ConfigFactory import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpec @@ -24,50 +25,53 @@ import pureconfig._ import pureconfig.generic.auto._ class SqsMessageQueueProviderIntegrationSpec extends AnyWordSpec with Matchers { - val undertest = new SqsMessageQueueProvider() + val underTest = new SqsMessageQueueProvider() + private val sqsEndpoint = sys.env.getOrElse("SQS_SERVICE_ENDPOINT", "http://localhost:19003") "load" should { "fail if a required setting is not provided" in { val badConfig = - ConfigFactory.parseString(""" - | class-name = "vinyldns.sqs.queue.SqsMessageQueueProvider" - | polling-interval = 250.millis - | messages-per-poll = 10 - | max-retries = 100 - | - | settings { - | service-endpoint = "http://localhost:19007/" - | queue-name = "queue-name" - | } - | """.stripMargin) + ConfigFactory.parseString( + s""" + | class-name = "vinyldns.sqs.queue.SqsMessageQueueProvider" + | polling-interval = 250.millis + | messages-per-poll = 10 + | max-retries = 100 + | + | settings { + | service-endpoint = "$sqsEndpoint" + | queue-name = "queue-name" + | } + | """.stripMargin) val badSettings = ConfigSource.fromConfig(badConfig).loadOrThrow[MessageQueueConfig] - a[pureconfig.error.ConfigReaderException[MessageQueueConfig]] should be thrownBy undertest + a[pureconfig.error.ConfigReaderException[MessageQueueConfig]] should be thrownBy underTest .load(badSettings) .unsafeRunSync() } "create the queue if the queue is non-existent" in { val nonExistentQueueConfig = - ConfigFactory.parseString(""" - | class-name = "vinyldns.sqs.queue.SqsMessageQueueProvider" - | polling-interval = 250.millis - | messages-per-poll = 10 - | max-retries = 100 - | - | settings { - | access-key = "x" - | secret-key = "x" - | signing-region = "x" - | service-endpoint = "http://localhost:19007/" - | queue-name = "new-queue" - | } - | """.stripMargin) + ConfigFactory.parseString( + s""" + | class-name = "vinyldns.sqs.queue.SqsMessageQueueProvider" + | polling-interval = 250.millis + | messages-per-poll = 10 + | max-retries = 100 + | + | settings { + | access-key = "x" + | secret-key = "x" + | signing-region = "us-east-1" + | service-endpoint = "$sqsEndpoint" + | queue-name = "new-queue" + | } + | """.stripMargin) val messageConfig = ConfigSource.fromConfig(nonExistentQueueConfig).loadOrThrow[MessageQueueConfig] - val messageQueue = undertest.load(messageConfig).unsafeRunSync() + val messageQueue = underTest.load(messageConfig).unsafeRunSync() noException should be thrownBy messageQueue .asInstanceOf[SqsMessageQueue] @@ -77,65 +81,68 @@ class SqsMessageQueueProviderIntegrationSpec extends AnyWordSpec with Matchers { "fail with InvalidQueueName if an invalid queue name is given" in { val invalidQueueNameConfig = - ConfigFactory.parseString(""" - | class-name = "vinyldns.sqs.queue.SqsMessageQueueProvider" - | polling-interval = 250.millis - | messages-per-poll = 10 - | max-retries = 100 - | - | settings { - | access-key = "x" - | secret-key = "x" - | signing-region = "x" - | service-endpoint = "http://localhost:19007/" - | queue-name = "bad*queue*name" - | } - | """.stripMargin) + ConfigFactory.parseString( + s""" + | class-name = "vinyldns.sqs.queue.SqsMessageQueueProvider" + | polling-interval = 250.millis + | messages-per-poll = 10 + | max-retries = 100 + | + | settings { + | access-key = "x" + | secret-key = "x" + | signing-region = "us-east-1" + | service-endpoint = "$sqsEndpoint" + | queue-name = "bad*queue*name" + | } + | """.stripMargin) val messageConfig = ConfigSource.fromConfig(invalidQueueNameConfig).loadOrThrow[MessageQueueConfig] - assertThrows[InvalidQueueName](undertest.load(messageConfig).unsafeRunSync()) + assertThrows[InvalidQueueName](underTest.load(messageConfig).unsafeRunSync()) } "fail with InvalidQueueName if a FIFO queue is specified" in { val fifoQueueName = - ConfigFactory.parseString(""" - | class-name = "vinyldns.sqs.queue.SqsMessageQueueProvider" - | polling-interval = 250.millis - | messages-per-poll = 10 - | max-retries = 100 - | - | settings { - | access-key = "x" - | secret-key = "x" - | signing-region = "x" - | service-endpoint = "http://localhost:19007/" - | queue-name = "queue.fifo" - | } - | """.stripMargin) + ConfigFactory.parseString( + s""" + | class-name = "vinyldns.sqs.queue.SqsMessageQueueProvider" + | polling-interval = 250.millis + | messages-per-poll = 10 + | max-retries = 100 + | + | settings { + | access-key = "x" + | secret-key = "x" + | signing-region = "us-east-1" + | service-endpoint = "$sqsEndpoint" + | queue-name = "queue.fifo" + | } + | """.stripMargin) val messageConfig = ConfigSource.fromConfig(fifoQueueName).loadOrThrow[MessageQueueConfig] - assertThrows[InvalidQueueName](undertest.load(messageConfig).unsafeRunSync()) + assertThrows[InvalidQueueName](underTest.load(messageConfig).unsafeRunSync()) } } "MessageQueueLoader" should { "invoke SQS provider properly" in { val nonExistentQueueConfig = - ConfigFactory.parseString(""" - | class-name = "vinyldns.sqs.queue.SqsMessageQueueProvider" - | polling-interval = 250.millis - | messages-per-poll = 10 - | max-retries = 100 - | - | settings { - | access-key = "x" - | secret-key = "x" - | signing-region = "x" - | service-endpoint = "http://localhost:19007/" - | queue-name = "new-queue" - | } - | """.stripMargin) + ConfigFactory.parseString( + s""" + | class-name = "vinyldns.sqs.queue.SqsMessageQueueProvider" + | polling-interval = 250.millis + | messages-per-poll = 10 + | max-retries = 100 + | + | settings { + | access-key = "x" + | secret-key = "x" + | signing-region = "us-east-1" + | service-endpoint = "$sqsEndpoint" + | queue-name = "new-queue" + | } + | """.stripMargin) val messageConfig = ConfigSource.fromConfig(nonExistentQueueConfig).loadOrThrow[MessageQueueConfig] diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 0844e5e13..df3475c84 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -33,7 +33,7 @@ object Dependencies { "dnsjava" % "dnsjava" % "3.4.2", "org.apache.commons" % "commons-lang3" % "3.4", "org.apache.commons" % "commons-text" % "1.4", - "org.flywaydb" % "flyway-core" % "8.0.0", + "org.flywaydb" % "flyway-core" % "5.2.4", "org.json4s" %% "json4s-ext" % "3.5.3", "org.json4s" %% "json4s-jackson" % "3.5.3", "org.scalikejdbc" %% "scalikejdbc" % scalikejdbcV, @@ -79,7 +79,7 @@ object Dependencies { ) lazy val mysqlDependencies = Seq( - "org.flywaydb" % "flyway-core" % "8.0.0", + "org.flywaydb" % "flyway-core" % "5.2.4", "org.mariadb.jdbc" % "mariadb-java-client" % "2.3.0", "org.scalikejdbc" %% "scalikejdbc" % scalikejdbcV, "org.scalikejdbc" %% "scalikejdbc-config" % scalikejdbcV, diff --git a/project/Resolvers.scala b/project/Resolvers.scala deleted file mode 100644 index 76f79021f..000000000 --- a/project/Resolvers.scala +++ /dev/null @@ -1,10 +0,0 @@ -import sbt._ - -object Resolvers { - - lazy val additionalResolvers = Seq( - "dnvriend at bintray" at "https://dl.bintray.com/dnvriend/maven", - "bintray" at "https://jcenter.bintray.com", - "DynamoDBLocal" at "https://s3-us-west-2.amazonaws.com/dynamodb-local/release" - ) -} diff --git a/project/assembly.sbt b/project/assembly.sbt deleted file mode 100644 index d6540b84c..000000000 --- a/project/assembly.sbt +++ /dev/null @@ -1 +0,0 @@ -addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.8") diff --git a/project/plugins.sbt b/project/plugins.sbt index f6429eb47..38f8de3ba 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -2,24 +2,22 @@ logLevel := Level.Warn resolvers += "Flyway" at "https://flywaydb.org/repo" +addSbtPlugin("com.thesamet" % "sbt-protoc" % "0.99.18") + +addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "1.1.0") + addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.6.0") addSbtPlugin("io.spray" % "sbt-revolver" % "0.9.1") addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.9.0") -addSbtPlugin("io.github.davidmweber" % "flyway-sbt" % "5.0.0") - addSbtPlugin("org.wartremover" % "sbt-wartremover" % "2.4.10") addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.25") -addSbtPlugin("com.tapad" % "sbt-docker-compose" % "1.0.34") - addSbtPlugin("com.typesafe.sbt" % "sbt-ghpages" % "0.6.3") -addSbtPlugin("com.github.gseitz" % "sbt-release" % "1.0.8") - addSbtPlugin("de.heikoseeberger" % "sbt-header" % "5.5.0") addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.4") @@ -28,10 +26,6 @@ addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.3.4") addSbtPlugin("com.typesafe.sbt" % "sbt-license-report" % "1.2.0") -addSbtPlugin("com.47deg" % "sbt-microsites" % "1.1.5") +addSbtPlugin("com.47deg" % "sbt-microsites" % "1.3.4") -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "2.3") - -addSbtPlugin("io.crashbox" % "sbt-gpg" % "0.2.0") - -addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.2.10" ) +addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.2.24") diff --git a/project/protoc.sbt b/project/protoc.sbt deleted file mode 100644 index 29a56e7bd..000000000 --- a/project/protoc.sbt +++ /dev/null @@ -1 +0,0 @@ -addSbtPlugin("com.thesamet" % "sbt-protoc" % "0.99.18") diff --git a/quickstart/.env b/quickstart/.env new file mode 100644 index 000000000..fb0b428e2 --- /dev/null +++ b/quickstart/.env @@ -0,0 +1,24 @@ +# General settings +VINYLDNS_API_URL=http://localhost:9000 +VINYLDNS_PORTAL_URL=http://localhost:9001 + +# Portal settings +PORTAL_PORT=9001 +PLAY_HTTP_SECRET_KEY=change-this-for-prod +VINYLDNS_BACKEND_URL=http://vinyldns-api:9000 +LDAP_PROVIDER_URL=ldap://vinyldns-ldap:19004 +TEST_LOGIN=false + +# API Settings +REST_PORT=9000 +SQS_SERVICE_ENDPOINT=http://vinyldns-integration:19003 +SNS_SERVICE_ENDPOINT=http://vinyldns-integration:19003 +R53_SERVICE_ENDPOINT=http://vinyldns-integration:19003 +MYSQL_ENDPOINT=vinyldns-integration:19002 +DEFAULT_DNS_ADDRESS=vinyldns-integration:19001 + +JDBC_DRIVER=org.mariadb.jdbc.Driver +JDBC_URL=jdbc:mariadb://vinyldns-integration:19002/vinyldns?user=root&password=pass +JDBC_MIGRATION_URL=jdbc:mariadb://vinyldns-integration:19002/?user=root&password=pass +JDBC_USER=root +JDBC_PASSWORD=pass diff --git a/quickstart/README.md b/quickstart/README.md new file mode 100644 index 000000000..fb9636c6f --- /dev/null +++ b/quickstart/README.md @@ -0,0 +1,38 @@ +# VinylDNS QuickStart + +To get started with VinylDNS, you can experiment with the QuickStart. + +QuickStart utilizes Docker Compose to start up the VinylDNS API and Portal along with required dependencies such as: + +- MySQL +- OpenLDAP +- SQS +- SNS +- BIND 9 + +## Running + +To run the QuickStart, you will need the following prerequisites: + +- Docker +- Docker Compose + +From a shell in the `quickstart/` directory, simply run: + +```shell script +./quickstart-vinyldns.sh +``` + +The `quickstart-vinyldns.sh` script takes a number of optional arguments: + +| Flag | Description | +|:---|:-----------------------------------------------------------------------------| +| `-a, --api-only` | do not start up the VinylDNS Portal" | +| `-b, --build` | force a rebuild of the Docker images with the local code" | +| `-c, --clean` | stops all VinylDNS containers" | +| `-d, --deps-only` | only start up the dependencies, not the API or Portal" | +| `-r, --reset` | reset any the running containers" | +| `-s, --service` | specify the service to run" | +| `-t, --timeout` | the time to wait (in seconds) for the Portal and API to start (default: 60)" | +| `-u, --update` | remove the local quickstart images to force a re-pull from Docker Hub" | +| `-v, --version-tag` | specify Docker image tag version (default: latest)" | diff --git a/quickstart/bind9/README.md b/quickstart/bind9/README.md new file mode 100644 index 000000000..fbf5b1c96 --- /dev/null +++ b/quickstart/bind9/README.md @@ -0,0 +1,22 @@ +## Bind Test Configuration + +This folder contains test configuration for BIND zones. The zones are partitioned into four distinct partitions to allow +for four parallel testing threads that won't interfere with one another. + +### Layout + +| Directory | Detail | +|:---|:---| +| `etc/` | Contains zone configurations separated by partition | +| `etc/_template` | Contains the template file for creating the partitioned `conf` files. Currently this is just a find and replace operation - finding `{placeholder}` and replacing it with the desired placeholder. | +| `zones/` | Contains zone definitions separated by partition | +| `zones/_template` |Contains the template file for creating the partitioned zone files. Currently this is just a find and replace operation - finding `{placeholder}` and replacing it with the desired placeholder. | + +### Target Directories + +When used in a container, or to run `named`, the files in this directory should be copied to the following directories: + +| Directory | Target | +|:---|:---| +| `etc/named.conf.*` | `/etc/bind/` | +| `zones/` | `/var/bind/` | diff --git a/quickstart/bind9/etc/_template/named.partition.conf b/quickstart/bind9/etc/_template/named.partition.conf new file mode 100644 index 000000000..ee6ecdfe4 --- /dev/null +++ b/quickstart/bind9/etc/_template/named.partition.conf @@ -0,0 +1,186 @@ +zone "vinyldns" { + type master; + file "/var/bind/partition/vinyldns.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "old-vinyldns2{partition}" { + type master; + file "/var/bind/partition/old-vinyldns2.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "old-vinyldns3{partition}" { + type master; + file "/var/bind/partition/old-vinyldns3.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "dummy" { + type master; + file "/var/bind/partition/dummy.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "ok" { + type master; + file "/var/bind/partition/ok.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "shared" { + type master; + file "/var/bind/partition/shared.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "non.test.shared" { + type master; + file "/var/bind/partition/non.test.shared.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "system-test" { + type master; + file "/var/bind/partition/system-test.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "system-test-history" { + type master; + file "/var/bind/partition/system-test-history.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "{partition}.10.in-addr.arpa" { + type master; + file "/var/bind/partition/10.10.in-addr.arpa"; + allow-update { key "vinyldns."; }; + }; + +zone "{partition}.0.192.in-addr.arpa" { + type master; + file "/var/bind/partition/2.0.192.in-addr.arpa"; + allow-update { key "vinyldns."; }; + }; + +zone "192/30.{partition}.0.192.in-addr.arpa" { + type master; + file "/var/bind/partition/192^30.2.0.192.in-addr.arpa"; + allow-update { key "vinyldns."; }; + }; + +zone "{partition}.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa" { + type master; + file "/var/bind/partition/1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa"; + allow-update { key "vinyldns."; }; + }; + +zone "0.0.0.1.{partition}.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa" { + type master; + file "/var/bind/partition/0.0.0.1.1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa"; + allow-update { key "vinyldns."; }; + }; + +zone "one-time" { + type master; + file "/var/bind/partition/one-time.hosts"; + allow-update { key "vinyldns."; key "vinyldns-sha1."; key "vinyldns-sha224."; key "vinyldns-sha256."; key "vinyldns-sha384."; key "vinyldns-sha512."; }; + }; + +zone "sync-test" { + type master; + file "/var/bind/partition/sync-test.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "invalid-zone" { + type master; + file "/var/bind/partition/invalid-zone.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-searched-1{partition}" { + type master; + file "/var/bind/partition/list-zones-test-searched-1.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-searched-2{partition}" { + type master; + file "/var/bind/partition/list-zones-test-searched-2.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-searched-3{partition}" { + type master; + file "/var/bind/partition/list-zones-test-searched-3.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-unfiltered-1{partition}" { + type master; + file "/var/bind/partition/list-zones-test-unfiltered-1.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-unfiltered-2{partition}" { + type master; + file "/var/bind/partition/list-zones-test-unfiltered-2.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "one-time-shared" { + type master; + file "/var/bind/partition/one-time-shared.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "parent.com" { + type master; + file "/var/bind/partition/parent.com.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "child.parent.com" { + type master; + file "/var/bind/partition/child.parent.com.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "example.com" { + type master; + file "/var/bind/partition/example.com.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "dskey.example.com" { + type master; + file "/var/bind/partition/dskey.example.com.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "not.loaded" { + type master; + file "/var/bind/partition/not.loaded.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "zone.requires.review" { + type master; + file "/var/bind/partition/zone.requires.review.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-records" { + type master; + file "/var/bind/partition/list-records.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "open" { + type master; + file "/var/bind/partition/open.hosts"; + allow-update { any; }; + allow-transfer { any; }; + }; diff --git a/quickstart/bind9/etc/named.conf.default b/quickstart/bind9/etc/named.conf.default new file mode 100644 index 000000000..762f51787 --- /dev/null +++ b/quickstart/bind9/etc/named.conf.default @@ -0,0 +1,162 @@ +zone "vinyldns" { + type master; + file "/var/bind/default/vinyldns.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "old-vinyldns2" { + type master; + file "/var/bind/default/old-vinyldns2.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "old-vinyldns3" { + type master; + file "/var/bind/default/old-vinyldns3.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "dummy" { + type master; + file "/var/bind/default/dummy.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "ok" { + type master; + file "/var/bind/default/ok.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "shared" { + type master; + file "/var/bind/default/shared.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "non.test.shared" { + type master; + file "/var/bind/default/non.test.shared.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "system-test" { + type master; + file "/var/bind/default/system-test.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "system-test-history" { + type master; + file "/var/bind/default/system-test-history.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "10.10.in-addr.arpa" { + type master; + file "/var/bind/default/10.10.in-addr.arpa"; + allow-update { key "vinyldns."; }; + }; + +zone "one-time" { + type master; + file "/var/bind/default/one-time.hosts"; + allow-update { key "vinyldns."; key "vinyldns-sha1."; key "vinyldns-sha224."; key "vinyldns-sha256."; key "vinyldns-sha384."; key "vinyldns-sha512."; }; + }; + +zone "sync-test" { + type master; + file "/var/bind/default/sync-test.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "invalid-zone" { + type master; + file "/var/bind/default/invalid-zone.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-searched-1{partition}" { + type master; + file "/var/bind/default/list-zones-test-searched-1.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-searched-2{partition}" { + type master; + file "/var/bind/default/list-zones-test-searched-2.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-searched-3{partition}" { + type master; + file "/var/bind/default/list-zones-test-searched-3.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-unfiltered-1{partition}" { + type master; + file "/var/bind/default/list-zones-test-unfiltered-1.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-unfiltered-2{partition}" { + type master; + file "/var/bind/default/list-zones-test-unfiltered-2.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "one-time-shared" { + type master; + file "/var/bind/default/one-time-shared.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "parent.com" { + type master; + file "/var/bind/default/parent.com.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "child.parent.com" { + type master; + file "/var/bind/default/child.parent.com.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "example.com" { + type master; + file "/var/bind/default/example.com.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "dskey.example.com" { + type master; + file "/var/bind/default/dskey.example.com.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "not.loaded" { + type master; + file "/var/bind/default/not.loaded.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "zone.requires.review" { + type master; + file "/var/bind/default/zone.requires.review.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-records" { + type master; + file "/var/bind/default/list-records.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "open" { + type master; + file "/var/bind/default/open.hosts"; + allow-update { any; }; + allow-transfer { any; }; + }; diff --git a/quickstart/bind9/etc/named.conf.local b/quickstart/bind9/etc/named.conf.local new file mode 100644 index 000000000..2a0fb56e4 --- /dev/null +++ b/quickstart/bind9/etc/named.conf.local @@ -0,0 +1,36 @@ + +key "vinyldns." { + algorithm hmac-md5; + secret "nzisn+4G2ldMn0q1CV3vsg=="; +}; + +key "vinyldns-sha1." { + algorithm hmac-sha1; + secret "0nIhR1zS/nHUg2n0AIIUyJwXUyQ="; +}; + +key "vinyldns-sha224." { + algorithm hmac-sha224; + secret "yud/F666YjcnfqPSulHaYXrNObNnS1Jv+rX61A=="; +}; + +key "vinyldns-sha256." { + algorithm hmac-sha256; + secret "wzLsDGgPRxFaC6z/9Bc0n1W4KrnmaUdFCgCn2+7zbPU="; +}; + +key "vinyldns-sha384." { + algorithm hmac-sha384; + secret "ne9jSUJ7PBGveM37aOX+ZmBXQgz1EqkbYBO1s5l/LNpjEno4OfYvGo1Lv1rnw3pE"; +}; + +key "vinyldns-sha512." { + algorithm hmac-sha512; + secret "xfKA0DYb88tiUGND+cWddwUg3/SugYSsdvCfBOJ1jr8MEdgbVRyrlVDEXLsfTUGorQ3ShENdymw2yw+rTr+lwA=="; +}; + +include "/etc/bind/named.conf.default"; +include "/etc/bind/named.conf.partition1"; +include "/etc/bind/named.conf.partition2"; +include "/etc/bind/named.conf.partition3"; +include "/etc/bind/named.conf.partition4"; diff --git a/quickstart/bind9/etc/named.conf.partition1 b/quickstart/bind9/etc/named.conf.partition1 new file mode 100644 index 000000000..6f2d543a3 --- /dev/null +++ b/quickstart/bind9/etc/named.conf.partition1 @@ -0,0 +1,186 @@ +zone "vinyldns1" { + type master; + file "/var/bind/partition1/vinyldns.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "old-vinyldns21" { + type master; + file "/var/bind/partition1/old-vinyldns2.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "old-vinyldns31" { + type master; + file "/var/bind/partition1/old-vinyldns3.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "dummy1" { + type master; + file "/var/bind/partition1/dummy.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "ok1" { + type master; + file "/var/bind/partition1/ok.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "shared1" { + type master; + file "/var/bind/partition1/shared.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "non.test.shared1" { + type master; + file "/var/bind/partition1/non.test.shared.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "system-test1" { + type master; + file "/var/bind/partition1/system-test.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "system-test-history1" { + type master; + file "/var/bind/partition1/system-test-history.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "1.10.in-addr.arpa" { + type master; + file "/var/bind/partition1/10.10.in-addr.arpa"; + allow-update { key "vinyldns."; }; + }; + +zone "1.0.192.in-addr.arpa" { + type master; + file "/var/bind/partition1/2.0.192.in-addr.arpa"; + allow-update { key "vinyldns."; }; + }; + +zone "192/30.1.0.192.in-addr.arpa" { + type master; + file "/var/bind/partition1/192^30.2.0.192.in-addr.arpa"; + allow-update { key "vinyldns."; }; + }; + +zone "1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa" { + type master; + file "/var/bind/partition1/1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa"; + allow-update { key "vinyldns."; }; + }; + +zone "0.0.0.1.1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa" { + type master; + file "/var/bind/partition1/0.0.0.1.1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa"; + allow-update { key "vinyldns."; }; + }; + +zone "one-time1" { + type master; + file "/var/bind/partition1/one-time.hosts"; + allow-update { key "vinyldns."; key "vinyldns-sha1."; key "vinyldns-sha224."; key "vinyldns-sha256."; key "vinyldns-sha384."; key "vinyldns-sha512."; }; + }; + +zone "sync-test1" { + type master; + file "/var/bind/partition1/sync-test.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "invalid-zone1" { + type master; + file "/var/bind/partition1/invalid-zone.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-searched-11" { + type master; + file "/var/bind/partition1/list-zones-test-searched-1.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-searched-21" { + type master; + file "/var/bind/partition1/list-zones-test-searched-2.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-searched-31" { + type master; + file "/var/bind/partition1/list-zones-test-searched-3.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-unfiltered-11" { + type master; + file "/var/bind/partition1/list-zones-test-unfiltered-1.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-unfiltered-21" { + type master; + file "/var/bind/partition1/list-zones-test-unfiltered-2.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "one-time-shared1" { + type master; + file "/var/bind/partition1/one-time-shared.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "parent.com1" { + type master; + file "/var/bind/partition1/parent.com.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "child.parent.com1" { + type master; + file "/var/bind/partition1/child.parent.com.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "example.com1" { + type master; + file "/var/bind/partition1/example.com.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "dskey.example.com1" { + type master; + file "/var/bind/partition1/dskey.example.com.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "not.loaded1" { + type master; + file "/var/bind/partition1/not.loaded.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "zone.requires.review1" { + type master; + file "/var/bind/partition1/zone.requires.review.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-records1" { + type master; + file "/var/bind/partition1/list-records.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "open1" { + type master; + file "/var/bind/partition1/open.hosts"; + allow-update { any; }; + allow-transfer { any; }; + }; diff --git a/quickstart/bind9/etc/named.conf.partition2 b/quickstart/bind9/etc/named.conf.partition2 new file mode 100644 index 000000000..51e77a3be --- /dev/null +++ b/quickstart/bind9/etc/named.conf.partition2 @@ -0,0 +1,186 @@ +zone "vinyldns2" { + type master; + file "/var/bind/partition2/vinyldns.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "old-vinyldns22" { + type master; + file "/var/bind/partition2/old-vinyldns2.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "old-vinyldns32" { + type master; + file "/var/bind/partition2/old-vinyldns3.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "dummy2" { + type master; + file "/var/bind/partition2/dummy.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "ok2" { + type master; + file "/var/bind/partition2/ok.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "shared2" { + type master; + file "/var/bind/partition2/shared.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "non.test.shared2" { + type master; + file "/var/bind/partition2/non.test.shared.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "system-test2" { + type master; + file "/var/bind/partition2/system-test.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "system-test-history2" { + type master; + file "/var/bind/partition2/system-test-history.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "2.10.in-addr.arpa" { + type master; + file "/var/bind/partition2/10.10.in-addr.arpa"; + allow-update { key "vinyldns."; }; + }; + +zone "2.0.192.in-addr.arpa" { + type master; + file "/var/bind/partition2/2.0.192.in-addr.arpa"; + allow-update { key "vinyldns."; }; + }; + +zone "192/30.2.0.192.in-addr.arpa" { + type master; + file "/var/bind/partition2/192^30.2.0.192.in-addr.arpa"; + allow-update { key "vinyldns."; }; + }; + +zone "2.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa" { + type master; + file "/var/bind/partition2/1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa"; + allow-update { key "vinyldns."; }; + }; + +zone "0.0.0.1.2.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa" { + type master; + file "/var/bind/partition2/0.0.0.1.1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa"; + allow-update { key "vinyldns."; }; + }; + +zone "one-time2" { + type master; + file "/var/bind/partition2/one-time.hosts"; + allow-update { key "vinyldns."; key "vinyldns-sha1."; key "vinyldns-sha224."; key "vinyldns-sha256."; key "vinyldns-sha384."; key "vinyldns-sha512."; }; + }; + +zone "sync-test2" { + type master; + file "/var/bind/partition2/sync-test.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "invalid-zone2" { + type master; + file "/var/bind/partition2/invalid-zone.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-searched-12" { + type master; + file "/var/bind/partition2/list-zones-test-searched-1.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-searched-22" { + type master; + file "/var/bind/partition2/list-zones-test-searched-2.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-searched-32" { + type master; + file "/var/bind/partition2/list-zones-test-searched-3.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-unfiltered-12" { + type master; + file "/var/bind/partition2/list-zones-test-unfiltered-1.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-unfiltered-22" { + type master; + file "/var/bind/partition2/list-zones-test-unfiltered-2.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "one-time-shared2" { + type master; + file "/var/bind/partition2/one-time-shared.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "parent.com2" { + type master; + file "/var/bind/partition2/parent.com.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "child.parent.com2" { + type master; + file "/var/bind/partition2/child.parent.com.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "example.com2" { + type master; + file "/var/bind/partition2/example.com.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "dskey.example.com2" { + type master; + file "/var/bind/partition2/dskey.example.com.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "not.loaded2" { + type master; + file "/var/bind/partition2/not.loaded.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "zone.requires.review2" { + type master; + file "/var/bind/partition2/zone.requires.review.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-records2" { + type master; + file "/var/bind/partition2/list-records.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "open2" { + type master; + file "/var/bind/partition2/open.hosts"; + allow-update { any; }; + allow-transfer { any; }; + }; diff --git a/quickstart/bind9/etc/named.conf.partition3 b/quickstart/bind9/etc/named.conf.partition3 new file mode 100644 index 000000000..c2699cf8a --- /dev/null +++ b/quickstart/bind9/etc/named.conf.partition3 @@ -0,0 +1,186 @@ +zone "vinyldns3" { + type master; + file "/var/bind/partition3/vinyldns.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "old-vinyldns23" { + type master; + file "/var/bind/partition3/old-vinyldns2.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "old-vinyldns33" { + type master; + file "/var/bind/partition3/old-vinyldns3.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "dummy3" { + type master; + file "/var/bind/partition3/dummy.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "ok3" { + type master; + file "/var/bind/partition3/ok.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "shared3" { + type master; + file "/var/bind/partition3/shared.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "non.test.shared3" { + type master; + file "/var/bind/partition3/non.test.shared.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "system-test3" { + type master; + file "/var/bind/partition3/system-test.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "system-test-history3" { + type master; + file "/var/bind/partition3/system-test-history.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "3.10.in-addr.arpa" { + type master; + file "/var/bind/partition3/10.10.in-addr.arpa"; + allow-update { key "vinyldns."; }; + }; + +zone "3.0.192.in-addr.arpa" { + type master; + file "/var/bind/partition3/2.0.192.in-addr.arpa"; + allow-update { key "vinyldns."; }; + }; + +zone "192/30.3.0.192.in-addr.arpa" { + type master; + file "/var/bind/partition3/192^30.2.0.192.in-addr.arpa"; + allow-update { key "vinyldns."; }; + }; + +zone "3.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa" { + type master; + file "/var/bind/partition3/1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa"; + allow-update { key "vinyldns."; }; + }; + +zone "0.0.0.1.3.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa" { + type master; + file "/var/bind/partition3/0.0.0.1.1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa"; + allow-update { key "vinyldns."; }; + }; + +zone "one-time3" { + type master; + file "/var/bind/partition3/one-time.hosts"; + allow-update { key "vinyldns."; key "vinyldns-sha1."; key "vinyldns-sha224."; key "vinyldns-sha256."; key "vinyldns-sha384."; key "vinyldns-sha512."; }; + }; + +zone "sync-test3" { + type master; + file "/var/bind/partition3/sync-test.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "invalid-zone3" { + type master; + file "/var/bind/partition3/invalid-zone.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-searched-13" { + type master; + file "/var/bind/partition3/list-zones-test-searched-1.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-searched-23" { + type master; + file "/var/bind/partition3/list-zones-test-searched-2.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-searched-33" { + type master; + file "/var/bind/partition3/list-zones-test-searched-3.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-unfiltered-13" { + type master; + file "/var/bind/partition3/list-zones-test-unfiltered-1.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-unfiltered-23" { + type master; + file "/var/bind/partition3/list-zones-test-unfiltered-2.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "one-time-shared3" { + type master; + file "/var/bind/partition3/one-time-shared.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "parent.com3" { + type master; + file "/var/bind/partition3/parent.com.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "child.parent.com3" { + type master; + file "/var/bind/partition3/child.parent.com.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "example.com3" { + type master; + file "/var/bind/partition3/example.com.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "dskey.example.com3" { + type master; + file "/var/bind/partition3/dskey.example.com.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "not.loaded3" { + type master; + file "/var/bind/partition3/not.loaded.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "zone.requires.review3" { + type master; + file "/var/bind/partition3/zone.requires.review.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-records3" { + type master; + file "/var/bind/partition3/list-records.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "open3" { + type master; + file "/var/bind/partition3/open.hosts"; + allow-update { any; }; + allow-transfer { any; }; + }; diff --git a/quickstart/bind9/etc/named.conf.partition4 b/quickstart/bind9/etc/named.conf.partition4 new file mode 100644 index 000000000..c3538c284 --- /dev/null +++ b/quickstart/bind9/etc/named.conf.partition4 @@ -0,0 +1,186 @@ +zone "vinyldns4" { + type master; + file "/var/bind/partition4/vinyldns.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "old-vinyldns24" { + type master; + file "/var/bind/partition4/old-vinyldns2.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "old-vinyldns34" { + type master; + file "/var/bind/partition4/old-vinyldns3.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "dummy4" { + type master; + file "/var/bind/partition4/dummy.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "ok4" { + type master; + file "/var/bind/partition4/ok.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "shared4" { + type master; + file "/var/bind/partition4/shared.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "non.test.shared4" { + type master; + file "/var/bind/partition4/non.test.shared.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "system-test4" { + type master; + file "/var/bind/partition4/system-test.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "system-test-history4" { + type master; + file "/var/bind/partition4/system-test-history.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "4.10.in-addr.arpa" { + type master; + file "/var/bind/partition4/10.10.in-addr.arpa"; + allow-update { key "vinyldns."; }; + }; + +zone "4.0.192.in-addr.arpa" { + type master; + file "/var/bind/partition4/2.0.192.in-addr.arpa"; + allow-update { key "vinyldns."; }; + }; + +zone "192/30.4.0.192.in-addr.arpa" { + type master; + file "/var/bind/partition4/192^30.2.0.192.in-addr.arpa"; + allow-update { key "vinyldns."; }; + }; + +zone "4.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa" { + type master; + file "/var/bind/partition4/1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa"; + allow-update { key "vinyldns."; }; + }; + +zone "0.0.0.1.4.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa" { + type master; + file "/var/bind/partition4/0.0.0.1.1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa"; + allow-update { key "vinyldns."; }; + }; + +zone "one-time4" { + type master; + file "/var/bind/partition4/one-time.hosts"; + allow-update { key "vinyldns."; key "vinyldns-sha1."; key "vinyldns-sha224."; key "vinyldns-sha256."; key "vinyldns-sha384."; key "vinyldns-sha512."; }; + }; + +zone "sync-test4" { + type master; + file "/var/bind/partition4/sync-test.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "invalid-zone4" { + type master; + file "/var/bind/partition4/invalid-zone.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-searched-14" { + type master; + file "/var/bind/partition4/list-zones-test-searched-1.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-searched-24" { + type master; + file "/var/bind/partition4/list-zones-test-searched-2.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-searched-34" { + type master; + file "/var/bind/partition4/list-zones-test-searched-3.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-unfiltered-14" { + type master; + file "/var/bind/partition4/list-zones-test-unfiltered-1.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-zones-test-unfiltered-24" { + type master; + file "/var/bind/partition4/list-zones-test-unfiltered-2.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "one-time-shared4" { + type master; + file "/var/bind/partition4/one-time-shared.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "parent.com4" { + type master; + file "/var/bind/partition4/parent.com.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "child.parent.com4" { + type master; + file "/var/bind/partition4/child.parent.com.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "example.com4" { + type master; + file "/var/bind/partition4/example.com.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "dskey.example.com4" { + type master; + file "/var/bind/partition4/dskey.example.com.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "not.loaded4" { + type master; + file "/var/bind/partition4/not.loaded.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "zone.requires.review4" { + type master; + file "/var/bind/partition4/zone.requires.review.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "list-records4" { + type master; + file "/var/bind/partition4/list-records.hosts"; + allow-update { key "vinyldns."; }; + }; + +zone "open4" { + type master; + file "/var/bind/partition4/open.hosts"; + allow-update { any; }; + allow-transfer { any; }; + }; diff --git a/quickstart/bind9/zones/_template/0.0.0.1.1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa b/quickstart/bind9/zones/_template/0.0.0.1.1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa new file mode 100644 index 000000000..46ca61a46 --- /dev/null +++ b/quickstart/bind9/zones/_template/0.0.0.1.1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa @@ -0,0 +1,12 @@ +$ttl 38400 +0.0.0.1.{partition}.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa. IN SOA 172.17.42.1. admin.vinyldns.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +0.0.0.1.{partition}.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa. IN NS 172.17.42.1. +4.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR www.vinyldns. +5.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR mail.vinyldns. +0.0.0.0.f.f.f.f.0.0.0.0.0.0.0.0 IN PTR high.value.domain.ip6. +2.0.0.0.f.f.f.f.0.0.0.0.0.0.0.0 IN PTR needs.review.domain.ip6. diff --git a/quickstart/bind9/zones/_template/1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa b/quickstart/bind9/zones/_template/1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa new file mode 100644 index 000000000..4eee859bd --- /dev/null +++ b/quickstart/bind9/zones/_template/1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa @@ -0,0 +1,13 @@ +$ttl 38400 +{partition}.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa. IN SOA 172.17.42.1. admin.vinyldns.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +{partition}.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa. IN NS 172.17.42.1. +0.0.0.1 IN NS 172.17.42.1. +4.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR www.vinyldns. +5.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR mail.vinyldns. +0.0.0.0.f.f.f.f.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR high.value.domain.ip6. +2.0.0.0.f.f.f.f.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR needs.review.domain.ip6. diff --git a/quickstart/bind9/zones/_template/10.10.in-addr.arpa b/quickstart/bind9/zones/_template/10.10.in-addr.arpa new file mode 100644 index 000000000..67b80e585 --- /dev/null +++ b/quickstart/bind9/zones/_template/10.10.in-addr.arpa @@ -0,0 +1,10 @@ +$ttl 38400 +{partition}.10.in-addr.arpa. IN SOA 172.17.42.1. admin.vinyldns.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +{partition}.10.in-addr.arpa. IN NS 172.17.42.1. +24.0 IN PTR www.vinyl. +25.0 IN PTR mail.vinyl. diff --git a/quickstart/bind9/zones/_template/192^30.2.0.192.in-addr.arpa b/quickstart/bind9/zones/_template/192^30.2.0.192.in-addr.arpa new file mode 100644 index 000000000..85f09bceb --- /dev/null +++ b/quickstart/bind9/zones/_template/192^30.2.0.192.in-addr.arpa @@ -0,0 +1,11 @@ +$ttl 38400 +192/30.{partition}.0.192.in-addr.arpa. IN SOA 172.17.42.1. admin.vinyldns.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +192/30.{partition}.0.192.in-addr.arpa. IN NS 172.17.42.1. +192 IN PTR portal.vinyldns. +194 IN PTR mail.vinyldns. +195 IN PTR test.vinyldns. diff --git a/quickstart/bind9/zones/_template/2.0.192.in-addr.arpa b/quickstart/bind9/zones/_template/2.0.192.in-addr.arpa new file mode 100644 index 000000000..c457c2575 --- /dev/null +++ b/quickstart/bind9/zones/_template/2.0.192.in-addr.arpa @@ -0,0 +1,15 @@ +$ttl 38400 +{partition}.0.192.in-addr.arpa. IN SOA 172.17.42.1. admin.vinyldns.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +{partition}.0.192.in-addr.arpa. IN NS 172.17.42.1. +192/30 IN NS 172.17.42.1. +192 IN CNAME 192.192/30.2.0.192.in-addr.arpa. +193 IN CNAME 193.192/30.2.0.192.in-addr.arpa. +194 IN CNAME 194.192/30.2.0.192.in-addr.arpa. +195 IN CNAME 195.192/30.2.0.192.in-addr.arpa. +253 IN PTR high.value.domain.ip4. +255 IN PTR needs.review.domain.ip4 diff --git a/quickstart/bind9/zones/_template/child.parent.com.hosts b/quickstart/bind9/zones/_template/child.parent.com.hosts new file mode 100644 index 000000000..478bea811 --- /dev/null +++ b/quickstart/bind9/zones/_template/child.parent.com.hosts @@ -0,0 +1,9 @@ +$ttl 38400 +$ORIGIN child.parent.com{partition}. +@ IN SOA ns1.parent.com{partition}. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +@ IN NS ns1.parent.com{partition}. diff --git a/quickstart/bind9/zones/_template/dskey.example.com.hosts b/quickstart/bind9/zones/_template/dskey.example.com.hosts new file mode 100644 index 000000000..2e2fabc90 --- /dev/null +++ b/quickstart/bind9/zones/_template/dskey.example.com.hosts @@ -0,0 +1,9 @@ +$TTL 1h +$ORIGIN dskey.example.com{partition}. +@ IN SOA ns1.parent.com{partition}. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +dskey.example.com{partition}. IN NS 172.17.42.1. diff --git a/docker/bind9/zones/sync-test.hosts b/quickstart/bind9/zones/_template/dummy.hosts old mode 100755 new mode 100644 similarity index 54% rename from docker/bind9/zones/sync-test.hosts rename to quickstart/bind9/zones/_template/dummy.hosts index 72024b633..8c72fe987 --- a/docker/bind9/zones/sync-test.hosts +++ b/quickstart/bind9/zones/_template/dummy.hosts @@ -1,17 +1,15 @@ $ttl 38400 -sync-test. IN SOA 172.17.42.1. admin.test.com. ( +dummy{partition}. IN SOA 172.17.42.1. admin.test.com. ( 1439234395 10800 3600 604800 38400 ) -sync-test. IN NS 172.17.42.1. +dummy{partition}. IN NS 172.17.42.1. jenkins IN A 10.1.1.1 foo IN A 2.2.2.2 test IN A 3.3.3.3 test IN A 4.4.4.4 @ IN A 5.5.5.5 already-exists IN A 6.6.6.6 -fqdn.sync-test. IN A 7.7.7.7 -_sip._tcp IN SRV 10 60 5060 foo.sync-test. -existing.dotted IN A 9.9.9.9 +non-approved-delegation IN NS 7.7.7.7 diff --git a/quickstart/bind9/zones/_template/example.com.hosts b/quickstart/bind9/zones/_template/example.com.hosts new file mode 100644 index 000000000..83b4aad2d --- /dev/null +++ b/quickstart/bind9/zones/_template/example.com.hosts @@ -0,0 +1,10 @@ +$TTL 1h +$ORIGIN example.com{partition}. +@ IN SOA ns1.parent.com{partition}. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +example.com{partition}. IN NS 172.17.42.1. +dskey IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/_template/invalid-zone.hosts b/quickstart/bind9/zones/_template/invalid-zone.hosts new file mode 100644 index 000000000..d3e2f1efe --- /dev/null +++ b/quickstart/bind9/zones/_template/invalid-zone.hosts @@ -0,0 +1,17 @@ +$ttl 38400 +invalid-zone{partition}. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +invalid-zone{partition}. IN NS 172.17.42.1. +invalid-zone{partition}. IN NS not-approved.thing.com. +invalid.child.invalid-zone{partition}. IN NS 172.17.42.1. +dotted.host.invalid-zone{partition}. IN A 1.2.3.4 +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/_template/list-records.hosts b/quickstart/bind9/zones/_template/list-records.hosts new file mode 100644 index 000000000..d5d8b44c6 --- /dev/null +++ b/quickstart/bind9/zones/_template/list-records.hosts @@ -0,0 +1,38 @@ +$ttl 38400 +list-records{partition}. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-records{partition}. IN NS 172.17.42.1. +00-test-list-recordsets-0-A IN A 10.1.1.1 +00-test-list-recordsets-0-A IN A 10.2.2.2 +00-test-list-recordsets-0-CNAME IN CNAME cname1. +00-test-list-recordsets-1-A IN A 10.1.1.1 +00-test-list-recordsets-1-A IN A 10.2.2.2 +00-test-list-recordsets-1-CNAME IN CNAME cname1. +00-test-list-recordsets-2-A IN A 10.1.1.1 +00-test-list-recordsets-2-A IN A 10.2.2.2 +00-test-list-recordsets-2-CNAME IN CNAME cname1. +00-test-list-recordsets-3-A IN A 10.1.1.1 +00-test-list-recordsets-3-A IN A 10.2.2.2 +00-test-list-recordsets-3-CNAME IN CNAME cname1. +00-test-list-recordsets-4-A IN A 10.1.1.1 +00-test-list-recordsets-4-A IN A 10.2.2.2 +00-test-list-recordsets-4-CNAME IN CNAME cname1. +00-test-list-recordsets-5-A IN A 10.1.1.1 +00-test-list-recordsets-5-A IN A 10.2.2.2 +00-test-list-recordsets-5-CNAME IN CNAME cname1. +00-test-list-recordsets-6-A IN A 10.1.1.1 +00-test-list-recordsets-6-A IN A 10.2.2.2 +00-test-list-recordsets-6-CNAME IN CNAME cname1. +00-test-list-recordsets-7-A IN A 10.1.1.1 +00-test-list-recordsets-7-A IN A 10.2.2.2 +00-test-list-recordsets-7-CNAME IN CNAME cname1. +00-test-list-recordsets-8-A IN A 10.1.1.1 +00-test-list-recordsets-8-A IN A 10.2.2.2 +00-test-list-recordsets-8-CNAME IN CNAME cname1. +00-test-list-recordsets-9-A IN A 10.1.1.1 +00-test-list-recordsets-9-A IN A 10.2.2.2 +00-test-list-recordsets-9-CNAME IN CNAME cname1. diff --git a/quickstart/bind9/zones/_template/list-zones-test-searched-1.hosts b/quickstart/bind9/zones/_template/list-zones-test-searched-1.hosts new file mode 100644 index 000000000..a9de7daa1 --- /dev/null +++ b/quickstart/bind9/zones/_template/list-zones-test-searched-1.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +list-zones-test-searched-1{partition}. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-zones-test-searched-1{partition}. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/_template/list-zones-test-searched-2.hosts b/quickstart/bind9/zones/_template/list-zones-test-searched-2.hosts new file mode 100644 index 000000000..881467a92 --- /dev/null +++ b/quickstart/bind9/zones/_template/list-zones-test-searched-2.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +list-zones-test-searched-2{partition}. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-zones-test-searched-2{partition}. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/_template/list-zones-test-searched-3.hosts b/quickstart/bind9/zones/_template/list-zones-test-searched-3.hosts new file mode 100644 index 000000000..9b6513f1f --- /dev/null +++ b/quickstart/bind9/zones/_template/list-zones-test-searched-3.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +list-zones-test-searched-3{partition}. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-zones-test-searched-3{partition}. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/_template/list-zones-test-unfiltered-1.hosts b/quickstart/bind9/zones/_template/list-zones-test-unfiltered-1.hosts new file mode 100644 index 000000000..dd9dd12b6 --- /dev/null +++ b/quickstart/bind9/zones/_template/list-zones-test-unfiltered-1.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +list-zones-test-unfiltered-1{partition}. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-zones-test-unfiltered-1{partition}. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/_template/list-zones-test-unfiltered-2.hosts b/quickstart/bind9/zones/_template/list-zones-test-unfiltered-2.hosts new file mode 100644 index 000000000..8469e24d0 --- /dev/null +++ b/quickstart/bind9/zones/_template/list-zones-test-unfiltered-2.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +list-zones-test-unfiltered-2{partition}. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-zones-test-unfiltered-2{partition}. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/_template/non.test.shared.hosts b/quickstart/bind9/zones/_template/non.test.shared.hosts new file mode 100644 index 000000000..462e42081 --- /dev/null +++ b/quickstart/bind9/zones/_template/non.test.shared.hosts @@ -0,0 +1,13 @@ +$ttl 38400 +non.test.shared{partition}. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +non.test.shared{partition}. IN NS 172.17.42.1. +@ IN A 1.1.1.1 +delete-test-batch IN A 2.2.2.2 +update-test-batch IN A 3.3.3.3 +delete-test IN A 4.4.4.4 +update-test IN A 5.5.5.5 diff --git a/quickstart/bind9/zones/_template/not.loaded.hosts b/quickstart/bind9/zones/_template/not.loaded.hosts new file mode 100644 index 000000000..ccb468620 --- /dev/null +++ b/quickstart/bind9/zones/_template/not.loaded.hosts @@ -0,0 +1,9 @@ +$ttl 38400 +not.loaded{partition}. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +not.loaded{partition}. IN NS 172.17.42.1. +foo IN A 1.1.1.1 diff --git a/quickstart/bind9/zones/_template/ok.hosts b/quickstart/bind9/zones/_template/ok.hosts new file mode 100644 index 000000000..35f75b587 --- /dev/null +++ b/quickstart/bind9/zones/_template/ok.hosts @@ -0,0 +1,16 @@ +$ttl 38400 +ok{partition}. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +ok{partition}. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 +dotted.a IN A 7.7.7.7 +dottedc.name IN CNAME test.example.com diff --git a/quickstart/bind9/zones/_template/old-shared.hosts b/quickstart/bind9/zones/_template/old-shared.hosts new file mode 100644 index 000000000..026d01349 --- /dev/null +++ b/quickstart/bind9/zones/_template/old-shared.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +old-shared{partition}. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +old-shared{partition}. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/_template/old-vinyldns2.hosts b/quickstart/bind9/zones/_template/old-vinyldns2.hosts new file mode 100644 index 000000000..a1d20aa6d --- /dev/null +++ b/quickstart/bind9/zones/_template/old-vinyldns2.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +old-vinyldns2{partition}. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +old-vinyldns2{partition}. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/_template/old-vinyldns3.hosts b/quickstart/bind9/zones/_template/old-vinyldns3.hosts new file mode 100644 index 000000000..277635157 --- /dev/null +++ b/quickstart/bind9/zones/_template/old-vinyldns3.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +old-vinyldns3{partition}. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +old-vinyldns3{partition}. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/_template/one-time-shared.hosts b/quickstart/bind9/zones/_template/one-time-shared.hosts new file mode 100644 index 000000000..0286e5ded --- /dev/null +++ b/quickstart/bind9/zones/_template/one-time-shared.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +one-time-shared{partition}. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +one-time-shared{partition}. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/_template/one-time.hosts b/quickstart/bind9/zones/_template/one-time.hosts new file mode 100644 index 000000000..df2fd08fd --- /dev/null +++ b/quickstart/bind9/zones/_template/one-time.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +one-time{partition}. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +one-time{partition}. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/_template/open.hosts b/quickstart/bind9/zones/_template/open.hosts new file mode 100644 index 000000000..f4661cd33 --- /dev/null +++ b/quickstart/bind9/zones/_template/open.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +open{partition}. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +open{partition}. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/_template/parent.com.hosts b/quickstart/bind9/zones/_template/parent.com.hosts new file mode 100644 index 000000000..b364ffa3d --- /dev/null +++ b/quickstart/bind9/zones/_template/parent.com.hosts @@ -0,0 +1,15 @@ +$ttl 38400 +$ORIGIN parent.com{partition}. +@ IN SOA ns1.parent.com{partition}. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +parent.com{partition}. IN NS ns1.parent.com{partition}. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +already-exists IN A 6.6.6.6 +ns1 IN A 172.17.42.1 diff --git a/quickstart/bind9/zones/_template/shared.hosts b/quickstart/bind9/zones/_template/shared.hosts new file mode 100644 index 000000000..2d809bb35 --- /dev/null +++ b/quickstart/bind9/zones/_template/shared.hosts @@ -0,0 +1,16 @@ +$ttl 38400 +shared{partition}. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +shared{partition}. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 +delete-test-batch IN A 2.2.2.2 +update-test-batch IN A 3.3.3.3 diff --git a/quickstart/bind9/zones/_template/sync-test.hosts b/quickstart/bind9/zones/_template/sync-test.hosts new file mode 100644 index 000000000..ae95585af --- /dev/null +++ b/quickstart/bind9/zones/_template/sync-test.hosts @@ -0,0 +1,17 @@ +$ttl 38400 +sync-test{partition}. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +sync-test{partition}. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 +fqdn.sync-test{partition}. IN A 7.7.7.7 +_sip._tcp IN SRV 10 60 5060 foo.sync-test. +existing.dotted IN A 9.9.9.9 diff --git a/quickstart/bind9/zones/_template/system-test-history.hosts b/quickstart/bind9/zones/_template/system-test-history.hosts new file mode 100644 index 000000000..d656b3d9b --- /dev/null +++ b/quickstart/bind9/zones/_template/system-test-history.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +system-test-history{partition}. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +system-test-history{partition}. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/_template/system-test.hosts b/quickstart/bind9/zones/_template/system-test.hosts new file mode 100644 index 000000000..f98d54779 --- /dev/null +++ b/quickstart/bind9/zones/_template/system-test.hosts @@ -0,0 +1,16 @@ +$ttl 38400 +system-test{partition}. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +system-test{partition}. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 +high-value-domain IN A 1.1.1.1 +high-VALUE-domain-UPPER-CASE IN A 1.1.1.1 diff --git a/quickstart/bind9/zones/_template/vinyldns.hosts b/quickstart/bind9/zones/_template/vinyldns.hosts new file mode 100644 index 000000000..931b22b92 --- /dev/null +++ b/quickstart/bind9/zones/_template/vinyldns.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +vinyldns{partition}. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +vinyldns{partition}. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/docker/bind9/zones/non.test.shared.hosts b/quickstart/bind9/zones/_template/zone.requires.review.hosts old mode 100755 new mode 100644 similarity index 50% rename from docker/bind9/zones/non.test.shared.hosts rename to quickstart/bind9/zones/_template/zone.requires.review.hosts index e270c8093..715a30e18 --- a/docker/bind9/zones/non.test.shared.hosts +++ b/quickstart/bind9/zones/_template/zone.requires.review.hosts @@ -1,13 +1,11 @@ $ttl 38400 -non.test.shared. IN SOA 172.17.42.1. admin.test.com. ( +zone.requires.review{partition}. IN SOA 172.17.42.1. admin.test.com. ( 1439234395 10800 3600 604800 38400 ) -non.test.shared. IN NS 172.17.42.1. +zone.requires.review{partition}. IN NS 172.17.42.1. @ IN A 1.1.1.1 delete-test-batch IN A 2.2.2.2 update-test-batch IN A 3.3.3.3 -delete-test IN A 4.4.4.4 -update-test IN A 5.5.5.5 diff --git a/docker/bind9/zones/10.10.in-addr.arpa b/quickstart/bind9/zones/default/10.10.in-addr.arpa old mode 100755 new mode 100644 similarity index 100% rename from docker/bind9/zones/10.10.in-addr.arpa rename to quickstart/bind9/zones/default/10.10.in-addr.arpa diff --git a/docker/bind9/zones/child.parent.com.hosts b/quickstart/bind9/zones/default/child.parent.com.hosts similarity index 100% rename from docker/bind9/zones/child.parent.com.hosts rename to quickstart/bind9/zones/default/child.parent.com.hosts diff --git a/docker/bind9/zones/dskey.example.com.hosts b/quickstart/bind9/zones/default/dskey.example.com.hosts similarity index 100% rename from docker/bind9/zones/dskey.example.com.hosts rename to quickstart/bind9/zones/default/dskey.example.com.hosts diff --git a/docker/bind9/zones/dummy.hosts b/quickstart/bind9/zones/default/dummy.hosts similarity index 100% rename from docker/bind9/zones/dummy.hosts rename to quickstart/bind9/zones/default/dummy.hosts diff --git a/docker/bind9/zones/example.com.hosts b/quickstart/bind9/zones/default/example.com.hosts similarity index 100% rename from docker/bind9/zones/example.com.hosts rename to quickstart/bind9/zones/default/example.com.hosts diff --git a/docker/bind9/zones/invalid-zone.hosts b/quickstart/bind9/zones/default/invalid-zone.hosts similarity index 100% rename from docker/bind9/zones/invalid-zone.hosts rename to quickstart/bind9/zones/default/invalid-zone.hosts diff --git a/docker/bind9/zones/list-records.hosts b/quickstart/bind9/zones/default/list-records.hosts similarity index 100% rename from docker/bind9/zones/list-records.hosts rename to quickstart/bind9/zones/default/list-records.hosts diff --git a/docker/bind9/zones/list-zones-test-searched-1.hosts b/quickstart/bind9/zones/default/list-zones-test-searched-1.hosts similarity index 100% rename from docker/bind9/zones/list-zones-test-searched-1.hosts rename to quickstart/bind9/zones/default/list-zones-test-searched-1.hosts diff --git a/docker/bind9/zones/list-zones-test-searched-2.hosts b/quickstart/bind9/zones/default/list-zones-test-searched-2.hosts similarity index 100% rename from docker/bind9/zones/list-zones-test-searched-2.hosts rename to quickstart/bind9/zones/default/list-zones-test-searched-2.hosts diff --git a/docker/bind9/zones/list-zones-test-searched-3.hosts b/quickstart/bind9/zones/default/list-zones-test-searched-3.hosts similarity index 100% rename from docker/bind9/zones/list-zones-test-searched-3.hosts rename to quickstart/bind9/zones/default/list-zones-test-searched-3.hosts diff --git a/docker/bind9/zones/list-zones-test-unfiltered-1.hosts b/quickstart/bind9/zones/default/list-zones-test-unfiltered-1.hosts old mode 100755 new mode 100644 similarity index 100% rename from docker/bind9/zones/list-zones-test-unfiltered-1.hosts rename to quickstart/bind9/zones/default/list-zones-test-unfiltered-1.hosts diff --git a/docker/bind9/zones/list-zones-test-unfiltered-2.hosts b/quickstart/bind9/zones/default/list-zones-test-unfiltered-2.hosts old mode 100755 new mode 100644 similarity index 100% rename from docker/bind9/zones/list-zones-test-unfiltered-2.hosts rename to quickstart/bind9/zones/default/list-zones-test-unfiltered-2.hosts diff --git a/quickstart/bind9/zones/default/non.test.shared.hosts b/quickstart/bind9/zones/default/non.test.shared.hosts new file mode 100644 index 000000000..098846079 --- /dev/null +++ b/quickstart/bind9/zones/default/non.test.shared.hosts @@ -0,0 +1,13 @@ +$ttl 38400 +non.test.shared. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +non.test.shared. IN NS 172.17.42.1. +@ IN A 1.1.1.1 +delete-test-batch IN A 2.2.2.2 +update-test-batch IN A 3.3.3.3 +delete-test IN A 4.4.4.4 +update-test IN A 5.5.5.5 diff --git a/docker/bind9/zones/not.loaded.hosts b/quickstart/bind9/zones/default/not.loaded.hosts similarity index 100% rename from docker/bind9/zones/not.loaded.hosts rename to quickstart/bind9/zones/default/not.loaded.hosts diff --git a/docker/bind9/zones/ok.hosts b/quickstart/bind9/zones/default/ok.hosts old mode 100755 new mode 100644 similarity index 100% rename from docker/bind9/zones/ok.hosts rename to quickstart/bind9/zones/default/ok.hosts diff --git a/docker/bind9/zones/old-shared.hosts b/quickstart/bind9/zones/default/old-shared.hosts old mode 100755 new mode 100644 similarity index 100% rename from docker/bind9/zones/old-shared.hosts rename to quickstart/bind9/zones/default/old-shared.hosts diff --git a/docker/bind9/zones/old-vinyldns2.hosts b/quickstart/bind9/zones/default/old-vinyldns2.hosts old mode 100755 new mode 100644 similarity index 100% rename from docker/bind9/zones/old-vinyldns2.hosts rename to quickstart/bind9/zones/default/old-vinyldns2.hosts diff --git a/docker/bind9/zones/old-vinyldns3.hosts b/quickstart/bind9/zones/default/old-vinyldns3.hosts old mode 100755 new mode 100644 similarity index 100% rename from docker/bind9/zones/old-vinyldns3.hosts rename to quickstart/bind9/zones/default/old-vinyldns3.hosts diff --git a/docker/bind9/zones/one-time-shared.hosts b/quickstart/bind9/zones/default/one-time-shared.hosts old mode 100755 new mode 100644 similarity index 100% rename from docker/bind9/zones/one-time-shared.hosts rename to quickstart/bind9/zones/default/one-time-shared.hosts diff --git a/docker/bind9/zones/one-time.hosts b/quickstart/bind9/zones/default/one-time.hosts old mode 100755 new mode 100644 similarity index 100% rename from docker/bind9/zones/one-time.hosts rename to quickstart/bind9/zones/default/one-time.hosts diff --git a/docker/bind9/zones/open.hosts b/quickstart/bind9/zones/default/open.hosts similarity index 100% rename from docker/bind9/zones/open.hosts rename to quickstart/bind9/zones/default/open.hosts diff --git a/docker/bind9/zones/parent.com.hosts b/quickstart/bind9/zones/default/parent.com.hosts old mode 100755 new mode 100644 similarity index 100% rename from docker/bind9/zones/parent.com.hosts rename to quickstart/bind9/zones/default/parent.com.hosts diff --git a/docker/bind9/zones/shared.hosts b/quickstart/bind9/zones/default/shared.hosts old mode 100755 new mode 100644 similarity index 100% rename from docker/bind9/zones/shared.hosts rename to quickstart/bind9/zones/default/shared.hosts diff --git a/quickstart/bind9/zones/default/sync-test.hosts b/quickstart/bind9/zones/default/sync-test.hosts new file mode 100644 index 000000000..a369f01dd --- /dev/null +++ b/quickstart/bind9/zones/default/sync-test.hosts @@ -0,0 +1,17 @@ +$ttl 38400 +sync-test. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +sync-test. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 +fqdn.sync-test. IN A 7.7.7.7 +_sip._tcp IN SRV 10 60 5060 foo.sync-test. +existing.dotted IN A 9.9.9.9 diff --git a/docker/bind9/zones/system-test-history.hosts b/quickstart/bind9/zones/default/system-test-history.hosts old mode 100755 new mode 100644 similarity index 100% rename from docker/bind9/zones/system-test-history.hosts rename to quickstart/bind9/zones/default/system-test-history.hosts diff --git a/docker/bind9/zones/system-test.hosts b/quickstart/bind9/zones/default/system-test.hosts old mode 100755 new mode 100644 similarity index 100% rename from docker/bind9/zones/system-test.hosts rename to quickstart/bind9/zones/default/system-test.hosts diff --git a/docker/bind9/zones/vinyldns.hosts b/quickstart/bind9/zones/default/vinyldns.hosts similarity index 100% rename from docker/bind9/zones/vinyldns.hosts rename to quickstart/bind9/zones/default/vinyldns.hosts diff --git a/docker/bind9/zones/zone.requires.review.hosts b/quickstart/bind9/zones/default/zone.requires.review.hosts similarity index 100% rename from docker/bind9/zones/zone.requires.review.hosts rename to quickstart/bind9/zones/default/zone.requires.review.hosts diff --git a/docker/bind9/zones/0.0.0.1.1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa b/quickstart/bind9/zones/partition1/0.0.0.1.1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa old mode 100755 new mode 100644 similarity index 100% rename from docker/bind9/zones/0.0.0.1.1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa rename to quickstart/bind9/zones/partition1/0.0.0.1.1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa diff --git a/docker/bind9/zones/1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa b/quickstart/bind9/zones/partition1/1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa old mode 100755 new mode 100644 similarity index 100% rename from docker/bind9/zones/1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa rename to quickstart/bind9/zones/partition1/1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa diff --git a/quickstart/bind9/zones/partition1/10.10.in-addr.arpa b/quickstart/bind9/zones/partition1/10.10.in-addr.arpa new file mode 100644 index 000000000..3b11d2099 --- /dev/null +++ b/quickstart/bind9/zones/partition1/10.10.in-addr.arpa @@ -0,0 +1,10 @@ +$ttl 38400 +1.10.in-addr.arpa. IN SOA 172.17.42.1. admin.vinyldns.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +1.10.in-addr.arpa. IN NS 172.17.42.1. +24.0 IN PTR www.vinyl. +25.0 IN PTR mail.vinyl. diff --git a/quickstart/bind9/zones/partition1/192^30.2.0.192.in-addr.arpa b/quickstart/bind9/zones/partition1/192^30.2.0.192.in-addr.arpa new file mode 100644 index 000000000..f95c2de07 --- /dev/null +++ b/quickstart/bind9/zones/partition1/192^30.2.0.192.in-addr.arpa @@ -0,0 +1,11 @@ +$ttl 38400 +192/30.1.0.192.in-addr.arpa. IN SOA 172.17.42.1. admin.vinyldns.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +192/30.1.0.192.in-addr.arpa. IN NS 172.17.42.1. +192 IN PTR portal.vinyldns. +194 IN PTR mail.vinyldns. +195 IN PTR test.vinyldns. diff --git a/quickstart/bind9/zones/partition1/2.0.192.in-addr.arpa b/quickstart/bind9/zones/partition1/2.0.192.in-addr.arpa new file mode 100644 index 000000000..e9c799534 --- /dev/null +++ b/quickstart/bind9/zones/partition1/2.0.192.in-addr.arpa @@ -0,0 +1,15 @@ +$ttl 38400 +1.0.192.in-addr.arpa. IN SOA 172.17.42.1. admin.vinyldns.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +1.0.192.in-addr.arpa. IN NS 172.17.42.1. +192/30 IN NS 172.17.42.1. +192 IN CNAME 192.192/30.2.0.192.in-addr.arpa. +193 IN CNAME 193.192/30.2.0.192.in-addr.arpa. +194 IN CNAME 194.192/30.2.0.192.in-addr.arpa. +195 IN CNAME 195.192/30.2.0.192.in-addr.arpa. +253 IN PTR high.value.domain.ip4. +255 IN PTR needs.review.domain.ip4 diff --git a/quickstart/bind9/zones/partition1/child.parent.com.hosts b/quickstart/bind9/zones/partition1/child.parent.com.hosts new file mode 100644 index 000000000..b43e247c9 --- /dev/null +++ b/quickstart/bind9/zones/partition1/child.parent.com.hosts @@ -0,0 +1,9 @@ +$ttl 38400 +$ORIGIN child.parent.com1. +@ IN SOA ns1.parent.com1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +@ IN NS ns1.parent.com1. diff --git a/quickstart/bind9/zones/partition1/dskey.example.com.hosts b/quickstart/bind9/zones/partition1/dskey.example.com.hosts new file mode 100644 index 000000000..1e9300b6f --- /dev/null +++ b/quickstart/bind9/zones/partition1/dskey.example.com.hosts @@ -0,0 +1,9 @@ +$TTL 1h +$ORIGIN dskey.example.com1. +@ IN SOA ns1.parent.com1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +dskey.example.com1. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition1/dummy.hosts b/quickstart/bind9/zones/partition1/dummy.hosts new file mode 100644 index 000000000..804ff27f0 --- /dev/null +++ b/quickstart/bind9/zones/partition1/dummy.hosts @@ -0,0 +1,15 @@ +$ttl 38400 +dummy1. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +dummy1. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 +non-approved-delegation IN NS 7.7.7.7 diff --git a/quickstart/bind9/zones/partition1/example.com.hosts b/quickstart/bind9/zones/partition1/example.com.hosts new file mode 100644 index 000000000..93994fa0b --- /dev/null +++ b/quickstart/bind9/zones/partition1/example.com.hosts @@ -0,0 +1,10 @@ +$TTL 1h +$ORIGIN example.com1. +@ IN SOA ns1.parent.com1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +example.com1. IN NS 172.17.42.1. +dskey IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition1/invalid-zone.hosts b/quickstart/bind9/zones/partition1/invalid-zone.hosts new file mode 100644 index 000000000..bbb9bd122 --- /dev/null +++ b/quickstart/bind9/zones/partition1/invalid-zone.hosts @@ -0,0 +1,17 @@ +$ttl 38400 +invalid-zone1. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +invalid-zone1. IN NS 172.17.42.1. +invalid-zone1. IN NS not-approved.thing.com. +invalid.child.invalid-zone1. IN NS 172.17.42.1. +dotted.host.invalid-zone1. IN A 1.2.3.4 +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/partition1/list-records.hosts b/quickstart/bind9/zones/partition1/list-records.hosts new file mode 100644 index 000000000..f17446273 --- /dev/null +++ b/quickstart/bind9/zones/partition1/list-records.hosts @@ -0,0 +1,38 @@ +$ttl 38400 +list-records1. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-records1. IN NS 172.17.42.1. +00-test-list-recordsets-0-A IN A 10.1.1.1 +00-test-list-recordsets-0-A IN A 10.2.2.2 +00-test-list-recordsets-0-CNAME IN CNAME cname1. +00-test-list-recordsets-1-A IN A 10.1.1.1 +00-test-list-recordsets-1-A IN A 10.2.2.2 +00-test-list-recordsets-1-CNAME IN CNAME cname1. +00-test-list-recordsets-2-A IN A 10.1.1.1 +00-test-list-recordsets-2-A IN A 10.2.2.2 +00-test-list-recordsets-2-CNAME IN CNAME cname1. +00-test-list-recordsets-3-A IN A 10.1.1.1 +00-test-list-recordsets-3-A IN A 10.2.2.2 +00-test-list-recordsets-3-CNAME IN CNAME cname1. +00-test-list-recordsets-4-A IN A 10.1.1.1 +00-test-list-recordsets-4-A IN A 10.2.2.2 +00-test-list-recordsets-4-CNAME IN CNAME cname1. +00-test-list-recordsets-5-A IN A 10.1.1.1 +00-test-list-recordsets-5-A IN A 10.2.2.2 +00-test-list-recordsets-5-CNAME IN CNAME cname1. +00-test-list-recordsets-6-A IN A 10.1.1.1 +00-test-list-recordsets-6-A IN A 10.2.2.2 +00-test-list-recordsets-6-CNAME IN CNAME cname1. +00-test-list-recordsets-7-A IN A 10.1.1.1 +00-test-list-recordsets-7-A IN A 10.2.2.2 +00-test-list-recordsets-7-CNAME IN CNAME cname1. +00-test-list-recordsets-8-A IN A 10.1.1.1 +00-test-list-recordsets-8-A IN A 10.2.2.2 +00-test-list-recordsets-8-CNAME IN CNAME cname1. +00-test-list-recordsets-9-A IN A 10.1.1.1 +00-test-list-recordsets-9-A IN A 10.2.2.2 +00-test-list-recordsets-9-CNAME IN CNAME cname1. diff --git a/quickstart/bind9/zones/partition1/list-zones-test-searched-1.hosts b/quickstart/bind9/zones/partition1/list-zones-test-searched-1.hosts new file mode 100644 index 000000000..bf7c6835f --- /dev/null +++ b/quickstart/bind9/zones/partition1/list-zones-test-searched-1.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +list-zones-test-searched-11. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-zones-test-searched-11. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition1/list-zones-test-searched-2.hosts b/quickstart/bind9/zones/partition1/list-zones-test-searched-2.hosts new file mode 100644 index 000000000..45e746668 --- /dev/null +++ b/quickstart/bind9/zones/partition1/list-zones-test-searched-2.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +list-zones-test-searched-21. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-zones-test-searched-21. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition1/list-zones-test-searched-3.hosts b/quickstart/bind9/zones/partition1/list-zones-test-searched-3.hosts new file mode 100644 index 000000000..ee4224234 --- /dev/null +++ b/quickstart/bind9/zones/partition1/list-zones-test-searched-3.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +list-zones-test-searched-31. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-zones-test-searched-31. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition1/list-zones-test-unfiltered-1.hosts b/quickstart/bind9/zones/partition1/list-zones-test-unfiltered-1.hosts new file mode 100644 index 000000000..0ee4fecd5 --- /dev/null +++ b/quickstart/bind9/zones/partition1/list-zones-test-unfiltered-1.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +list-zones-test-unfiltered-11. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-zones-test-unfiltered-11. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition1/list-zones-test-unfiltered-2.hosts b/quickstart/bind9/zones/partition1/list-zones-test-unfiltered-2.hosts new file mode 100644 index 000000000..e59eecd2f --- /dev/null +++ b/quickstart/bind9/zones/partition1/list-zones-test-unfiltered-2.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +list-zones-test-unfiltered-21. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-zones-test-unfiltered-21. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition1/non.test.shared.hosts b/quickstart/bind9/zones/partition1/non.test.shared.hosts new file mode 100644 index 000000000..6a99fb0c5 --- /dev/null +++ b/quickstart/bind9/zones/partition1/non.test.shared.hosts @@ -0,0 +1,13 @@ +$ttl 38400 +non.test.shared1. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +non.test.shared1. IN NS 172.17.42.1. +@ IN A 1.1.1.1 +delete-test-batch IN A 2.2.2.2 +update-test-batch IN A 3.3.3.3 +delete-test IN A 4.4.4.4 +update-test IN A 5.5.5.5 diff --git a/quickstart/bind9/zones/partition1/not.loaded.hosts b/quickstart/bind9/zones/partition1/not.loaded.hosts new file mode 100644 index 000000000..117e55ccc --- /dev/null +++ b/quickstart/bind9/zones/partition1/not.loaded.hosts @@ -0,0 +1,9 @@ +$ttl 38400 +not.loaded1. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +not.loaded1. IN NS 172.17.42.1. +foo IN A 1.1.1.1 diff --git a/quickstart/bind9/zones/partition1/ok.hosts b/quickstart/bind9/zones/partition1/ok.hosts new file mode 100644 index 000000000..c8748a430 --- /dev/null +++ b/quickstart/bind9/zones/partition1/ok.hosts @@ -0,0 +1,16 @@ +$ttl 38400 +ok1. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +ok1. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 +dotted.a IN A 7.7.7.7 +dottedc.name IN CNAME test.example.com diff --git a/quickstart/bind9/zones/partition1/old-shared.hosts b/quickstart/bind9/zones/partition1/old-shared.hosts new file mode 100644 index 000000000..487dd6bbe --- /dev/null +++ b/quickstart/bind9/zones/partition1/old-shared.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +old-shared1. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +old-shared1. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/partition1/old-vinyldns2.hosts b/quickstart/bind9/zones/partition1/old-vinyldns2.hosts new file mode 100644 index 000000000..e0ffb3bbf --- /dev/null +++ b/quickstart/bind9/zones/partition1/old-vinyldns2.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +old-vinyldns21. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +old-vinyldns21. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/partition1/old-vinyldns3.hosts b/quickstart/bind9/zones/partition1/old-vinyldns3.hosts new file mode 100644 index 000000000..f98e656d8 --- /dev/null +++ b/quickstart/bind9/zones/partition1/old-vinyldns3.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +old-vinyldns31. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +old-vinyldns31. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/partition1/one-time-shared.hosts b/quickstart/bind9/zones/partition1/one-time-shared.hosts new file mode 100644 index 000000000..df3f87abe --- /dev/null +++ b/quickstart/bind9/zones/partition1/one-time-shared.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +one-time-shared1. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +one-time-shared1. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition1/one-time.hosts b/quickstart/bind9/zones/partition1/one-time.hosts new file mode 100644 index 000000000..abe1f028f --- /dev/null +++ b/quickstart/bind9/zones/partition1/one-time.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +one-time1. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +one-time1. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/partition1/open.hosts b/quickstart/bind9/zones/partition1/open.hosts new file mode 100644 index 000000000..f72115af3 --- /dev/null +++ b/quickstart/bind9/zones/partition1/open.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +open1. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +open1. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition1/parent.com.hosts b/quickstart/bind9/zones/partition1/parent.com.hosts new file mode 100644 index 000000000..e93a37057 --- /dev/null +++ b/quickstart/bind9/zones/partition1/parent.com.hosts @@ -0,0 +1,15 @@ +$ttl 38400 +$ORIGIN parent.com1. +@ IN SOA ns1.parent.com1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +parent.com1. IN NS ns1.parent.com1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +already-exists IN A 6.6.6.6 +ns1 IN A 172.17.42.1 diff --git a/quickstart/bind9/zones/partition1/shared.hosts b/quickstart/bind9/zones/partition1/shared.hosts new file mode 100644 index 000000000..5be10b61d --- /dev/null +++ b/quickstart/bind9/zones/partition1/shared.hosts @@ -0,0 +1,16 @@ +$ttl 38400 +shared1. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +shared1. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 +delete-test-batch IN A 2.2.2.2 +update-test-batch IN A 3.3.3.3 diff --git a/quickstart/bind9/zones/partition1/sync-test.hosts b/quickstart/bind9/zones/partition1/sync-test.hosts new file mode 100644 index 000000000..365b097a7 --- /dev/null +++ b/quickstart/bind9/zones/partition1/sync-test.hosts @@ -0,0 +1,17 @@ +$ttl 38400 +sync-test1. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +sync-test1. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 +fqdn.sync-test1. IN A 7.7.7.7 +_sip._tcp IN SRV 10 60 5060 foo.sync-test. +existing.dotted IN A 9.9.9.9 diff --git a/quickstart/bind9/zones/partition1/system-test-history.hosts b/quickstart/bind9/zones/partition1/system-test-history.hosts new file mode 100644 index 000000000..6c7c73058 --- /dev/null +++ b/quickstart/bind9/zones/partition1/system-test-history.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +system-test-history1. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +system-test-history1. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/partition1/system-test.hosts b/quickstart/bind9/zones/partition1/system-test.hosts new file mode 100644 index 000000000..0a138f9ed --- /dev/null +++ b/quickstart/bind9/zones/partition1/system-test.hosts @@ -0,0 +1,16 @@ +$ttl 38400 +system-test1. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +system-test1. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 +high-value-domain IN A 1.1.1.1 +high-VALUE-domain-UPPER-CASE IN A 1.1.1.1 diff --git a/quickstart/bind9/zones/partition1/vinyldns.hosts b/quickstart/bind9/zones/partition1/vinyldns.hosts new file mode 100644 index 000000000..c5fc44e94 --- /dev/null +++ b/quickstart/bind9/zones/partition1/vinyldns.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +vinyldns1. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +vinyldns1. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/partition1/zone.requires.review.hosts b/quickstart/bind9/zones/partition1/zone.requires.review.hosts new file mode 100644 index 000000000..e1522d7e1 --- /dev/null +++ b/quickstart/bind9/zones/partition1/zone.requires.review.hosts @@ -0,0 +1,11 @@ +$ttl 38400 +zone.requires.review1. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +zone.requires.review1. IN NS 172.17.42.1. +@ IN A 1.1.1.1 +delete-test-batch IN A 2.2.2.2 +update-test-batch IN A 3.3.3.3 diff --git a/quickstart/bind9/zones/partition2/0.0.0.1.1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa b/quickstart/bind9/zones/partition2/0.0.0.1.1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa new file mode 100644 index 000000000..1aed1cd53 --- /dev/null +++ b/quickstart/bind9/zones/partition2/0.0.0.1.1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa @@ -0,0 +1,12 @@ +$ttl 38400 +0.0.0.1.2.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa. IN SOA 172.17.42.1. admin.vinyldns.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +0.0.0.1.2.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa. IN NS 172.17.42.1. +4.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR www.vinyldns. +5.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR mail.vinyldns. +0.0.0.0.f.f.f.f.0.0.0.0.0.0.0.0 IN PTR high.value.domain.ip6. +2.0.0.0.f.f.f.f.0.0.0.0.0.0.0.0 IN PTR needs.review.domain.ip6. diff --git a/quickstart/bind9/zones/partition2/1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa b/quickstart/bind9/zones/partition2/1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa new file mode 100644 index 000000000..861e849ea --- /dev/null +++ b/quickstart/bind9/zones/partition2/1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa @@ -0,0 +1,13 @@ +$ttl 38400 +2.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa. IN SOA 172.17.42.1. admin.vinyldns.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +2.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa. IN NS 172.17.42.1. +0.0.0.1 IN NS 172.17.42.1. +4.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR www.vinyldns. +5.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR mail.vinyldns. +0.0.0.0.f.f.f.f.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR high.value.domain.ip6. +2.0.0.0.f.f.f.f.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR needs.review.domain.ip6. diff --git a/quickstart/bind9/zones/partition2/10.10.in-addr.arpa b/quickstart/bind9/zones/partition2/10.10.in-addr.arpa new file mode 100644 index 000000000..2031c6c82 --- /dev/null +++ b/quickstart/bind9/zones/partition2/10.10.in-addr.arpa @@ -0,0 +1,10 @@ +$ttl 38400 +2.10.in-addr.arpa. IN SOA 172.17.42.1. admin.vinyldns.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +2.10.in-addr.arpa. IN NS 172.17.42.1. +24.0 IN PTR www.vinyl. +25.0 IN PTR mail.vinyl. diff --git a/docker/bind9/zones/192^30.2.0.192.in-addr.arpa b/quickstart/bind9/zones/partition2/192^30.2.0.192.in-addr.arpa similarity index 100% rename from docker/bind9/zones/192^30.2.0.192.in-addr.arpa rename to quickstart/bind9/zones/partition2/192^30.2.0.192.in-addr.arpa diff --git a/docker/bind9/zones/2.0.192.in-addr.arpa b/quickstart/bind9/zones/partition2/2.0.192.in-addr.arpa similarity index 100% rename from docker/bind9/zones/2.0.192.in-addr.arpa rename to quickstart/bind9/zones/partition2/2.0.192.in-addr.arpa diff --git a/quickstart/bind9/zones/partition2/child.parent.com.hosts b/quickstart/bind9/zones/partition2/child.parent.com.hosts new file mode 100644 index 000000000..a1a1177b3 --- /dev/null +++ b/quickstart/bind9/zones/partition2/child.parent.com.hosts @@ -0,0 +1,9 @@ +$ttl 38400 +$ORIGIN child.parent.com2. +@ IN SOA ns1.parent.com2. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +@ IN NS ns1.parent.com2. diff --git a/quickstart/bind9/zones/partition2/dskey.example.com.hosts b/quickstart/bind9/zones/partition2/dskey.example.com.hosts new file mode 100644 index 000000000..e35faa9b5 --- /dev/null +++ b/quickstart/bind9/zones/partition2/dskey.example.com.hosts @@ -0,0 +1,9 @@ +$TTL 1h +$ORIGIN dskey.example.com2. +@ IN SOA ns1.parent.com2. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +dskey.example.com2. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition2/dummy.hosts b/quickstart/bind9/zones/partition2/dummy.hosts new file mode 100644 index 000000000..50346d691 --- /dev/null +++ b/quickstart/bind9/zones/partition2/dummy.hosts @@ -0,0 +1,15 @@ +$ttl 38400 +dummy2. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +dummy2. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 +non-approved-delegation IN NS 7.7.7.7 diff --git a/quickstart/bind9/zones/partition2/example.com.hosts b/quickstart/bind9/zones/partition2/example.com.hosts new file mode 100644 index 000000000..1fcafb230 --- /dev/null +++ b/quickstart/bind9/zones/partition2/example.com.hosts @@ -0,0 +1,10 @@ +$TTL 1h +$ORIGIN example.com2. +@ IN SOA ns1.parent.com2. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +example.com2. IN NS 172.17.42.1. +dskey IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition2/invalid-zone.hosts b/quickstart/bind9/zones/partition2/invalid-zone.hosts new file mode 100644 index 000000000..b4ba68241 --- /dev/null +++ b/quickstart/bind9/zones/partition2/invalid-zone.hosts @@ -0,0 +1,17 @@ +$ttl 38400 +invalid-zone2. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +invalid-zone2. IN NS 172.17.42.1. +invalid-zone2. IN NS not-approved.thing.com. +invalid.child.invalid-zone2. IN NS 172.17.42.1. +dotted.host.invalid-zone2. IN A 1.2.3.4 +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/partition2/list-records.hosts b/quickstart/bind9/zones/partition2/list-records.hosts new file mode 100644 index 000000000..6d3b0ac6b --- /dev/null +++ b/quickstart/bind9/zones/partition2/list-records.hosts @@ -0,0 +1,38 @@ +$ttl 38400 +list-records2. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-records2. IN NS 172.17.42.1. +00-test-list-recordsets-0-A IN A 10.1.1.1 +00-test-list-recordsets-0-A IN A 10.2.2.2 +00-test-list-recordsets-0-CNAME IN CNAME cname1. +00-test-list-recordsets-1-A IN A 10.1.1.1 +00-test-list-recordsets-1-A IN A 10.2.2.2 +00-test-list-recordsets-1-CNAME IN CNAME cname1. +00-test-list-recordsets-2-A IN A 10.1.1.1 +00-test-list-recordsets-2-A IN A 10.2.2.2 +00-test-list-recordsets-2-CNAME IN CNAME cname1. +00-test-list-recordsets-3-A IN A 10.1.1.1 +00-test-list-recordsets-3-A IN A 10.2.2.2 +00-test-list-recordsets-3-CNAME IN CNAME cname1. +00-test-list-recordsets-4-A IN A 10.1.1.1 +00-test-list-recordsets-4-A IN A 10.2.2.2 +00-test-list-recordsets-4-CNAME IN CNAME cname1. +00-test-list-recordsets-5-A IN A 10.1.1.1 +00-test-list-recordsets-5-A IN A 10.2.2.2 +00-test-list-recordsets-5-CNAME IN CNAME cname1. +00-test-list-recordsets-6-A IN A 10.1.1.1 +00-test-list-recordsets-6-A IN A 10.2.2.2 +00-test-list-recordsets-6-CNAME IN CNAME cname1. +00-test-list-recordsets-7-A IN A 10.1.1.1 +00-test-list-recordsets-7-A IN A 10.2.2.2 +00-test-list-recordsets-7-CNAME IN CNAME cname1. +00-test-list-recordsets-8-A IN A 10.1.1.1 +00-test-list-recordsets-8-A IN A 10.2.2.2 +00-test-list-recordsets-8-CNAME IN CNAME cname1. +00-test-list-recordsets-9-A IN A 10.1.1.1 +00-test-list-recordsets-9-A IN A 10.2.2.2 +00-test-list-recordsets-9-CNAME IN CNAME cname1. diff --git a/quickstart/bind9/zones/partition2/list-zones-test-searched-1.hosts b/quickstart/bind9/zones/partition2/list-zones-test-searched-1.hosts new file mode 100644 index 000000000..300315754 --- /dev/null +++ b/quickstart/bind9/zones/partition2/list-zones-test-searched-1.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +list-zones-test-searched-12. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-zones-test-searched-12. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition2/list-zones-test-searched-2.hosts b/quickstart/bind9/zones/partition2/list-zones-test-searched-2.hosts new file mode 100644 index 000000000..475e9770d --- /dev/null +++ b/quickstart/bind9/zones/partition2/list-zones-test-searched-2.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +list-zones-test-searched-22. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-zones-test-searched-22. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition2/list-zones-test-searched-3.hosts b/quickstart/bind9/zones/partition2/list-zones-test-searched-3.hosts new file mode 100644 index 000000000..7539a0099 --- /dev/null +++ b/quickstart/bind9/zones/partition2/list-zones-test-searched-3.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +list-zones-test-searched-32. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-zones-test-searched-32. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition2/list-zones-test-unfiltered-1.hosts b/quickstart/bind9/zones/partition2/list-zones-test-unfiltered-1.hosts new file mode 100644 index 000000000..1da508d1f --- /dev/null +++ b/quickstart/bind9/zones/partition2/list-zones-test-unfiltered-1.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +list-zones-test-unfiltered-12. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-zones-test-unfiltered-12. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition2/list-zones-test-unfiltered-2.hosts b/quickstart/bind9/zones/partition2/list-zones-test-unfiltered-2.hosts new file mode 100644 index 000000000..dc7931fc5 --- /dev/null +++ b/quickstart/bind9/zones/partition2/list-zones-test-unfiltered-2.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +list-zones-test-unfiltered-22. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-zones-test-unfiltered-22. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition2/non.test.shared.hosts b/quickstart/bind9/zones/partition2/non.test.shared.hosts new file mode 100644 index 000000000..591b49fbe --- /dev/null +++ b/quickstart/bind9/zones/partition2/non.test.shared.hosts @@ -0,0 +1,13 @@ +$ttl 38400 +non.test.shared2. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +non.test.shared2. IN NS 172.17.42.1. +@ IN A 1.1.1.1 +delete-test-batch IN A 2.2.2.2 +update-test-batch IN A 3.3.3.3 +delete-test IN A 4.4.4.4 +update-test IN A 5.5.5.5 diff --git a/quickstart/bind9/zones/partition2/not.loaded.hosts b/quickstart/bind9/zones/partition2/not.loaded.hosts new file mode 100644 index 000000000..ffec07633 --- /dev/null +++ b/quickstart/bind9/zones/partition2/not.loaded.hosts @@ -0,0 +1,9 @@ +$ttl 38400 +not.loaded2. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +not.loaded2. IN NS 172.17.42.1. +foo IN A 1.1.1.1 diff --git a/quickstart/bind9/zones/partition2/ok.hosts b/quickstart/bind9/zones/partition2/ok.hosts new file mode 100644 index 000000000..382a2be90 --- /dev/null +++ b/quickstart/bind9/zones/partition2/ok.hosts @@ -0,0 +1,16 @@ +$ttl 38400 +ok2. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +ok2. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 +dotted.a IN A 7.7.7.7 +dottedc.name IN CNAME test.example.com diff --git a/quickstart/bind9/zones/partition2/old-shared.hosts b/quickstart/bind9/zones/partition2/old-shared.hosts new file mode 100644 index 000000000..10fb245f8 --- /dev/null +++ b/quickstart/bind9/zones/partition2/old-shared.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +old-shared2. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +old-shared2. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/partition2/old-vinyldns2.hosts b/quickstart/bind9/zones/partition2/old-vinyldns2.hosts new file mode 100644 index 000000000..25bf67302 --- /dev/null +++ b/quickstart/bind9/zones/partition2/old-vinyldns2.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +old-vinyldns22. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +old-vinyldns22. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/partition2/old-vinyldns3.hosts b/quickstart/bind9/zones/partition2/old-vinyldns3.hosts new file mode 100644 index 000000000..7bc3c4018 --- /dev/null +++ b/quickstart/bind9/zones/partition2/old-vinyldns3.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +old-vinyldns32. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +old-vinyldns32. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/partition2/one-time-shared.hosts b/quickstart/bind9/zones/partition2/one-time-shared.hosts new file mode 100644 index 000000000..b2f69ddf8 --- /dev/null +++ b/quickstart/bind9/zones/partition2/one-time-shared.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +one-time-shared2. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +one-time-shared2. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition2/one-time.hosts b/quickstart/bind9/zones/partition2/one-time.hosts new file mode 100644 index 000000000..25a326d85 --- /dev/null +++ b/quickstart/bind9/zones/partition2/one-time.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +one-time2. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +one-time2. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/partition2/open.hosts b/quickstart/bind9/zones/partition2/open.hosts new file mode 100644 index 000000000..e7225f2a8 --- /dev/null +++ b/quickstart/bind9/zones/partition2/open.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +open2. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +open2. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition2/parent.com.hosts b/quickstart/bind9/zones/partition2/parent.com.hosts new file mode 100644 index 000000000..957a98326 --- /dev/null +++ b/quickstart/bind9/zones/partition2/parent.com.hosts @@ -0,0 +1,15 @@ +$ttl 38400 +$ORIGIN parent.com2. +@ IN SOA ns1.parent.com2. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +parent.com2. IN NS ns1.parent.com2. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +already-exists IN A 6.6.6.6 +ns1 IN A 172.17.42.1 diff --git a/quickstart/bind9/zones/partition2/shared.hosts b/quickstart/bind9/zones/partition2/shared.hosts new file mode 100644 index 000000000..a7ca73f1a --- /dev/null +++ b/quickstart/bind9/zones/partition2/shared.hosts @@ -0,0 +1,16 @@ +$ttl 38400 +shared2. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +shared2. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 +delete-test-batch IN A 2.2.2.2 +update-test-batch IN A 3.3.3.3 diff --git a/quickstart/bind9/zones/partition2/sync-test.hosts b/quickstart/bind9/zones/partition2/sync-test.hosts new file mode 100644 index 000000000..01260c520 --- /dev/null +++ b/quickstart/bind9/zones/partition2/sync-test.hosts @@ -0,0 +1,17 @@ +$ttl 38400 +sync-test2. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +sync-test2. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 +fqdn.sync-test2. IN A 7.7.7.7 +_sip._tcp IN SRV 10 60 5060 foo.sync-test. +existing.dotted IN A 9.9.9.9 diff --git a/quickstart/bind9/zones/partition2/system-test-history.hosts b/quickstart/bind9/zones/partition2/system-test-history.hosts new file mode 100644 index 000000000..1ddb9ee42 --- /dev/null +++ b/quickstart/bind9/zones/partition2/system-test-history.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +system-test-history2. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +system-test-history2. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/partition2/system-test.hosts b/quickstart/bind9/zones/partition2/system-test.hosts new file mode 100644 index 000000000..691894863 --- /dev/null +++ b/quickstart/bind9/zones/partition2/system-test.hosts @@ -0,0 +1,16 @@ +$ttl 38400 +system-test2. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +system-test2. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 +high-value-domain IN A 1.1.1.1 +high-VALUE-domain-UPPER-CASE IN A 1.1.1.1 diff --git a/quickstart/bind9/zones/partition2/vinyldns.hosts b/quickstart/bind9/zones/partition2/vinyldns.hosts new file mode 100644 index 000000000..e934beda3 --- /dev/null +++ b/quickstart/bind9/zones/partition2/vinyldns.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +vinyldns2. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +vinyldns2. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/partition2/zone.requires.review.hosts b/quickstart/bind9/zones/partition2/zone.requires.review.hosts new file mode 100644 index 000000000..90a970f45 --- /dev/null +++ b/quickstart/bind9/zones/partition2/zone.requires.review.hosts @@ -0,0 +1,11 @@ +$ttl 38400 +zone.requires.review2. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +zone.requires.review2. IN NS 172.17.42.1. +@ IN A 1.1.1.1 +delete-test-batch IN A 2.2.2.2 +update-test-batch IN A 3.3.3.3 diff --git a/quickstart/bind9/zones/partition3/0.0.0.1.1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa b/quickstart/bind9/zones/partition3/0.0.0.1.1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa new file mode 100644 index 000000000..f3f7799b6 --- /dev/null +++ b/quickstart/bind9/zones/partition3/0.0.0.1.1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa @@ -0,0 +1,12 @@ +$ttl 38400 +0.0.0.1.3.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa. IN SOA 172.17.42.1. admin.vinyldns.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +0.0.0.1.3.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa. IN NS 172.17.42.1. +4.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR www.vinyldns. +5.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR mail.vinyldns. +0.0.0.0.f.f.f.f.0.0.0.0.0.0.0.0 IN PTR high.value.domain.ip6. +2.0.0.0.f.f.f.f.0.0.0.0.0.0.0.0 IN PTR needs.review.domain.ip6. diff --git a/quickstart/bind9/zones/partition3/1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa b/quickstart/bind9/zones/partition3/1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa new file mode 100644 index 000000000..8e97b0dbc --- /dev/null +++ b/quickstart/bind9/zones/partition3/1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa @@ -0,0 +1,13 @@ +$ttl 38400 +3.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa. IN SOA 172.17.42.1. admin.vinyldns.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +3.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa. IN NS 172.17.42.1. +0.0.0.1 IN NS 172.17.42.1. +4.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR www.vinyldns. +5.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR mail.vinyldns. +0.0.0.0.f.f.f.f.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR high.value.domain.ip6. +2.0.0.0.f.f.f.f.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR needs.review.domain.ip6. diff --git a/quickstart/bind9/zones/partition3/10.10.in-addr.arpa b/quickstart/bind9/zones/partition3/10.10.in-addr.arpa new file mode 100644 index 000000000..34fe12f4f --- /dev/null +++ b/quickstart/bind9/zones/partition3/10.10.in-addr.arpa @@ -0,0 +1,10 @@ +$ttl 38400 +3.10.in-addr.arpa. IN SOA 172.17.42.1. admin.vinyldns.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +3.10.in-addr.arpa. IN NS 172.17.42.1. +24.0 IN PTR www.vinyl. +25.0 IN PTR mail.vinyl. diff --git a/quickstart/bind9/zones/partition3/192^30.2.0.192.in-addr.arpa b/quickstart/bind9/zones/partition3/192^30.2.0.192.in-addr.arpa new file mode 100644 index 000000000..bcda0b5d2 --- /dev/null +++ b/quickstart/bind9/zones/partition3/192^30.2.0.192.in-addr.arpa @@ -0,0 +1,11 @@ +$ttl 38400 +192/30.3.0.192.in-addr.arpa. IN SOA 172.17.42.1. admin.vinyldns.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +192/30.3.0.192.in-addr.arpa. IN NS 172.17.42.1. +192 IN PTR portal.vinyldns. +194 IN PTR mail.vinyldns. +195 IN PTR test.vinyldns. diff --git a/quickstart/bind9/zones/partition3/2.0.192.in-addr.arpa b/quickstart/bind9/zones/partition3/2.0.192.in-addr.arpa new file mode 100644 index 000000000..03cb1e7e6 --- /dev/null +++ b/quickstart/bind9/zones/partition3/2.0.192.in-addr.arpa @@ -0,0 +1,15 @@ +$ttl 38400 +3.0.192.in-addr.arpa. IN SOA 172.17.42.1. admin.vinyldns.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +3.0.192.in-addr.arpa. IN NS 172.17.42.1. +192/30 IN NS 172.17.42.1. +192 IN CNAME 192.192/30.2.0.192.in-addr.arpa. +193 IN CNAME 193.192/30.2.0.192.in-addr.arpa. +194 IN CNAME 194.192/30.2.0.192.in-addr.arpa. +195 IN CNAME 195.192/30.2.0.192.in-addr.arpa. +253 IN PTR high.value.domain.ip4. +255 IN PTR needs.review.domain.ip4 diff --git a/quickstart/bind9/zones/partition3/child.parent.com.hosts b/quickstart/bind9/zones/partition3/child.parent.com.hosts new file mode 100644 index 000000000..5411a8138 --- /dev/null +++ b/quickstart/bind9/zones/partition3/child.parent.com.hosts @@ -0,0 +1,9 @@ +$ttl 38400 +$ORIGIN child.parent.com3. +@ IN SOA ns1.parent.com3. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +@ IN NS ns1.parent.com3. diff --git a/quickstart/bind9/zones/partition3/dskey.example.com.hosts b/quickstart/bind9/zones/partition3/dskey.example.com.hosts new file mode 100644 index 000000000..fd759aa84 --- /dev/null +++ b/quickstart/bind9/zones/partition3/dskey.example.com.hosts @@ -0,0 +1,9 @@ +$TTL 1h +$ORIGIN dskey.example.com3. +@ IN SOA ns1.parent.com3. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +dskey.example.com3. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition3/dummy.hosts b/quickstart/bind9/zones/partition3/dummy.hosts new file mode 100644 index 000000000..a79b6a4f9 --- /dev/null +++ b/quickstart/bind9/zones/partition3/dummy.hosts @@ -0,0 +1,15 @@ +$ttl 38400 +dummy3. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +dummy3. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 +non-approved-delegation IN NS 7.7.7.7 diff --git a/quickstart/bind9/zones/partition3/example.com.hosts b/quickstart/bind9/zones/partition3/example.com.hosts new file mode 100644 index 000000000..6eac59f8d --- /dev/null +++ b/quickstart/bind9/zones/partition3/example.com.hosts @@ -0,0 +1,10 @@ +$TTL 1h +$ORIGIN example.com3. +@ IN SOA ns1.parent.com3. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +example.com3. IN NS 172.17.42.1. +dskey IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition3/invalid-zone.hosts b/quickstart/bind9/zones/partition3/invalid-zone.hosts new file mode 100644 index 000000000..f9063bfc4 --- /dev/null +++ b/quickstart/bind9/zones/partition3/invalid-zone.hosts @@ -0,0 +1,17 @@ +$ttl 38400 +invalid-zone3. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +invalid-zone3. IN NS 172.17.42.1. +invalid-zone3. IN NS not-approved.thing.com. +invalid.child.invalid-zone3. IN NS 172.17.42.1. +dotted.host.invalid-zone3. IN A 1.2.3.4 +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/partition3/list-records.hosts b/quickstart/bind9/zones/partition3/list-records.hosts new file mode 100644 index 000000000..48c26a6be --- /dev/null +++ b/quickstart/bind9/zones/partition3/list-records.hosts @@ -0,0 +1,38 @@ +$ttl 38400 +list-records3. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-records3. IN NS 172.17.42.1. +00-test-list-recordsets-0-A IN A 10.1.1.1 +00-test-list-recordsets-0-A IN A 10.2.2.2 +00-test-list-recordsets-0-CNAME IN CNAME cname1. +00-test-list-recordsets-1-A IN A 10.1.1.1 +00-test-list-recordsets-1-A IN A 10.2.2.2 +00-test-list-recordsets-1-CNAME IN CNAME cname1. +00-test-list-recordsets-2-A IN A 10.1.1.1 +00-test-list-recordsets-2-A IN A 10.2.2.2 +00-test-list-recordsets-2-CNAME IN CNAME cname1. +00-test-list-recordsets-3-A IN A 10.1.1.1 +00-test-list-recordsets-3-A IN A 10.2.2.2 +00-test-list-recordsets-3-CNAME IN CNAME cname1. +00-test-list-recordsets-4-A IN A 10.1.1.1 +00-test-list-recordsets-4-A IN A 10.2.2.2 +00-test-list-recordsets-4-CNAME IN CNAME cname1. +00-test-list-recordsets-5-A IN A 10.1.1.1 +00-test-list-recordsets-5-A IN A 10.2.2.2 +00-test-list-recordsets-5-CNAME IN CNAME cname1. +00-test-list-recordsets-6-A IN A 10.1.1.1 +00-test-list-recordsets-6-A IN A 10.2.2.2 +00-test-list-recordsets-6-CNAME IN CNAME cname1. +00-test-list-recordsets-7-A IN A 10.1.1.1 +00-test-list-recordsets-7-A IN A 10.2.2.2 +00-test-list-recordsets-7-CNAME IN CNAME cname1. +00-test-list-recordsets-8-A IN A 10.1.1.1 +00-test-list-recordsets-8-A IN A 10.2.2.2 +00-test-list-recordsets-8-CNAME IN CNAME cname1. +00-test-list-recordsets-9-A IN A 10.1.1.1 +00-test-list-recordsets-9-A IN A 10.2.2.2 +00-test-list-recordsets-9-CNAME IN CNAME cname1. diff --git a/quickstart/bind9/zones/partition3/list-zones-test-searched-1.hosts b/quickstart/bind9/zones/partition3/list-zones-test-searched-1.hosts new file mode 100644 index 000000000..5b43f9d48 --- /dev/null +++ b/quickstart/bind9/zones/partition3/list-zones-test-searched-1.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +list-zones-test-searched-13. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-zones-test-searched-13. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition3/list-zones-test-searched-2.hosts b/quickstart/bind9/zones/partition3/list-zones-test-searched-2.hosts new file mode 100644 index 000000000..e29044539 --- /dev/null +++ b/quickstart/bind9/zones/partition3/list-zones-test-searched-2.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +list-zones-test-searched-23. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-zones-test-searched-23. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition3/list-zones-test-searched-3.hosts b/quickstart/bind9/zones/partition3/list-zones-test-searched-3.hosts new file mode 100644 index 000000000..1fbd2cd17 --- /dev/null +++ b/quickstart/bind9/zones/partition3/list-zones-test-searched-3.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +list-zones-test-searched-33. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-zones-test-searched-33. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition3/list-zones-test-unfiltered-1.hosts b/quickstart/bind9/zones/partition3/list-zones-test-unfiltered-1.hosts new file mode 100644 index 000000000..d70b6fda2 --- /dev/null +++ b/quickstart/bind9/zones/partition3/list-zones-test-unfiltered-1.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +list-zones-test-unfiltered-13. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-zones-test-unfiltered-13. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition3/list-zones-test-unfiltered-2.hosts b/quickstart/bind9/zones/partition3/list-zones-test-unfiltered-2.hosts new file mode 100644 index 000000000..e3f969a25 --- /dev/null +++ b/quickstart/bind9/zones/partition3/list-zones-test-unfiltered-2.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +list-zones-test-unfiltered-23. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-zones-test-unfiltered-23. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition3/non.test.shared.hosts b/quickstart/bind9/zones/partition3/non.test.shared.hosts new file mode 100644 index 000000000..f71303352 --- /dev/null +++ b/quickstart/bind9/zones/partition3/non.test.shared.hosts @@ -0,0 +1,13 @@ +$ttl 38400 +non.test.shared3. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +non.test.shared3. IN NS 172.17.42.1. +@ IN A 1.1.1.1 +delete-test-batch IN A 2.2.2.2 +update-test-batch IN A 3.3.3.3 +delete-test IN A 4.4.4.4 +update-test IN A 5.5.5.5 diff --git a/quickstart/bind9/zones/partition3/not.loaded.hosts b/quickstart/bind9/zones/partition3/not.loaded.hosts new file mode 100644 index 000000000..cc50178c2 --- /dev/null +++ b/quickstart/bind9/zones/partition3/not.loaded.hosts @@ -0,0 +1,9 @@ +$ttl 38400 +not.loaded3. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +not.loaded3. IN NS 172.17.42.1. +foo IN A 1.1.1.1 diff --git a/quickstart/bind9/zones/partition3/ok.hosts b/quickstart/bind9/zones/partition3/ok.hosts new file mode 100644 index 000000000..9690ef8bf --- /dev/null +++ b/quickstart/bind9/zones/partition3/ok.hosts @@ -0,0 +1,16 @@ +$ttl 38400 +ok3. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +ok3. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 +dotted.a IN A 7.7.7.7 +dottedc.name IN CNAME test.example.com diff --git a/quickstart/bind9/zones/partition3/old-shared.hosts b/quickstart/bind9/zones/partition3/old-shared.hosts new file mode 100644 index 000000000..e30a3874f --- /dev/null +++ b/quickstart/bind9/zones/partition3/old-shared.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +old-shared3. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +old-shared3. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/partition3/old-vinyldns2.hosts b/quickstart/bind9/zones/partition3/old-vinyldns2.hosts new file mode 100644 index 000000000..90b8b34d3 --- /dev/null +++ b/quickstart/bind9/zones/partition3/old-vinyldns2.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +old-vinyldns23. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +old-vinyldns23. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/partition3/old-vinyldns3.hosts b/quickstart/bind9/zones/partition3/old-vinyldns3.hosts new file mode 100644 index 000000000..04844dcf8 --- /dev/null +++ b/quickstart/bind9/zones/partition3/old-vinyldns3.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +old-vinyldns33. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +old-vinyldns33. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/partition3/one-time-shared.hosts b/quickstart/bind9/zones/partition3/one-time-shared.hosts new file mode 100644 index 000000000..6bd47a8b8 --- /dev/null +++ b/quickstart/bind9/zones/partition3/one-time-shared.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +one-time-shared3. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +one-time-shared3. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition3/one-time.hosts b/quickstart/bind9/zones/partition3/one-time.hosts new file mode 100644 index 000000000..05b7506e3 --- /dev/null +++ b/quickstart/bind9/zones/partition3/one-time.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +one-time3. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +one-time3. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/partition3/open.hosts b/quickstart/bind9/zones/partition3/open.hosts new file mode 100644 index 000000000..3ca4ab7c6 --- /dev/null +++ b/quickstart/bind9/zones/partition3/open.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +open3. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +open3. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition3/parent.com.hosts b/quickstart/bind9/zones/partition3/parent.com.hosts new file mode 100644 index 000000000..33b348661 --- /dev/null +++ b/quickstart/bind9/zones/partition3/parent.com.hosts @@ -0,0 +1,15 @@ +$ttl 38400 +$ORIGIN parent.com3. +@ IN SOA ns1.parent.com3. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +parent.com3. IN NS ns1.parent.com3. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +already-exists IN A 6.6.6.6 +ns1 IN A 172.17.42.1 diff --git a/quickstart/bind9/zones/partition3/shared.hosts b/quickstart/bind9/zones/partition3/shared.hosts new file mode 100644 index 000000000..38610bdc8 --- /dev/null +++ b/quickstart/bind9/zones/partition3/shared.hosts @@ -0,0 +1,16 @@ +$ttl 38400 +shared3. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +shared3. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 +delete-test-batch IN A 2.2.2.2 +update-test-batch IN A 3.3.3.3 diff --git a/quickstart/bind9/zones/partition3/sync-test.hosts b/quickstart/bind9/zones/partition3/sync-test.hosts new file mode 100644 index 000000000..988d2d0f0 --- /dev/null +++ b/quickstart/bind9/zones/partition3/sync-test.hosts @@ -0,0 +1,17 @@ +$ttl 38400 +sync-test3. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +sync-test3. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 +fqdn.sync-test3. IN A 7.7.7.7 +_sip._tcp IN SRV 10 60 5060 foo.sync-test. +existing.dotted IN A 9.9.9.9 diff --git a/quickstart/bind9/zones/partition3/system-test-history.hosts b/quickstart/bind9/zones/partition3/system-test-history.hosts new file mode 100644 index 000000000..dd1357713 --- /dev/null +++ b/quickstart/bind9/zones/partition3/system-test-history.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +system-test-history3. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +system-test-history3. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/partition3/system-test.hosts b/quickstart/bind9/zones/partition3/system-test.hosts new file mode 100644 index 000000000..eee3f457e --- /dev/null +++ b/quickstart/bind9/zones/partition3/system-test.hosts @@ -0,0 +1,16 @@ +$ttl 38400 +system-test3. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +system-test3. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 +high-value-domain IN A 1.1.1.1 +high-VALUE-domain-UPPER-CASE IN A 1.1.1.1 diff --git a/quickstart/bind9/zones/partition3/vinyldns.hosts b/quickstart/bind9/zones/partition3/vinyldns.hosts new file mode 100644 index 000000000..a890cdb81 --- /dev/null +++ b/quickstart/bind9/zones/partition3/vinyldns.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +vinyldns3. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +vinyldns3. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/partition3/zone.requires.review.hosts b/quickstart/bind9/zones/partition3/zone.requires.review.hosts new file mode 100644 index 000000000..28fa8cd08 --- /dev/null +++ b/quickstart/bind9/zones/partition3/zone.requires.review.hosts @@ -0,0 +1,11 @@ +$ttl 38400 +zone.requires.review3. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +zone.requires.review3. IN NS 172.17.42.1. +@ IN A 1.1.1.1 +delete-test-batch IN A 2.2.2.2 +update-test-batch IN A 3.3.3.3 diff --git a/quickstart/bind9/zones/partition4/0.0.0.1.1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa b/quickstart/bind9/zones/partition4/0.0.0.1.1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa new file mode 100644 index 000000000..dc4531ba7 --- /dev/null +++ b/quickstart/bind9/zones/partition4/0.0.0.1.1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa @@ -0,0 +1,12 @@ +$ttl 38400 +0.0.0.1.4.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa. IN SOA 172.17.42.1. admin.vinyldns.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +0.0.0.1.4.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa. IN NS 172.17.42.1. +4.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR www.vinyldns. +5.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR mail.vinyldns. +0.0.0.0.f.f.f.f.0.0.0.0.0.0.0.0 IN PTR high.value.domain.ip6. +2.0.0.0.f.f.f.f.0.0.0.0.0.0.0.0 IN PTR needs.review.domain.ip6. diff --git a/quickstart/bind9/zones/partition4/1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa b/quickstart/bind9/zones/partition4/1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa new file mode 100644 index 000000000..bd78df2a1 --- /dev/null +++ b/quickstart/bind9/zones/partition4/1.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa @@ -0,0 +1,13 @@ +$ttl 38400 +4.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa. IN SOA 172.17.42.1. admin.vinyldns.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +4.9.e.f.c.c.7.2.9.6.d.f.ip6.arpa. IN NS 172.17.42.1. +0.0.0.1 IN NS 172.17.42.1. +4.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR www.vinyldns. +5.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR mail.vinyldns. +0.0.0.0.f.f.f.f.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR high.value.domain.ip6. +2.0.0.0.f.f.f.f.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR needs.review.domain.ip6. diff --git a/quickstart/bind9/zones/partition4/10.10.in-addr.arpa b/quickstart/bind9/zones/partition4/10.10.in-addr.arpa new file mode 100644 index 000000000..c25fe5314 --- /dev/null +++ b/quickstart/bind9/zones/partition4/10.10.in-addr.arpa @@ -0,0 +1,10 @@ +$ttl 38400 +4.10.in-addr.arpa. IN SOA 172.17.42.1. admin.vinyldns.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +4.10.in-addr.arpa. IN NS 172.17.42.1. +24.0 IN PTR www.vinyl. +25.0 IN PTR mail.vinyl. diff --git a/quickstart/bind9/zones/partition4/192^30.2.0.192.in-addr.arpa b/quickstart/bind9/zones/partition4/192^30.2.0.192.in-addr.arpa new file mode 100644 index 000000000..cd0622f26 --- /dev/null +++ b/quickstart/bind9/zones/partition4/192^30.2.0.192.in-addr.arpa @@ -0,0 +1,11 @@ +$ttl 38400 +192/30.4.0.192.in-addr.arpa. IN SOA 172.17.42.1. admin.vinyldns.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +192/30.4.0.192.in-addr.arpa. IN NS 172.17.42.1. +192 IN PTR portal.vinyldns. +194 IN PTR mail.vinyldns. +195 IN PTR test.vinyldns. diff --git a/quickstart/bind9/zones/partition4/2.0.192.in-addr.arpa b/quickstart/bind9/zones/partition4/2.0.192.in-addr.arpa new file mode 100644 index 000000000..3763763f2 --- /dev/null +++ b/quickstart/bind9/zones/partition4/2.0.192.in-addr.arpa @@ -0,0 +1,15 @@ +$ttl 38400 +4.0.192.in-addr.arpa. IN SOA 172.17.42.1. admin.vinyldns.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +4.0.192.in-addr.arpa. IN NS 172.17.42.1. +192/30 IN NS 172.17.42.1. +192 IN CNAME 192.192/30.2.0.192.in-addr.arpa. +193 IN CNAME 193.192/30.2.0.192.in-addr.arpa. +194 IN CNAME 194.192/30.2.0.192.in-addr.arpa. +195 IN CNAME 195.192/30.2.0.192.in-addr.arpa. +253 IN PTR high.value.domain.ip4. +255 IN PTR needs.review.domain.ip4 diff --git a/quickstart/bind9/zones/partition4/child.parent.com.hosts b/quickstart/bind9/zones/partition4/child.parent.com.hosts new file mode 100644 index 000000000..510870422 --- /dev/null +++ b/quickstart/bind9/zones/partition4/child.parent.com.hosts @@ -0,0 +1,9 @@ +$ttl 38400 +$ORIGIN child.parent.com4. +@ IN SOA ns1.parent.com4. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +@ IN NS ns1.parent.com4. diff --git a/quickstart/bind9/zones/partition4/dskey.example.com.hosts b/quickstart/bind9/zones/partition4/dskey.example.com.hosts new file mode 100644 index 000000000..dc31f190f --- /dev/null +++ b/quickstart/bind9/zones/partition4/dskey.example.com.hosts @@ -0,0 +1,9 @@ +$TTL 1h +$ORIGIN dskey.example.com4. +@ IN SOA ns1.parent.com4. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +dskey.example.com4. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition4/dummy.hosts b/quickstart/bind9/zones/partition4/dummy.hosts new file mode 100644 index 000000000..518db4e05 --- /dev/null +++ b/quickstart/bind9/zones/partition4/dummy.hosts @@ -0,0 +1,15 @@ +$ttl 38400 +dummy4. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +dummy4. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 +non-approved-delegation IN NS 7.7.7.7 diff --git a/quickstart/bind9/zones/partition4/example.com.hosts b/quickstart/bind9/zones/partition4/example.com.hosts new file mode 100644 index 000000000..357c435dd --- /dev/null +++ b/quickstart/bind9/zones/partition4/example.com.hosts @@ -0,0 +1,10 @@ +$TTL 1h +$ORIGIN example.com4. +@ IN SOA ns1.parent.com4. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +example.com4. IN NS 172.17.42.1. +dskey IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition4/invalid-zone.hosts b/quickstart/bind9/zones/partition4/invalid-zone.hosts new file mode 100644 index 000000000..67ac92d7e --- /dev/null +++ b/quickstart/bind9/zones/partition4/invalid-zone.hosts @@ -0,0 +1,17 @@ +$ttl 38400 +invalid-zone4. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +invalid-zone4. IN NS 172.17.42.1. +invalid-zone4. IN NS not-approved.thing.com. +invalid.child.invalid-zone4. IN NS 172.17.42.1. +dotted.host.invalid-zone4. IN A 1.2.3.4 +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/partition4/list-records.hosts b/quickstart/bind9/zones/partition4/list-records.hosts new file mode 100644 index 000000000..9e2b58fd4 --- /dev/null +++ b/quickstart/bind9/zones/partition4/list-records.hosts @@ -0,0 +1,38 @@ +$ttl 38400 +list-records4. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-records4. IN NS 172.17.42.1. +00-test-list-recordsets-0-A IN A 10.1.1.1 +00-test-list-recordsets-0-A IN A 10.2.2.2 +00-test-list-recordsets-0-CNAME IN CNAME cname1. +00-test-list-recordsets-1-A IN A 10.1.1.1 +00-test-list-recordsets-1-A IN A 10.2.2.2 +00-test-list-recordsets-1-CNAME IN CNAME cname1. +00-test-list-recordsets-2-A IN A 10.1.1.1 +00-test-list-recordsets-2-A IN A 10.2.2.2 +00-test-list-recordsets-2-CNAME IN CNAME cname1. +00-test-list-recordsets-3-A IN A 10.1.1.1 +00-test-list-recordsets-3-A IN A 10.2.2.2 +00-test-list-recordsets-3-CNAME IN CNAME cname1. +00-test-list-recordsets-4-A IN A 10.1.1.1 +00-test-list-recordsets-4-A IN A 10.2.2.2 +00-test-list-recordsets-4-CNAME IN CNAME cname1. +00-test-list-recordsets-5-A IN A 10.1.1.1 +00-test-list-recordsets-5-A IN A 10.2.2.2 +00-test-list-recordsets-5-CNAME IN CNAME cname1. +00-test-list-recordsets-6-A IN A 10.1.1.1 +00-test-list-recordsets-6-A IN A 10.2.2.2 +00-test-list-recordsets-6-CNAME IN CNAME cname1. +00-test-list-recordsets-7-A IN A 10.1.1.1 +00-test-list-recordsets-7-A IN A 10.2.2.2 +00-test-list-recordsets-7-CNAME IN CNAME cname1. +00-test-list-recordsets-8-A IN A 10.1.1.1 +00-test-list-recordsets-8-A IN A 10.2.2.2 +00-test-list-recordsets-8-CNAME IN CNAME cname1. +00-test-list-recordsets-9-A IN A 10.1.1.1 +00-test-list-recordsets-9-A IN A 10.2.2.2 +00-test-list-recordsets-9-CNAME IN CNAME cname1. diff --git a/quickstart/bind9/zones/partition4/list-zones-test-searched-1.hosts b/quickstart/bind9/zones/partition4/list-zones-test-searched-1.hosts new file mode 100644 index 000000000..08f2def7b --- /dev/null +++ b/quickstart/bind9/zones/partition4/list-zones-test-searched-1.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +list-zones-test-searched-14. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-zones-test-searched-14. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition4/list-zones-test-searched-2.hosts b/quickstart/bind9/zones/partition4/list-zones-test-searched-2.hosts new file mode 100644 index 000000000..eac40d747 --- /dev/null +++ b/quickstart/bind9/zones/partition4/list-zones-test-searched-2.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +list-zones-test-searched-24. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-zones-test-searched-24. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition4/list-zones-test-searched-3.hosts b/quickstart/bind9/zones/partition4/list-zones-test-searched-3.hosts new file mode 100644 index 000000000..418d82843 --- /dev/null +++ b/quickstart/bind9/zones/partition4/list-zones-test-searched-3.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +list-zones-test-searched-34. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-zones-test-searched-34. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition4/list-zones-test-unfiltered-1.hosts b/quickstart/bind9/zones/partition4/list-zones-test-unfiltered-1.hosts new file mode 100644 index 000000000..4b68e3b88 --- /dev/null +++ b/quickstart/bind9/zones/partition4/list-zones-test-unfiltered-1.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +list-zones-test-unfiltered-14. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-zones-test-unfiltered-14. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition4/list-zones-test-unfiltered-2.hosts b/quickstart/bind9/zones/partition4/list-zones-test-unfiltered-2.hosts new file mode 100644 index 000000000..3f93f6183 --- /dev/null +++ b/quickstart/bind9/zones/partition4/list-zones-test-unfiltered-2.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +list-zones-test-unfiltered-24. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +list-zones-test-unfiltered-24. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition4/non.test.shared.hosts b/quickstart/bind9/zones/partition4/non.test.shared.hosts new file mode 100644 index 000000000..180a85f22 --- /dev/null +++ b/quickstart/bind9/zones/partition4/non.test.shared.hosts @@ -0,0 +1,13 @@ +$ttl 38400 +non.test.shared4. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +non.test.shared4. IN NS 172.17.42.1. +@ IN A 1.1.1.1 +delete-test-batch IN A 2.2.2.2 +update-test-batch IN A 3.3.3.3 +delete-test IN A 4.4.4.4 +update-test IN A 5.5.5.5 diff --git a/quickstart/bind9/zones/partition4/not.loaded.hosts b/quickstart/bind9/zones/partition4/not.loaded.hosts new file mode 100644 index 000000000..510738a33 --- /dev/null +++ b/quickstart/bind9/zones/partition4/not.loaded.hosts @@ -0,0 +1,9 @@ +$ttl 38400 +not.loaded4. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +not.loaded4. IN NS 172.17.42.1. +foo IN A 1.1.1.1 diff --git a/quickstart/bind9/zones/partition4/ok.hosts b/quickstart/bind9/zones/partition4/ok.hosts new file mode 100644 index 000000000..ff6b2e917 --- /dev/null +++ b/quickstart/bind9/zones/partition4/ok.hosts @@ -0,0 +1,16 @@ +$ttl 38400 +ok4. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +ok4. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 +dotted.a IN A 7.7.7.7 +dottedc.name IN CNAME test.example.com diff --git a/quickstart/bind9/zones/partition4/old-shared.hosts b/quickstart/bind9/zones/partition4/old-shared.hosts new file mode 100644 index 000000000..84a666607 --- /dev/null +++ b/quickstart/bind9/zones/partition4/old-shared.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +old-shared4. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +old-shared4. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/partition4/old-vinyldns2.hosts b/quickstart/bind9/zones/partition4/old-vinyldns2.hosts new file mode 100644 index 000000000..05ae0ff9b --- /dev/null +++ b/quickstart/bind9/zones/partition4/old-vinyldns2.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +old-vinyldns24. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +old-vinyldns24. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/partition4/old-vinyldns3.hosts b/quickstart/bind9/zones/partition4/old-vinyldns3.hosts new file mode 100644 index 000000000..633881d7d --- /dev/null +++ b/quickstart/bind9/zones/partition4/old-vinyldns3.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +old-vinyldns34. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +old-vinyldns34. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/partition4/one-time-shared.hosts b/quickstart/bind9/zones/partition4/one-time-shared.hosts new file mode 100644 index 000000000..156cee37a --- /dev/null +++ b/quickstart/bind9/zones/partition4/one-time-shared.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +one-time-shared4. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +one-time-shared4. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition4/one-time.hosts b/quickstart/bind9/zones/partition4/one-time.hosts new file mode 100644 index 000000000..e62427e5a --- /dev/null +++ b/quickstart/bind9/zones/partition4/one-time.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +one-time4. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +one-time4. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/partition4/open.hosts b/quickstart/bind9/zones/partition4/open.hosts new file mode 100644 index 000000000..7870b2dd4 --- /dev/null +++ b/quickstart/bind9/zones/partition4/open.hosts @@ -0,0 +1,8 @@ +$ttl 38400 +open4. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +open4. IN NS 172.17.42.1. diff --git a/quickstart/bind9/zones/partition4/parent.com.hosts b/quickstart/bind9/zones/partition4/parent.com.hosts new file mode 100644 index 000000000..2d47b276a --- /dev/null +++ b/quickstart/bind9/zones/partition4/parent.com.hosts @@ -0,0 +1,15 @@ +$ttl 38400 +$ORIGIN parent.com4. +@ IN SOA ns1.parent.com4. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +parent.com4. IN NS ns1.parent.com4. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +already-exists IN A 6.6.6.6 +ns1 IN A 172.17.42.1 diff --git a/quickstart/bind9/zones/partition4/shared.hosts b/quickstart/bind9/zones/partition4/shared.hosts new file mode 100644 index 000000000..c4b9a4c8f --- /dev/null +++ b/quickstart/bind9/zones/partition4/shared.hosts @@ -0,0 +1,16 @@ +$ttl 38400 +shared4. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +shared4. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 +delete-test-batch IN A 2.2.2.2 +update-test-batch IN A 3.3.3.3 diff --git a/quickstart/bind9/zones/partition4/sync-test.hosts b/quickstart/bind9/zones/partition4/sync-test.hosts new file mode 100644 index 000000000..a014733fe --- /dev/null +++ b/quickstart/bind9/zones/partition4/sync-test.hosts @@ -0,0 +1,17 @@ +$ttl 38400 +sync-test4. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +sync-test4. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 +fqdn.sync-test4. IN A 7.7.7.7 +_sip._tcp IN SRV 10 60 5060 foo.sync-test. +existing.dotted IN A 9.9.9.9 diff --git a/quickstart/bind9/zones/partition4/system-test-history.hosts b/quickstart/bind9/zones/partition4/system-test-history.hosts new file mode 100644 index 000000000..d72deaf42 --- /dev/null +++ b/quickstart/bind9/zones/partition4/system-test-history.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +system-test-history4. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +system-test-history4. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/partition4/system-test.hosts b/quickstart/bind9/zones/partition4/system-test.hosts new file mode 100644 index 000000000..877aa936b --- /dev/null +++ b/quickstart/bind9/zones/partition4/system-test.hosts @@ -0,0 +1,16 @@ +$ttl 38400 +system-test4. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +system-test4. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 +high-value-domain IN A 1.1.1.1 +high-VALUE-domain-UPPER-CASE IN A 1.1.1.1 diff --git a/quickstart/bind9/zones/partition4/vinyldns.hosts b/quickstart/bind9/zones/partition4/vinyldns.hosts new file mode 100644 index 000000000..66d785b41 --- /dev/null +++ b/quickstart/bind9/zones/partition4/vinyldns.hosts @@ -0,0 +1,14 @@ +$ttl 38400 +vinyldns4. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +vinyldns4. IN NS 172.17.42.1. +jenkins IN A 10.1.1.1 +foo IN A 2.2.2.2 +test IN A 3.3.3.3 +test IN A 4.4.4.4 +@ IN A 5.5.5.5 +already-exists IN A 6.6.6.6 diff --git a/quickstart/bind9/zones/partition4/zone.requires.review.hosts b/quickstart/bind9/zones/partition4/zone.requires.review.hosts new file mode 100644 index 000000000..4879ca584 --- /dev/null +++ b/quickstart/bind9/zones/partition4/zone.requires.review.hosts @@ -0,0 +1,11 @@ +$ttl 38400 +zone.requires.review4. IN SOA 172.17.42.1. admin.test.com. ( + 1439234395 + 10800 + 3600 + 604800 + 38400 ) +zone.requires.review4. IN NS 172.17.42.1. +@ IN A 1.1.1.1 +delete-test-batch IN A 2.2.2.2 +update-test-batch IN A 3.3.3.3 diff --git a/quickstart/docker-compose.yml b/quickstart/docker-compose.yml new file mode 100644 index 000000000..8b0b9acbe --- /dev/null +++ b/quickstart/docker-compose.yml @@ -0,0 +1,75 @@ +version: "3.8" + +services: + + # LDAP container hosting example users + ldap: + container_name: "vinyldns-ldap" + image: vinyldns/build:openldap + ports: + - "19004:19004" + + # Integration image hosting r53, sns, sqs, bind, and mysql + integration: + container_name: "vinyldns-api-integration" + hostname: "vinyldns-integration" + image: "vinyldns/build:base-test-integration-${VINYLDNS_IMAGE_VERSION}" + build: + context: ../ + dockerfile: test/api/integration/Dockerfile + args: + VINYLDNS_BASE_VERSION: "${VINYLDNS_BASE_VERSION}" + environment: + RUN_SERVICES: "deps-only tail-logs" + LOCALSTACK_EXT_HOSTNAME: "${LOCALSTACK_EXT_HOSTNAME:-vinyldns-integration}" + env_file: + .env + ports: + - "19001-19003:19001-19003/tcp" + - "19001:19001/udp" + + # The VinylDNS API + api: + container_name: "vinyldns-api" + oom_kill_disable: true + image: "vinyldns/api:${VINYLDNS_IMAGE_VERSION}" + build: + context: ../ + dockerfile: build/docker/api/Dockerfile + args: + VINYLDNS_VERSION: "${VINYLDNS_IMAGE_VERSION}" + DOCKER_FILE_PATH: "build/docker/api" + volumes: + - ../build/docker/api/application.conf:/opt/vinyldns/conf/application.conf + env_file: + .env + ports: + - "9000:9000" + depends_on: + - integration + + # The VinylDNS portal + portal: + container_name: "vinyldns-portal" + oom_kill_disable: true + image: "vinyldns/portal:${VINYLDNS_IMAGE_VERSION}" + build: + context: ../ + dockerfile: build/docker/portal/Dockerfile + args: + DOCKER_FILE_PATH: "build/docker/portal" + VINYLDNS_VERSION: "${VINYLDNS_IMAGE_VERSION}" + env_file: + .env + ports: + - "${PORTAL_PORT}:${PORTAL_PORT}" + volumes: + - ../build/docker/portal/application.conf:/opt/vinyldns/conf/application.conf + depends_on: + - api + - ldap + +# Custom network so that we don't interfere with the host system +networks: + default: + name: "vinyldns_net" diff --git a/quickstart/quickstart-vinyldns.sh b/quickstart/quickstart-vinyldns.sh new file mode 100755 index 000000000..3dc5318cf --- /dev/null +++ b/quickstart/quickstart-vinyldns.sh @@ -0,0 +1,197 @@ +#!/usr/bin/env bash +##################################################################################################### +# Starts up the api, portal, and dependent services via +# docker-compose. The api will be available on localhost:9000 and the +# portal will be on localhost:9001 +# +# Relevant overrides can be found in .env +##################################################################################################### +set -eo pipefail + +DIR=$( + cd "$(dirname "$0")" || exit + pwd -P +) +source "${DIR}/../utils/includes/terminal_colors.sh" + +function usage() { + echo -e "usage: quickstart-vinyldns.sh [OPTIONS]" + echo -e "Starts up a local VinylDNS installation using Docker Compose" + echo + echo -e "options:" + echo -e "\t-a, --api-only do not start up the VinylDNS Portal" + echo -e "\t-b, --build force a rebuild of the Docker images with the local code" + echo -e "\t-c, --clean stops all VinylDNS containers and exits" + echo -e "\t-d, --deps-only only start up the dependencies, not the API or Portal" + echo -e "\t-r, --reset stops any the running containers before starting new containers" + echo -e "\t-s, --service specify the service to run" + echo -e "\t-t, --timeout the time to wait (in seconds) for the Portal and API to start (default: 60)" + echo -e "\t-u, --update remove the local quickstart images to force a re-pull from Docker Hub" + echo -e "\t-v, --version-tag specify Docker image tag version (default: latest)" + echo + echo -e "\t-h, --help show this help" +} + +function wait_for_url() { + echo -n "Waiting for ${F_BLUE}$1${F_RESET} at ${URL} .." + RETRY="$TIMEOUT" + while [ "$RETRY" -ge 0 ]; do + echo -n "." + if curl -I -s "${URL}" -o /dev/null -w "%{http_code}" &>/dev/null || false; then + echo "${F_GREEN}OK${F_RESET}" + break + else + ((RETRY -= 1)) + sleep 1 + if [[ $RETRY -eq 1 ]]; then + echo "${F_RED}FAILED${F_RESET}" + echo "${F_RED}Timeout waiting for ${F_BLUE}$1${F_RED} to be ready${F_RESET}" + exit 1 + fi + fi + done +} + +function is_running() { + if (docker ps --format "{{.Image}}" | grep -q "$1"); then + return 0 + fi + return 1 +} + +function wait_for_api() { + if is_running "vinyldns/api"; then + URL="$VINYLDNS_API_URL" + wait_for_url "VinylDNS API" + fi +} + +function wait_for_portal() { + if is_running "vinyldns/portal"; then + URL="$VINYLDNS_PORTAL_URL" + wait_for_url "VinylDNS Portal" + fi +} + +# Source customizable env files ('-a' causes all variables to be exported) +set -a +source "${DIR}/.env" +set +a + +# The version of VinylDNS docker image to run +export VINYLDNS_VERSION=latest +# The base/starting version of VinylDNS docker build image to use (vinyldns/build:) +export VINYLDNS_BASE_VERSION=latest +# The version of the images to build +export VINYLDNS_IMAGE_VERSION=${VINYLDNS_VERSION} + +# Defaults +TIMEOUT=60 +DOCKER_COMPOSE_CONFIG="${DIR}/docker-compose.yml" +SERVICE="" +BUILD="" +RESET_DOCKER=0 +UPDATE=0 +CLEAN=0 +while [[ $# -gt 0 ]]; do + case "$1" in + -t | --timeout) + TIMEOUT="$2" + shift + shift + ;; + -d | --deps-only) + export LOCALSTACK_EXT_HOSTNAME="localhost" + SERVICE="integration ldap" + shift + ;; + -a | --api-only) + SERVICE="api" + shift + ;; + -c | --clean) + CLEAN=1 + shift + ;; + -s | --service) + SERVICE="$2" + shift + shift + ;; + -u | --update) + UPDATE=1 + shift + ;; + -b | --build) + BUILD="--build" + shift + ;; + -r | --reset) + RESET_DOCKER=1 + shift + ;; + -v | --version-tag) + export VINYLDNS_VERSION=$2 + export VINYLDNS_BASE_VERSION=${VINYLDNS_VERSION} + export VINYLDNS_IMAGE_VERSION=${VINYLDNS_VERSION} + shift + shift + ;; + *) + usage + exit + ;; + esac +done + +if [[ $RESET_DOCKER -eq 1 ]] || [[ $CLEAN -eq 1 ]]; then + "${DIR}/../utils/clean-vinyldns-containers.sh" + if [[ $CLEAN -eq 1 ]]; then + echo "${F_GREEN}Clean up completed!${F_RESET}" + exit 0 + fi +fi + +# Update images if requested +if [[ $UPDATE -eq 1 ]]; then + echo "${F_YELLOW}Removing any running VinylDNS docker containers tagged ${F_RESET}'${VINYLDNS_IMAGE_VERSION}'${F_YELLOW}...${F_RESET}" + "${DIR}/../utils/clean-vinyldns-containers.sh" &> /dev/null || true + + echo "${F_YELLOW}Removing any local VinylDNS Docker images tagged ${F_RESET}'${VINYLDNS_IMAGE_VERSION}'${F_YELLOW}...${F_RESET}" + docker images -a |grep vinyldns | grep "${VINYLDNS_IMAGE_VERSION}" | awk '{print $3}' | xargs docker rmi -f &> /dev/null || true + echo "${F_GREEN}Successfully removed all local VinylDNS Docker images and running containers tagged ${F_RESET}'${VINYLDNS_IMAGE_VERSION}'${F_YELLOW}...${F_RESET}" + echo "${F_LRED}You may need to re-run with the '--build' flag...${F_RESET}" +fi + + +if [ -n "${BUILD}" ] || [ -n "$(docker images vinyldns/portal:local-dev --format '{{.Repository}}:{{.Tag}}')" ]; then + VINYLDNS_IMAGE_VERSION="local-dev" + export VINYLDNS_VERSION=${VINYLDNS_IMAGE_VERSION} +fi + +if [ -n "${BUILD}" ]; then + echo "Building containers and starting VinylDNS (${VINYLDNS_IMAGE_VERSION}) in the background..." +else + echo "Starting VinylDNS (${VINYLDNS_IMAGE_VERSION}) the background..." +fi +docker-compose -f "${DOCKER_COMPOSE_CONFIG}" up ${BUILD} -d ${SERVICE} || ( + echo -e "${F_RED}Sorry, there was an error starting VinylDNS :-(\nTry resetting any existing containers with:\n\t${F_RESET}'$0 --reset'"; \ + exit 1; \ +) + +if is_running "vinyldns/portal" || is_running "vinyldns/api"; then + echo + wait_for_api + wait_for_portal + echo +fi + +if is_running "vinyldns/portal"; then + echo "${F_GREEN}VinylDNS started! You can connect to the portal via ${F_RESET}${VINYLDNS_PORTAL_URL}" +elif is_running "vinyldns/api"; then + echo "${F_GREEN}VinylDNS API started! You can connect to the API via ${F_RESET}${VINYLDNS_API_URL}" +else + echo "${F_GREEN}VinylDNS dependencies started!${F_RESET}" +fi +echo "${F_GREEN}To clean up the running containers:${F_RESET}" +echo " $0 --clean" diff --git a/test/README.md b/test/README.md new file mode 100644 index 000000000..922776874 --- /dev/null +++ b/test/README.md @@ -0,0 +1,20 @@ +# Test + +This folder contains test containers for running integration and functional tests. + +| Path |Description | +| --- | --- | +|`api/functional` | A Docker container for running functional tests. Use the `Makefile` to build and run.
You can use `WITH_ARGS` to pass [arguments to `Pytest`](https://docs.pytest.org/en/6.2.x/usage.html#specifying-tests-selecting-tests).
Ex: `make run WITH_ARGS="-k test_verify_production"`

The tests are located in `modules/api/test/functional`| +|`api/integration` | A Docker container for running integration tests. Use the `Makefile` to build and run.
You can use `WITH_ARGS` to pass the command you would like to execute in the context of this container.
Ex: `make run WITH_ARGS="sbt ';validate'"`

This does not run any tests by default, but is used by other scripts to run the integration tests. (e.g., `build/verify.sh`)| +|`portal/functional` | A Docker container for running functional tests. Use the `Makefile` to build and run.

The tests are located in `modules/portal/test`| + +## Execution + +The functional tests can be run by using `make` as described in the table above. For other usages, check out +the `build/` directory. Specifically: + +| Path |Description | +| --- | --- | +| `build/func-test-api.sh` | Runs the functional tests for the API| +| `build/func-test-portal.sh` | Runs the functional tests for the Portal| +| `build/verify.sh` | Runs the unit and integration tests for everything| diff --git a/test/api/functional/Dockerfile b/test/api/functional/Dockerfile new file mode 100644 index 000000000..c9ab86297 --- /dev/null +++ b/test/api/functional/Dockerfile @@ -0,0 +1,30 @@ +# Build VinylDNS API if the JAR doesn't already exist +FROM vinyldns/build:base-build as base-build +ARG DOCKERFILE_PATH="test/api/functional" +COPY "${DOCKERFILE_PATH}/application.conf" /opt/vinyldns/conf/ +COPY . /build/ +WORKDIR /build + +## Run the build if we don't already have a vinyldns-api.jar +RUN if [ -f artifacts/vinyldns-api.jar ]; then cp artifacts/vinyldns-api.jar /opt/vinyldns; fi && \ + if [ ! -f /opt/vinyldns/vinyldns-api.jar ]; then \ + env SBT_OPTS="-Xmx2G -Xms512M -Xss2M -XX:MaxMetaspaceSize=2G" \ + sbt -Dbuild.scalafmtOnCompile=false -Dbuild.lintOnCompile=fase ";project api;coverageOff;assembly" \ + && cp artifacts/vinyldns-api.jar /opt/vinyldns/; \ + fi + +# Build the testing image, copying data from `vinyldns-api` +FROM vinyldns/build:base-test +SHELL ["/bin/bash","-c"] +ARG DOCKERFILE_PATH +COPY --from=base-build /opt/vinyldns /opt/vinyldns + +# Local bind server files +COPY quickstart/bind9/etc/named.conf.* /etc/bind/ +COPY quickstart/bind9/zones/ /var/bind/ +RUN named-checkconf + +# Copy over the functional tests +COPY modules/api/src/test/functional /functional_test + +ENTRYPOINT ["/bin/bash", "-c", "/initialize.sh bind localstack vinyldns-api mysql && /functional_test/run.sh \"$@\""] diff --git a/test/api/functional/Makefile b/test/api/functional/Makefile new file mode 100644 index 000000000..b380ac9d2 --- /dev/null +++ b/test/api/functional/Makefile @@ -0,0 +1,59 @@ +SHELL=bash +IMAGE_NAME=vinyldns-api-test +ROOT_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) +RELATIVE_ROOT_DIR:=$(shell realpath --relative-to=../../.. $(ROOT_DIR)) + +# Check that the required version of make is being used +REQ_MAKE_VER:=3.82 +ifneq ($(REQ_MAKE_VER),$(firstword $(sort $(MAKE_VERSION) $(REQ_MAKE_VER)))) + $(error The version of MAKE $(REQ_MAKE_VER) or higher is required; you are running $(MAKE_VERSION)) +endif + +# Extract arguments for `make run` +EXTRACT_ARGS=false +ifeq (run,$(firstword $(MAKECMDGOALS))) + EXTRACT_ARGS=true +endif +ifeq ($(EXTRACT_ARGS),true) + # use the rest as arguments for "run" + WITH_ARGS ?= $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)) +endif +ifneq ($(WITH_ARGS),) + ARG_SEPARATOR=-- +endif + +%: + @: + +.ONESHELL: + +.PHONY: all build run run-local run-deps-bg clean-containers + +all: build run + +build: + @set -euo pipefail + cd ../../.. + docker build -t $(IMAGE_NAME) $(DOCKER_PARAMS)--build-arg DOCKERFILE_PATH="$(RELATIVE_ROOT_DIR)" -f "$(ROOT_DIR)/Dockerfile" . + +run: + @set -euo pipefail + USE_TTY="" && test -t 1 && USE_TTY="-t" + docker run -i $${USE_TTY} --rm $(DOCKER_PARAMS) -p 9000:9000 -p 19001-19003:19001-19003 -p 19001:19001/udp $(IMAGE_NAME) $(ARG_SEPARATOR) $(WITH_ARGS) + +# Runs the dependencies for the functional test in the background +# This is useful when running the tests on your host machine against the API in a container +run-deps-bg: + @set -euo pipefail + docker stop $(IMAGE_NAME) &> /dev/null || true + USE_TTY="" && test -t 1 && USE_TTY="-t" + docker run -d $${USE_TTY} --name $(IMAGE_NAME) --rm $(DOCKER_PARAMS) --entrypoint "/initialize.sh" -p 9000:9000 -p 19001-19003:19001-19003 -p 19001:19001/udp $(IMAGE_NAME) all tail-logs + +run-local: + @set -euo pipefail + USE_TTY="" && test -t 1 && USE_TTY="-t" + docker run -i $${USE_TTY} --rm $(DOCKER_PARAMS) -p 9000:9000 -p 19001-19003:19001-19003 -p 19001:19001/udp -v "$(ROOT_DIR)/../../../modules/api/src/test/functional:/functional_test" $(IMAGE_NAME) -- $(WITH_ARGS) + +clean-containers: + @set -euo pipefail + "$(ROOT_DIR)/../../../utils/clean-vinyldns-containers.sh" diff --git a/docker/api/docker.conf b/test/api/functional/application.conf similarity index 72% rename from docker/api/docker.conf rename to test/api/functional/application.conf index a0ec1d680..cd56c482e 100644 --- a/docker/api/docker.conf +++ b/test/api/functional/application.conf @@ -1,19 +1,5 @@ ################################################################################################################ -# This configuration is only used by docker. Environment variables are required in order to start -# up a docker cluster appropriately, so most of the values are passed in here. Defaults assume a local docker compose -# for vinyldns running. -# SQS_ENDPOINT is the SQS endpoint -# SQS_QUEUE_NAME is the queue name for the SQS queue -# SQS_REGION is the service region where the SQS queue lives (e.g. us-east-1) -# AWS_ACCESS_KEY is the AWS access key -# AWS_SECRET_ACCESS_KEY is the AWS secret access key -# JDBC_MIGRATION_URL - the URL for migations in the SQL database -# JDBC_URL - the full URL to the SQL database -# JDBC_USER - the SQL database user -# JDBC_PASSWORD - the SQL database password -# DEFAULT_DNS_ADDRESS - the server (and port if not 53) of the default DNS server -# DEFAULT_DNS_KEY_NAME - the default key name used to connect to the default DNS server -# DEFAULT_DNS_KEY_SECRET - the default key secret used to connect to the default DNS server +# This configuration is only used by docker and the build process ################################################################################################################ vinyldns { @@ -25,24 +11,6 @@ vinyldns { # this is where we can save additional backends backend-providers = [ - { - class-name = "vinyldns.route53.backend.Route53BackendProviderLoader" - settings = { - backends = [ - { - id = "r53", - access-key = "test", - access-key = ${?AWS_ACCESS_KEY_ID} - secret-key = "test", - secret-key = ${?AWS_SECRET_ACCESS_KEY}, - service-endpoint = "http://vinyldns-localstack:19009", - service-endpoint = ${?AWS_ROUTE53_ENDPOINT}, - signing-region = "us-east-1" - signing-region = ${?AWS_DEFAULT_REGION} - } - ] - } - }, { class-name = "vinyldns.api.backend.dns.DnsBackendProviderLoader" settings = { @@ -56,7 +24,7 @@ vinyldns { key-name = ${?DEFAULT_DNS_KEY_NAME} key = "nzisn+4G2ldMn0q1CV3vsg==" key = ${?DEFAULT_DNS_KEY_SECRET} - primary-server = "vinyldns-bind9" + primary-server = "127.0.0.1:19001" primary-server = ${?DEFAULT_DNS_ADDRESS} } transfer-connection = { @@ -65,7 +33,7 @@ vinyldns { key-name = ${?DEFAULT_DNS_KEY_NAME} key = "nzisn+4G2ldMn0q1CV3vsg==" key = ${?DEFAULT_DNS_KEY_SECRET} - primary-server = "vinyldns-bind9" + primary-server = "127.0.0.1:19001" primary-server = ${?DEFAULT_DNS_ADDRESS} }, tsig-usage = "always" @@ -78,7 +46,7 @@ vinyldns { key-name = ${?DEFAULT_DNS_KEY_NAME} key = "nzisn+4G2ldMn0q1CV3vsg==" key = ${?DEFAULT_DNS_KEY_SECRET} - primary-server = "vinyldns-bind9" + primary-server = "127.0.0.1:19001" primary-server = ${?DEFAULT_DNS_ADDRESS} } transfer-connection = { @@ -87,7 +55,7 @@ vinyldns { key-name = ${?DEFAULT_DNS_KEY_NAME} key = "nzisn+4G2ldMn0q1CV3vsg==" key = ${?DEFAULT_DNS_KEY_SECRET} - primary-server = "vinyldns-bind9" + primary-server = "127.0.0.1:19001" primary-server = ${?DEFAULT_DNS_ADDRESS} }, tsig-usage = "always" @@ -106,18 +74,18 @@ vinyldns { settings { # AWS access key and secret. - access-key = "x" + access-key = "test" access-key = ${?AWS_ACCESS_KEY} - secret-key = "x" + secret-key = "test" secret-key = ${?AWS_SECRET_ACCESS_KEY} # Regional endpoint to make your requests (eg. 'us-west-2', 'us-east-1', etc.). This is the region where your queue is housed. - signing-region = "x" + signing-region = "us-east-1" signing-region = ${?SQS_REGION} # Endpoint to access queue - service-endpoint = "http://vinyldns-elasticmq:9324/" - service-endpoint = ${?SQS_ENDPOINT} + service-endpoint = "http://localhost:19003/" + service-endpoint = ${?SQS_SERVICE_ENDPOINT} # Queue name. Should be used in conjunction with service endpoint, rather than using a queue url which is subject to change. queue-name = "vinyldns" @@ -132,6 +100,15 @@ vinyldns { sync-delay = 10000 + approved-name-servers = [ + "172.17.42.1.", + "ns1.parent.com." + "ns1.parent.com1." + "ns1.parent.com2." + "ns1.parent.com3." + "ns1.parent.com4." + ] + crypto { type = "vinyldns.core.crypto.NoOpCrypto" } @@ -144,10 +121,12 @@ vinyldns { # these must be overridden to use MYSQL for production use # assumes a docker or mysql instance running locally name = "vinyldns" + name = ${?DATABASE_NAME} driver = "org.mariadb.jdbc.Driver" - migration-url = "jdbc:mariadb://vinyldns-mysql:3306/?user=root&password=pass" + driver = ${?JDBC_DRIVER} + migration-url = "jdbc:mariadb://localhost:19002/?user=root&password=pass" migration-url = ${?JDBC_MIGRATION_URL} - url = "jdbc:mariadb://vinyldns-mysql:3306/vinyldns?user=root&password=pass" + url = "jdbc:mariadb://localhost:19002/vinyldns?user=root&password=pass" url = ${?JDBC_URL} user = "root" user = ${?JDBC_USER} @@ -205,7 +184,6 @@ vinyldns { "high-value-domain.*" # for testing ] ip-list = [ - # using reverse zones in the vinyldns/bind9 docker image for testing "192.0.2.252", "192.0.2.253", "fd69:27cc:fe91:0:0:0:0:ffff", @@ -221,13 +199,56 @@ vinyldns { "needs-review.*" ] ip-list = [ + "192.0.1.254", + "192.0.1.255", "192.0.2.254", "192.0.2.255", + "192.0.3.254", + "192.0.3.255", + "192.0.4.254", + "192.0.4.255", "fd69:27cc:fe91:0:0:0:ffff:1", - "fd69:27cc:fe91:0:0:0:ffff:2" + "fd69:27cc:fe91:0:0:0:ffff:2", + "fd69:27cc:fe92:0:0:0:ffff:1", + "fd69:27cc:fe92:0:0:0:ffff:2", + "fd69:27cc:fe93:0:0:0:ffff:1", + "fd69:27cc:fe93:0:0:0:ffff:2", + "fd69:27cc:fe94:0:0:0:ffff:1", + "fd69:27cc:fe94:0:0:0:ffff:2" ] zone-name-list = [ "zone.requires.review." + "zone.requires.review1." + "zone.requires.review2." + "zone.requires.review3." + "zone.requires.review4." + ] + } + + # FQDNs / IPs that cannot be modified via VinylDNS + # regex-list used for all record types except PTR + # ip-list used exclusively for PTR records + high-value-domains = { + regex-list = [ + "high-value-domain.*" # for testing + ] + ip-list = [ + "192.0.1.252", + "192.0.1.253", + "192.0.2.252", + "192.0.2.253", + "192.0.3.252", + "192.0.3.253", + "192.0.4.252", + "192.0.4.253", + "fd69:27cc:fe91:0:0:0:0:ffff", + "fd69:27cc:fe91:0:0:0:ffff:0", + "fd69:27cc:fe92:0:0:0:0:ffff", + "fd69:27cc:fe92:0:0:0:ffff:0", + "fd69:27cc:fe93:0:0:0:0:ffff", + "fd69:27cc:fe93:0:0:0:ffff:0", + "fd69:27cc:fe94:0:0:0:0:ffff", + "fd69:27cc:fe94:0:0:0:ffff:0" ] } @@ -243,11 +264,11 @@ vinyldns { global-acl-rules = [ { group-ids: ["global-acl-group-id"], - fqdn-regex-list: [".*shared."] + fqdn-regex-list: [".*shared[0-9]{1}."] }, { group-ids: ["another-global-acl-group"], - fqdn-regex-list: [".*ok."] + fqdn-regex-list: [".*ok[0-9]{1}."] } ] } diff --git a/test/api/integration/.env.integration b/test/api/integration/.env.integration new file mode 100755 index 000000000..12521a5c3 --- /dev/null +++ b/test/api/integration/.env.integration @@ -0,0 +1,27 @@ +# Overrides that can be used when dependent services are running in the vinyldns-integration host +# and 'sbt' or tests are running in another container. More importantly, when these services are +# not accessible via "localhost" +# +# Any docker container that wishes to to use these, can simply specify this file using the `--env-file` +# argument. + +# General settings +VINYLDNS_API_URL=http://vinyldns-integration:9000 +VINYLDNS_PORTAL_URL=http://vinyldns-integration:9001 + +# Portal settings +VINYLDNS_BACKEND_URL=http://vinyldns-integration:9000 +LDAP_PROVIDER_URL=ldap://vinyldns-integration:19004 + +# API Settings +SQS_SERVICE_ENDPOINT=http://vinyldns-integration:19003 +SNS_SERVICE_ENDPOINT=http://vinyldns-integration:19003 +R53_SERVICE_ENDPOINT=http://vinyldns-integration:19003 +MYSQL_ENDPOINT=vinyldns-integration:19002 +DEFAULT_DNS_ADDRESS=vinyldns-integration:19001 + +JDBC_DRIVER=org.mariadb.jdbc.Driver +JDBC_USER=root +JDBC_PASSWORD=pass +JDBC_URL=jdbc:mariadb://vinyldns-integration:19002/vinyldns?user=${JDBC_USER}&password=${JDBC_PASSWORD} +JDBC_MIGRATION_URL=jdbc:mariadb://vinyldns-integration:19002/?user=${JDBC_USER}&password=${JDBC_PASSWORD} diff --git a/test/api/integration/Dockerfile b/test/api/integration/Dockerfile new file mode 100644 index 000000000..6854e678b --- /dev/null +++ b/test/api/integration/Dockerfile @@ -0,0 +1,34 @@ +ARG VINYLDNS_BASE_VERSION=latest + +# Build VinylDNS API if the JAR doesn't already exist +FROM vinyldns/build:base-build as base-build +ARG DOCKERFILE_PATH="test/api/integration" +COPY "${DOCKERFILE_PATH}/application.conf" /opt/vinyldns/conf/ +COPY . /build/ +WORKDIR /build + +## Run the build if we don't already have a vinyldns-api.jar +ARG SKIP_API_BUILD="false" +RUN if [ -f artifacts/vinyldns-api.jar ]; then cp artifacts/vinyldns-api.jar /opt/vinyldns; fi && \ + if [ ! -f /opt/vinyldns/vinyldns-api.jar ] && [ "$SKIP_API_BUILD" == "false" ]; then \ + env SBT_OPTS="-Xmx2G -Xms512M -Xss2M -XX:MaxMetaspaceSize=2G" \ + sbt -Dbuild.scalafmtOnCompile=false -Dbuild.lintOnCompile=fase ";project api;coverageOff;assembly" \ + && cp artifacts/vinyldns-api.jar /opt/vinyldns/; \ + fi + +# Build the testing image, copying data from `base-build` +FROM vinyldns/build:base-test-integration-${VINYLDNS_BASE_VERSION} +SHELL ["/bin/bash","-c"] +ARG DOCKERFILE_PATH +COPY --from=base-build /opt/vinyldns /opt/vinyldns + +# Copy the project contents +COPY . /build/ +WORKDIR /build + +# Local bind server files +COPY quickstart/bind9/etc/named.conf.* /etc/bind/ +COPY quickstart/bind9/zones/ /var/bind/ +RUN named-checkconf + +ENV RUN_SERVICES="all" diff --git a/test/api/integration/Makefile b/test/api/integration/Makefile new file mode 100644 index 000000000..4abd336cb --- /dev/null +++ b/test/api/integration/Makefile @@ -0,0 +1,64 @@ +SHELL=bash +IMAGE_NAME=vinyldns-api-integration +ROOT_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) +RELATIVE_ROOT_DIR:=$(shell realpath --relative-to=../../.. $(ROOT_DIR)) + +# Check that the required version of make is being used +REQ_MAKE_VER:=3.82 +ifneq ($(REQ_MAKE_VER),$(firstword $(sort $(MAKE_VERSION) $(REQ_MAKE_VER)))) + $(error The version of MAKE $(REQ_MAKE_VER) or higher is required; you are running $(MAKE_VERSION)) +endif + +# Extract arguments for `make run` +EXTRACT_ARGS=false +ifeq (run,$(firstword $(MAKECMDGOALS))) + EXTRACT_ARGS=true +endif +ifeq ($(EXTRACT_ARGS),true) + # use the rest as arguments for "run" + WITH_ARGS ?= $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)) +endif +ifneq ($(WITH_ARGS),) + ARG_SEPARATOR=-- +endif + +%: + @: + +.ONESHELL: + +.PHONY: all build run run-local run-bg stop-bg clean-containers + +all: build run + +build: + @set -euo pipefail + cd ../../.. + docker build -t $(IMAGE_NAME) $(DOCKER_PARAMS) --build-arg DOCKERFILE_PATH="$(RELATIVE_ROOT_DIR)" -f "$(ROOT_DIR)/Dockerfile" . + +run: + @set -euo pipefail + docker network create --driver bridge vinyldns_net &> /dev/null || true + USE_TTY="" && test -t 1 && USE_TTY="-t" + docker run -i $${USE_TTY} --rm --network vinyldns_net $(DOCKER_PARAMS) $(IMAGE_NAME) $(ARG_SEPARATOR) $(WITH_ARGS) + +run-bg: + @set -euo pipefail + docker stop $(IMAGE_NAME) &> /dev/null || true + docker network create --driver bridge vinyldns_net &> /dev/null || true + USE_TTY="" && test -t 1 && USE_TTY="-t" + docker run -d $${USE_TTY} --name $(IMAGE_NAME) --rm --network vinyldns_net $(DOCKER_PARAMS) -e RUN_SERVICES="deps-only tail-logs" -p 19001-19003:19001-19003 -p 19001:19001/udp $(IMAGE_NAME) + +stop-bg: + @set -euo pipefail + docker stop $(IMAGE_NAME) &> /dev/null || true + +run-local: + @set -euo pipefail + docker network create --driver bridge vinyldns_net &> /dev/null || true + USE_TTY="" && test -t 1 && USE_TTY="-t" + docker run -i $${USE_TTY} --rm --network vinyldns_net $(DOCKER_PARAMS) -v "$(ROOT_DIR)/../../..:/build" $(IMAGE_NAME) -- $(WITH_ARGS) + +clean-containers: + @set -euo pipefail + "$(ROOT_DIR)/../../../utils/clean-vinyldns-containers.sh" diff --git a/test/api/integration/application.conf b/test/api/integration/application.conf new file mode 100644 index 000000000..ac795eef8 --- /dev/null +++ b/test/api/integration/application.conf @@ -0,0 +1,356 @@ +################################################################################################################ +# This configuration is only used by docker and the build process +################################################################################################################ +vinyldns { + + base-version = "0.0.0-local-dev" + version = ${vinyldns.base-version} # default to the base version if not overridden + version = ${?VINYLDNS_VERSION} # override the base version via env var + + # How often to any particular zone can be synchronized in milliseconds + sync-delay = 10000 + sync-delay = ${?SYNC_DELAY} + + # If we should start up polling for change requests, set this to false for the inactive cluster + processing-disabled = false + processing-disabled = ${?PROCESSING_DISABLED} + + # Number of records that can be in a zone + max-zone-size = 60000 + max-zone-size = ${?MAX_ZONE_SIZE} + + # Types of unowned records that users can access in shared zones + shared-approved-types = ["A", "AAAA", "CNAME", "PTR", "TXT"] + + # Batch change settings + batch-change-limit = 1000 + batch-change-limit = ${?BATCH_CHANGE_LIMIT} + manual-batch-review-enabled = true + manual-batch-review-enabled = ${?MANUAL_BATCH_REVIEW_ENABLED} + scheduled-changes-enabled = true + scheduled-changes-enabled = ${?SCHEDULED_CHANGES_ENABLED} + multi-record-batch-change-enabled = true + multi-record-batch-change-enabled = ${?MULTI_RECORD_BATCH_CHANGE_ENABLED} + + # configured backend providers + backend { + # Use "default" when dns backend legacy = true + # otherwise, use the id of one of the connections in any of your backends + default-backend-id = "default" + + # this is where we can save additional backends + backend-providers = [ + { + class-name = "vinyldns.api.backend.dns.DnsBackendProviderLoader" + settings = { + legacy = false + backends = [ + { + id = "default" + zone-connection = { + name = "vinyldns." + key-name = "vinyldns." + key-name = ${?DEFAULT_DNS_KEY_NAME} + key = "nzisn+4G2ldMn0q1CV3vsg==" + key = ${?DEFAULT_DNS_KEY_SECRET} + primary-server = "127.0.0.1:19001" + primary-server = ${?DEFAULT_DNS_ADDRESS} + } + transfer-connection = { + name = "vinyldns." + key-name = "vinyldns." + key-name = ${?DEFAULT_DNS_KEY_NAME} + key = "nzisn+4G2ldMn0q1CV3vsg==" + key = ${?DEFAULT_DNS_KEY_SECRET} + primary-server = "127.0.0.1:19001" + primary-server = ${?DEFAULT_DNS_ADDRESS} + }, + tsig-usage = "always" + }, + { + id = "func-test-backend" + zone-connection = { + name = "vinyldns." + key-name = "vinyldns." + key-name = ${?DEFAULT_DNS_KEY_NAME} + key = "nzisn+4G2ldMn0q1CV3vsg==" + key = ${?DEFAULT_DNS_KEY_SECRET} + primary-server = "127.0.0.1:19001" + primary-server = ${?DEFAULT_DNS_ADDRESS} + } + transfer-connection = { + name = "vinyldns." + key-name = "vinyldns." + key-name = ${?DEFAULT_DNS_KEY_NAME} + key = "nzisn+4G2ldMn0q1CV3vsg==" + key = ${?DEFAULT_DNS_KEY_SECRET} + primary-server = "127.0.0.1:19001" + primary-server = ${?DEFAULT_DNS_ADDRESS} + }, + tsig-usage = "always" + } + ] + } + } + ] + } + + queue { + class-name = "vinyldns.sqs.queue.SqsMessageQueueProvider" + + messages-per-poll = 10 + polling-interval = 250.millis + + settings { + # AWS access key and secret. + access-key = "test" + access-key = ${?AWS_ACCESS_KEY} + secret-key = "test" + secret-key = ${?AWS_SECRET_ACCESS_KEY} + + # Regional endpoint to make your requests (eg. 'us-west-2', 'us-east-1', etc.). This is the region where your queue is housed. + signing-region = "us-east-1" + signing-region = ${?SQS_REGION} + + # Endpoint to access queue + service-endpoint = "http://localhost:19003/" + service-endpoint = ${?SQS_SERVICE_ENDPOINT} + + # Queue name. Should be used in conjunction with service endpoint, rather than using a queue url which is subject to change. + queue-name = "vinyldns" + queue-name = ${?SQS_QUEUE_NAME} + } + } + + email { + class-name = "vinyldns.api.notifier.email.EmailNotifierProvider" + class-name = ${?EMAIL_CLASS_NAME} + settings = { + from = "VinylDNS " + } + } + + sns { + class-name = "vinyldns.api.notifier.sns.SnsNotifierProvider" + class-name = ${?SNS_CLASS_NAME} + settings { + topic-arn = "arn:aws:sns:us-east-1:000000000000:batchChanges" + topic-arn = ${?SNS_TOPIC_ARN} + access-key = "test" + access-key = ${?SNS_ACCESS_KEY} + secret-key = "test" + secret-key = ${?SNS_SECRET_KEY} + service-endpoint = "http://127.0.0.1:19003" + service-endpoint = ${?SNS_SERVICE_ENDPOINT} + signing-region = "us-east-1" + signing-region = ${?SNS_REGION} + } + } + + rest { + host = "0.0.0.0" + port = 9000 + port=${?API_SERVICE_PORT} + } + + sync-delay = 10000 + + approved-name-servers = [ + "172.17.42.1.", + "ns1.parent.com." + "ns1.parent.com1." + "ns1.parent.com2." + "ns1.parent.com3." + "ns1.parent.com4." + ] + + crypto { + type = "vinyldns.core.crypto.NoOpCrypto" + } + + data-stores = ["mysql"] + + mysql { + settings { + # JDBC Settings, these are all values in scalikejdbc-config, not our own + # these must be overridden to use MYSQL for production use + # assumes a docker or mysql instance running locally + name = "vinyldns" + name = ${?DATABASE_NAME} + driver = "org.mariadb.jdbc.Driver" + driver = ${?JDBC_DRIVER} + migration-url = "jdbc:mariadb://localhost:19002/?user=root&password=pass" + migration-url = ${?JDBC_MIGRATION_URL} + url = "jdbc:mariadb://localhost:19002/vinyldns?user=root&password=pass" + url = ${?JDBC_URL} + user = "root" + user = ${?JDBC_USER} + password = "pass" + password = ${?JDBC_PASSWORD} + # see https://github.com/brettwooldridge/HikariCP + connection-timeout-millis = 1000 + idle-timeout = 10000 + max-lifetime = 600000 + maximum-pool-size = 20 + minimum-idle = 20 + register-mbeans = true + } + # Repositories that use this data store are listed here + repositories { + zone { + # no additional settings for now + } + batch-change { + # no additional settings for now + } + user { + + } + record-set { + + } + group { + + } + membership { + + } + group-change { + + } + zone-change { + + } + record-change { + + } + } + } + + backends = [] + + batch-change-limit = 1000 + + # FQDNs / IPs that cannot be modified via VinylDNS + # regex-list used for all record types except PTR + # ip-list used exclusively for PTR records + high-value-domains = { + regex-list = [ + "high-value-domain.*" # for testing + ] + ip-list = [ + "192.0.2.252", + "192.0.2.253", + "fd69:27cc:fe91:0:0:0:0:ffff", + "fd69:27cc:fe91:0:0:0:ffff:0" + ] + } + + # FQDNs / IPs / zone names that require manual review upon submission in batch change interface + # domain-list used for all record types except PTR + # ip-list used exclusively for PTR records + manual-review-domains = { + domain-list = [ + "needs-review.*" + ] + ip-list = [ + "192.0.1.254", + "192.0.1.255", + "192.0.2.254", + "192.0.2.255", + "192.0.3.254", + "192.0.3.255", + "192.0.4.254", + "192.0.4.255", + "fd69:27cc:fe91:0:0:0:ffff:1", + "fd69:27cc:fe91:0:0:0:ffff:2", + "fd69:27cc:fe92:0:0:0:ffff:1", + "fd69:27cc:fe92:0:0:0:ffff:2", + "fd69:27cc:fe93:0:0:0:ffff:1", + "fd69:27cc:fe93:0:0:0:ffff:2", + "fd69:27cc:fe94:0:0:0:ffff:1", + "fd69:27cc:fe94:0:0:0:ffff:2" + ] + zone-name-list = [ + "zone.requires.review." + "zone.requires.review1." + "zone.requires.review2." + "zone.requires.review3." + "zone.requires.review4." + ] + } + + # FQDNs / IPs that cannot be modified via VinylDNS + # regex-list used for all record types except PTR + # ip-list used exclusively for PTR records + high-value-domains = { + regex-list = [ + "high-value-domain.*" # for testing + ] + ip-list = [ + "192.0.1.252", + "192.0.1.253", + "192.0.2.252", + "192.0.2.253", + "192.0.3.252", + "192.0.3.253", + "192.0.4.252", + "192.0.4.253", + "fd69:27cc:fe91:0:0:0:0:ffff", + "fd69:27cc:fe91:0:0:0:ffff:0", + "fd69:27cc:fe92:0:0:0:0:ffff", + "fd69:27cc:fe92:0:0:0:ffff:0", + "fd69:27cc:fe93:0:0:0:0:ffff", + "fd69:27cc:fe93:0:0:0:ffff:0", + "fd69:27cc:fe94:0:0:0:0:ffff", + "fd69:27cc:fe94:0:0:0:ffff:0" + ] + } + + # types of unowned records that users can access in shared zones + shared-approved-types = ["A", "AAAA", "CNAME", "PTR", "TXT"] + + manual-batch-review-enabled = true + + scheduled-changes-enabled = true + + multi-record-batch-change-enabled = true + + global-acl-rules = [ + { + group-ids: ["global-acl-group-id"], + fqdn-regex-list: [".*shared[0-9]{1}."] + }, + { + group-ids: ["another-global-acl-group"], + fqdn-regex-list: [".*ok[0-9]{1}."] + } + ] +} + +akka { + loglevel = "INFO" + loggers = ["akka.event.slf4j.Slf4jLogger"] + logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" + logger-startup-timeout = 30s + + actor { + provider = "akka.actor.LocalActorRefProvider" + } +} + +akka.http { + server { + # The time period within which the TCP binding process must be completed. + # Set to `infinite` to disable. + bind-timeout = 5s + + # Show verbose error messages back to the client + verbose-error-messages = on + } + + parsing { + # Spray doesn't like the AWS4 headers + illegal-header-warnings = on + } +} diff --git a/test/portal/functional/Dockerfile b/test/portal/functional/Dockerfile new file mode 100644 index 000000000..45b2ea53a --- /dev/null +++ b/test/portal/functional/Dockerfile @@ -0,0 +1,14 @@ +FROM vinyldns/build:base-test-portal +SHELL ["/bin/bash","-c"] +ARG DOCKERFILE_PATH="test/portal/functional" + +WORKDIR /functional_test +COPY modules/portal /functional_test +COPY $DOCKERFILE_PATH/run.sh /functional_test +RUN cp /build/node_modules.tar.xz /functional_test && \ + cd /functional_test && \ + tar Jxf node_modules.tar.xz && \ + rm -rf node_modules.tar.xz + +ENTRYPOINT ["./run.sh"] + diff --git a/test/portal/functional/Makefile b/test/portal/functional/Makefile new file mode 100644 index 000000000..59f3f6cd1 --- /dev/null +++ b/test/portal/functional/Makefile @@ -0,0 +1,48 @@ +SHELL=bash +IMAGE_NAME=vinyldns-portal-test +ROOT_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) +RELATIVE_ROOT_DIR:=$(shell realpath --relative-to=../../.. $(ROOT_DIR)) + +# Check that the required version of make is being used +REQ_MAKE_VER:=3.82 +ifneq ($(REQ_MAKE_VER),$(firstword $(sort $(MAKE_VERSION) $(REQ_MAKE_VER)))) + $(error The version of MAKE $(REQ_MAKE_VER) or higher is required; you are running $(MAKE_VERSION)) +endif + +# Extract arguments for `make run` +EXTRACT_ARGS=false +ifeq (run,$(firstword $(MAKECMDGOALS))) + EXTRACT_ARGS=true +endif +ifeq ($(EXTRACT_ARGS),true) + # use the rest as arguments for "run" + WITH_ARGS ?= $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)) +endif + +%: + @: + +.ONESHELL: + +.PHONY: all build run run-local clean-containers + +all: build run + +build: + @set -euo pipefail + cd ../../.. + docker build -t $(IMAGE_NAME) --build-arg DOCKERFILE_PATH="$(RELATIVE_ROOT_DIR)" -f "$(ROOT_DIR)/Dockerfile" . + +run: + @set -euo pipefail + USE_TTY="" && test -t 1 && USE_TTY="-t" + docker run -i $${USE_TTY} --rm $(IMAGE_NAME) $(WITH_ARGS) + +run-local: + @set -euo pipefail + USE_TTY="" && test -t 1 && USE_TTY="-t" + docker run -i $${USE_TTY} --rm -v "$$(pwd)/../../../modules/portal:/functional_test" -v "$$(pwd)/run.sh:/functional_test/run.sh" $(IMAGE_NAME) $(WITH_ARGS) + +clean-containers: + @set -euo pipefail + "$(ROOT_DIR)/../../../utils/clean-vinyldns-containers.sh" diff --git a/test/portal/functional/run.sh b/test/portal/functional/run.sh new file mode 100755 index 000000000..c0fad0e32 --- /dev/null +++ b/test/portal/functional/run.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +set -eo pipefail + +ROOT_DIR=$(cd -P -- "$(dirname -- "$0")" && pwd -P) +cd "${ROOT_DIR}" +if [ "$1" == "--interactive" ]; then + shift + bash +else + # Attempt to just run grunt - this should work most of the time + # We may need to update dependencies if our local functional tests dependencies + # differ from those of the 'base-test-portal' docker image + grunt unit "$@" || { echo "Attempting to recover.." && npm install -f --no-audit --no-fund && grunt unit "$@"; } +fi diff --git a/bin/add-license-headers.sh b/utils/add-license-headers.sh similarity index 100% rename from bin/add-license-headers.sh rename to utils/add-license-headers.sh diff --git a/utils/admin/Dockerfile b/utils/admin/Dockerfile new file mode 100644 index 000000000..f292086af --- /dev/null +++ b/utils/admin/Dockerfile @@ -0,0 +1,23 @@ +FROM znly/protoc:0.4.0 as pbcompile +WORKDIR /vinyldns + +# Needs to protoc compile modules/core/src/main/protobuf/VinylDNSProto.proto +COPY modules/core/src/main/protobuf/VinylDNSProto.proto /vinyldns + +# Create a compiled protobuf in /vinyldns/target +RUN mkdir -p /vinyldns/python && \ + protoc --proto_path=/vinyldns --python_out=/vinyldns/python /vinyldns/VinylDNSProto.proto + + +FROM vinyldns/build:base-build +ARG DOCKERFILE_PATH +WORKDIR /app +RUN pip install mysql-connector-python==8.0.27 + +ENV DB_USER="root" DB_PASS="pass" DB_HOST="vinyldns-integration" DB_NAME="vinyldns" DB_PORT="19002" + +COPY --from=pbcompile /vinyldns/python . +COPY ${DOCKERFILE_PATH}/update-support-user.py . +RUN chmod 755 update-support-user.py + +ENTRYPOINT ["./update-support-user.py"] diff --git a/utils/admin/Makefile b/utils/admin/Makefile new file mode 100644 index 000000000..2f9e422fa --- /dev/null +++ b/utils/admin/Makefile @@ -0,0 +1,43 @@ +SHELL=bash +IMAGE_NAME=vinyldns-update-user +ROOT_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) +RELATIVE_ROOT_DIR:=$(shell realpath --relative-to=../.. $(ROOT_DIR)) + +# Check that the required version of make is being used +REQ_MAKE_VER:=3.82 +ifneq ($(REQ_MAKE_VER),$(firstword $(sort $(MAKE_VERSION) $(REQ_MAKE_VER)))) + $(error The version of MAKE $(REQ_MAKE_VER) or higher is required; you are running $(MAKE_VERSION)) +endif + +# Extract arguments for `make run` +EXTRACT_ARGS=false +ifeq (run,$(firstword $(MAKECMDGOALS))) + EXTRACT_ARGS=true +endif +ifeq ($(EXTRACT_ARGS),true) + # use the rest as arguments for "run" + WITH_ARGS ?= $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)) +endif +ifneq ($(WITH_ARGS),) + ARG_SEPARATOR=-- +endif + +%: + @: + +.ONESHELL: + +.PHONY: all build run + +all: build run + +build: + @set -euo pipefail + cd ../.. + docker build -t $(IMAGE_NAME) --build-arg DOCKERFILE_PATH="$(RELATIVE_ROOT_DIR)" -f "$(ROOT_DIR)/Dockerfile" . + +run: + @set -euo pipefail + docker network create --driver bridge vinyldns_net &> /dev/null || true + USE_TTY="" && test -t 1 && USE_TTY="-t" + docker run -i $${USE_TTY} --network vinyldns_net --rm $(DOCKER_PARAMS) $(IMAGE_NAME) $(WITH_ARGS) diff --git a/docker/admin/update-support-user.py b/utils/admin/update-support-user.py old mode 100755 new mode 100644 similarity index 84% rename from docker/admin/update-support-user.py rename to utils/admin/update-support-user.py index 4157f054b..247ede022 --- a/docker/admin/update-support-user.py +++ b/utils/admin/update-support-user.py @@ -1,12 +1,17 @@ #!/usr/bin/env python -import mysql.connector -import VinylDNSProto_pb2 -import sys import os +import sys + +import VinylDNSProto_pb2 +import mysql.connector # arguments +if len(sys.argv) != 3: + print("USAGE: update-support-user.py ") + exit(1) + user_name = sys.argv[1] -make_support = sys.argv[2][0].upper()=='T' if len(sys.argv) >= 2 else None +make_support = sys.argv[2][0].upper() == 'T' # environment variables to connect to database db_user = os.environ.get('DB_USER') @@ -23,7 +28,7 @@ update = "UPDATE user SET data = %(pb)s WHERE user_name = %(user_name)s" cursor = cnx.cursor(dictionary=True) try: - cursor.execute(query, { 'user_name': user_name }) + cursor.execute(query, {'user_name': user_name}) user = VinylDNSProto_pb2.User() for row in cursor: user_raw = row['data'] @@ -42,7 +47,7 @@ try: if make_support is not None: print("Updating {}, Support = {}".format(user_name, make_support)) user.isSupport = make_support - cursor.execute(update, { 'pb': user.SerializeToString(), 'user_name': user_name }) + cursor.execute(update, {'pb': user.SerializeToString(), 'user_name': user_name}) cnx.commit() else: print("Skipping making support as no make support value provided") diff --git a/utils/clean-vinyldns-containers.sh b/utils/clean-vinyldns-containers.sh new file mode 100755 index 000000000..3541a8bbb --- /dev/null +++ b/utils/clean-vinyldns-containers.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +# +# This script with kill and remove containers associated +# with VinylDNS +# +# Note: this will not remove the actual images from your +# machine, just the running containers + +ALL_IDS=$(docker ps -a | grep -e 'vinyldns' -e 'flaviovs/mock-smtp' | awk '{print $1}') +if [ "${ALL_IDS}" == "" ]; then + echo "Nothing to remove" + exit 0 +fi + +RUNNING_IDS=$(docker ps | grep -e 'vinyldns' -e 'flaviovs/mock-smtp' | awk '{print $1}') +if [ "${RUNNING_IDS}" != "" ]; then + echo "Killing running containers..." + echo "${RUNNING_IDS}" | xargs docker kill +fi + +ALL_IDS=$(docker ps -a | grep -e 'vinyldns' -e 'flaviovs/mock-smtp' | awk '{print $1}') +if [ "${ALL_IDS}" != "" ]; then + echo "Removing containers..." + echo "${ALL_IDS}" | xargs docker rm -v +fi + +docker network prune -f diff --git a/utils/includes/terminal_colors.sh b/utils/includes/terminal_colors.sh new file mode 100755 index 000000000..be7d81875 --- /dev/null +++ b/utils/includes/terminal_colors.sh @@ -0,0 +1,18 @@ +# Color codes prefixed with F_ (for "font") to disambiguate +F_RESET=$(echo -en '\033[0m') +F_RED=$(echo -en '\033[00;31m') +F_GREEN=$(echo -en '\033[00;32m') +F_YELLOW=$(echo -en '\033[00;33m') +F_BLUE=$(echo -en '\033[00;34m') +F_MAGENTA=$(echo -en '\033[00;35m') +F_PURPLE=$(echo -en '\033[00;35m') +F_CYAN=$(echo -en '\033[00;36m') +F_LGRAY=$(echo -en '\033[00;37m') +F_LRED=$(echo -en '\033[01;31m') +F_LGREEN=$(echo -en '\033[01;32m') +F_LYELLOW=$(echo -en '\033[01;33m') +F_LBLUE=$(echo -en '\033[01;34m') +F_LMAGENTA=$(echo -en '\033[01;35m') +F_LPURPLE=$(echo -en '\033[01;35m') +F_LCYAN=$(echo -en '\033[01;36m') +F_WHITE=$(echo -en '\033[01;37m') diff --git a/utils/update-support-user.sh b/utils/update-support-user.sh new file mode 100755 index 000000000..976b60f9c --- /dev/null +++ b/utils/update-support-user.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env bash + +usage () { + echo -e "Usage: update-support-user.sh [OPTIONS] \n" + echo -e "Description: Updates a user in VinylDNS to a support user, or removes the user as a support user.\n" + echo -e "Required Parameters:" + echo -e "username\tThe VinylDNS user for which to change the support flag" + echo -e "enableSupport\t'true' to set the user as a support user; 'false' to remove support privileges\n" + echo -e "OPTIONS:" + echo -e " -u|--user \tDatabase user name for accessing the VinylDNS database (DB_USER - default=root)" + echo -e " -p|--password\tDatabase user password for accessing the VinylDNS database (DB_PASS - default=pass)" + echo -e " -h|--host\tDatabase host name for the mysql server (DB_HOST - default=vinyldns-integration)" + echo -e " -n|--name\tName of the VinylDNS database, (DB_NAME - default=vinyldns)" + echo -e " -c|--port\tPort of the VinylDNS database, (DB_PORT - default=19002)" +} + +DIR=$( cd "$(dirname "$0")" || exit ; pwd -P ) +VINYL_ROOT=$DIR/.. +WORK_DIR=${VINYL_ROOT}/docker + +DB_USER=${DB_USER:-root} +DB_PASS=${DB_PASS:-pass} +DB_HOST=${DB_HOST:-vinyldns-integration} +DB_NAME=${DB_NAME:-vinyldns} +DB_PORT=${DB_PORT:-19002} + +while [ "$1" != "" ]; do + case "$1" in + -u | --user ) DB_USER="$2"; shift;; + -p | --password ) DB_PASS="$2"; shift;; + -h | --host ) DB_HOST="$2"; shift;; + -n | --name ) DB_NAME="$2"; shift;; + -c | --port ) DB_PORT="$2"; shift;; + * ) break;; + esac + shift +done + +VINYL_USER="$1" +MAKE_SUPPORT="$2" + +ERROR= +if [ -z "$DB_USER" ]; then + ERROR="1" +fi + +if [ -z "$DB_PASS" ]; then + ERROR="1" +fi + +if [ -z "$DB_HOST" ]; then + ERROR="1" +fi + +if [ -z "$DB_NAME" ]; then + ERROR="1" +fi + +if [ -z "$VINYL_USER" ]; then + ERROR="1" +fi + +if [ -z "$MAKE_SUPPORT" ]; then + ERROR="1" +fi + +if [ -n "$ERROR" ]; then + usage + exit 1 +fi + +# Build and run the Docker container +cd admin +make build +make run DOCKER_PARAMS="-e \"DB_USER=$DB_USER\" -e \"DB_PASS=$DB_PASS\" -e \"DB_HOST=$DB_HOST\" -e \"DB_NAME=$DB_NAME\" -e \"DB_PORT=$DB_PORT\"" WITH_ARGS="\"$VINYL_USER\" \"$MAKE_SUPPORT\"" diff --git a/version.sbt b/version.sbt index 3da2cab98..7ac0e7297 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.9.10" +version in ThisBuild := "0.10.4"