Compare commits
62 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a5cf641d27 | |||
| 2a76c9e469 | |||
| 8bbcebc53c | |||
| ac1fd02b2f | |||
| e42579541a | |||
| f180e7daba | |||
| 0ce37c53aa | |||
| 60005d7d6e | |||
| 4e7b3b9bdb | |||
| 66a5d48927 | |||
| 6e71ba266a | |||
| be409139d7 | |||
| 8d2fc74d04 | |||
| aaae19f783 | |||
| 092412cf92 | |||
| abb9704a87 | |||
| 6a11868a0b | |||
| f016067931 | |||
| c857c0d233 | |||
| dd1052cd75 | |||
| 32618a942b | |||
| 4d7deb3f2c | |||
| 85f462e002 | |||
| d1e2a78f24 | |||
| 233c3988bc | |||
| b199495d55 | |||
| 8b69b2551a | |||
| eb2a96a482 | |||
| b864e019c1 | |||
| fc7952f8a2 | |||
| 378c3e5d9b | |||
| a6b76a00bf | |||
| 9a525ace3b | |||
| baf6c6a8a3 | |||
| 729799faef | |||
| d7d49d10fb | |||
| 813cb3a65b | |||
| 78310e5639 | |||
| 3b83e65e21 | |||
| ce460ee4d8 | |||
| a3b1a542b2 | |||
| 163a096f81 | |||
| a0016d7ca3 | |||
| e1600d1b4e | |||
| 116350b65d | |||
| 9d41ddc2e5 | |||
| 53b10b142e | |||
| 6abd0ce862 | |||
| 579aa4971b | |||
| 725d8e5698 | |||
| 2b359cbd88 | |||
| 7b83b99cf1 | |||
| e90f4406e8 | |||
| 34b3f98d37 | |||
| eb8eb1ca43 | |||
| 85b71b851d | |||
| 2480d12a16 | |||
| 880a6c7380 | |||
| 69bbda1493 | |||
| cd2bc207ef | |||
| d83c364660 | |||
| 2efcb24321 |
@@ -0,0 +1,35 @@
|
|||||||
|
name: Publish JUnit Report (Short Names)
|
||||||
|
description: Normalize JUnit XML report names and publish a summary-only test report.
|
||||||
|
inputs:
|
||||||
|
token:
|
||||||
|
description: GitHub token for creating the check run.
|
||||||
|
required: true
|
||||||
|
report-name:
|
||||||
|
description: Name shown for the test report.
|
||||||
|
required: false
|
||||||
|
default: Summary of JUnit Tests
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
steps:
|
||||||
|
- name: Normalize JUnit report names
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
mkdir -p junit-short
|
||||||
|
shopt -s globstar nullglob
|
||||||
|
for f in **/target/*-reports/TEST-*.xml; do
|
||||||
|
base="$(basename "$f")"
|
||||||
|
short="${base#TEST-}"
|
||||||
|
short="${short%.xml}"
|
||||||
|
cp "$f" "junit-short/${short}"
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Publish Test Report
|
||||||
|
uses: dorny/test-reporter@v2
|
||||||
|
with:
|
||||||
|
token: ${{ inputs.token }}
|
||||||
|
name: ${{ inputs.report-name }}
|
||||||
|
path: "*"
|
||||||
|
reporter: java-junit
|
||||||
|
only-summary: true
|
||||||
|
working-directory: "junit-short"
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
name: "Setup Maven with GitHub Packages"
|
||||||
|
|
||||||
|
description: "Sets up JDK, caches Maven dependencies, and configures GitHub Packages for Maven repositories."
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
java-version:
|
||||||
|
description: "Java version to install"
|
||||||
|
default: "17"
|
||||||
|
required: true
|
||||||
|
java-distribution:
|
||||||
|
description: "Java distribution to use"
|
||||||
|
default: "corretto"
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: "composite"
|
||||||
|
steps:
|
||||||
|
- name: Set up JDK
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: ${{ inputs.java-distribution }}
|
||||||
|
java-version: ${{ inputs.java-version }}
|
||||||
|
|
||||||
|
- name: Cache Maven Repository
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ~/.m2/repository
|
||||||
|
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-maven-
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
name: Build and Analyse
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- develop
|
||||||
|
- feature*
|
||||||
|
pull_request:
|
||||||
|
types: [ opened, synchronize, reopened ]
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
build-and-analyse:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
|
||||||
|
|
||||||
|
- name: Setup Java and Maven
|
||||||
|
uses: ./.github/actions/setup-java-maven
|
||||||
|
|
||||||
|
- name: Build and analyze with SonarCloud
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||||
|
CF_API_TOKEN: ${{ secrets.API_TOKEN }}
|
||||||
|
run: |
|
||||||
|
echo "Running SonarCloud analysis..."
|
||||||
|
mvn -B -DtestClasspath=src/test/ verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=th-schwarz_CloudflareDNS-java
|
||||||
|
|
||||||
|
- name: Publish Test Report
|
||||||
|
uses: ./.github/actions/publish-report/
|
||||||
|
if: ${{ always() }}
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
report-name: Summary of JUnit Tests
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
default:
|
|
||||||
image: maven:3-amazoncorretto-17-alpine
|
|
||||||
|
|
||||||
stages:
|
|
||||||
- build
|
|
||||||
- on_commit
|
|
||||||
- sonarcloud_scan
|
|
||||||
- deploy
|
|
||||||
- release
|
|
||||||
|
|
||||||
variables:
|
|
||||||
GITLAB_CLONE_DIR: "/builds/th-schwarz/CloudflareDNS-java"
|
|
||||||
GITLAB_USERNAME: $GITLAB_USERNAME
|
|
||||||
GITLAB_USEREMAIL: GITLAB_USEREMAIL
|
|
||||||
SONAR_HOST_URL: $SONAR_HOST_URL
|
|
||||||
SONAR_PROJECT_KEY: "th-schwarz_CloudflareDNS-java"
|
|
||||||
SONAR_ORGANIZATION: "th-schwarz"
|
|
||||||
SONAR_TOKEN: $SONAR_TOKEN
|
|
||||||
SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"
|
|
||||||
GIT_DEPTH: "0" # Tells git to fetch all the branches of the project, required by the analysis task
|
|
||||||
API_EMAIL: $API_EMAIL
|
|
||||||
API_KEY: $API_KEY
|
|
||||||
API_TOKEN: $API_TOKEN
|
|
||||||
|
|
||||||
build:
|
|
||||||
stage: build
|
|
||||||
script:
|
|
||||||
- echo "Running package..."
|
|
||||||
- cd ${GITLAB_CLONE_DIR}
|
|
||||||
- mvn clean package
|
|
||||||
- echo "Preparing GitLab Pages from docs/ (javadoc)"
|
|
||||||
- mkdir public
|
|
||||||
- cp -rv docs/* public/
|
|
||||||
- mkdir public/apidocs
|
|
||||||
- cp -rv target/reports/apidocs public/
|
|
||||||
artifacts:
|
|
||||||
paths:
|
|
||||||
- target/surefire-reports/*.xml
|
|
||||||
- target/
|
|
||||||
- public/
|
|
||||||
except:
|
|
||||||
- tags
|
|
||||||
|
|
||||||
on_commits:
|
|
||||||
stage: on_commit
|
|
||||||
dependencies:
|
|
||||||
- build
|
|
||||||
script:
|
|
||||||
- echo "on_commit DONE"
|
|
||||||
only:
|
|
||||||
- /^feature.*$/
|
|
||||||
- merge_request
|
|
||||||
- develop
|
|
||||||
|
|
||||||
pages:
|
|
||||||
# triggers the page deployment of gitlab
|
|
||||||
stage: deploy
|
|
||||||
script:
|
|
||||||
- echo "Publishing to GitLab Pages ..."
|
|
||||||
artifacts:
|
|
||||||
paths:
|
|
||||||
- public
|
|
||||||
only:
|
|
||||||
- develop
|
|
||||||
|
|
||||||
sonarcloud_scan:
|
|
||||||
stage: sonarcloud_scan
|
|
||||||
dependencies:
|
|
||||||
- build
|
|
||||||
script:
|
|
||||||
- mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=${SONAR_PROJECT_KEY}
|
|
||||||
only:
|
|
||||||
- merge_requests
|
|
||||||
- develop
|
|
||||||
- tags
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
when:
|
||||||
|
- event: push
|
||||||
|
branch: develop
|
||||||
|
|
||||||
|
steps:
|
||||||
|
# - name: hello
|
||||||
|
# image: alpine
|
||||||
|
# commands:
|
||||||
|
# - echo "Hello World!"
|
||||||
|
|
||||||
|
- name: maven verify
|
||||||
|
image: maven:3-amazoncorretto-17-alpine
|
||||||
|
commands:
|
||||||
|
- mvn -B verify
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
# CloudflareDNS-java
|
# CloudflareDNS-java
|
||||||
|
|
||||||

|
[](https://ci.codeberg.org/repos/16522)
|
||||||

|
|
||||||
|
|
||||||
[](https://sonarcloud.io/summary/new_code?id=thischwa_CloudflareDNS-java)
|
[](https://sonarcloud.io/summary/new_code?id=th-schwarz_CloudflareDNS-java)
|
||||||
[](https://sonarcloud.io/summary/new_code?id=thischwa_CloudflareDNS-java)
|
[](https://sonarcloud.io/summary/new_code?id=th-schwarz_CloudflareDNS-java)
|
||||||
[](https://sonarcloud.io/summary/new_code?id=thischwa_CloudflareDNS-java)
|
[](https://sonarcloud.io/summary/new_code?id=th-schwarz_CloudflareDNS-java)
|
||||||
[](https://sonarcloud.io/summary/new_code?id=thischwa_CloudflareDNS-java)
|
[](https://sonarcloud.io/summary/new_code?id=th-schwarz_CloudflareDNS-java)
|
||||||
[](https://sonarcloud.io/summary/new_code?id=thischwa_CloudflareDNS-java)
|
[](https://sonarcloud.io/summary/new_code?id=th-schwarz_CloudflareDNS-java)
|
||||||
|
|
||||||
|
[](https://codeberg.org/th-schwarz/CloudflareDNS-java)
|
||||||
|
|
||||||
## Preface
|
## Preface
|
||||||
|
|
||||||
@@ -15,7 +16,7 @@ This project provides a java client for minimalistic access to the Cloudflare AP
|
|||||||
managing DNS settings such as creating, updating and deleting DNS records.
|
managing DNS settings such as creating, updating and deleting DNS records.
|
||||||
|
|
||||||
If you encounter any bugs or find missing features, feel free to report them on
|
If you encounter any bugs or find missing features, feel free to report them on
|
||||||
the [GitLab Issues page](https://gitlab.com/th-schwarz/CloudflareDNS-java/-/issues).
|
the [Codeberg Issues page](https://codeberg.org/th-schwarz/CloudflareDNS-java/issues).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -29,11 +30,11 @@ This guide comes without any warranty. Use at your own risk. The author is not r
|
|||||||
|
|
||||||
The project has its own maven repository. It can be added to the `pom.xml`:
|
The project has its own maven repository. It can be added to the `pom.xml`:
|
||||||
|
|
||||||
```xml<p>
|
```xml
|
||||||
<repositories>
|
<repositories>
|
||||||
<repository>
|
<repository>
|
||||||
<id>gitlab-cloudflare</id>
|
<id>gitea</id>
|
||||||
<url>https://gitlab.com/api/v4/projects/68509751/packages/maven</url>
|
<url>https://codeberg.org/api/packages/th-schwarz/maven</url>
|
||||||
</repository>
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
```
|
```
|
||||||
@@ -49,7 +50,10 @@ The dependency is:
|
|||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
- 0.3.0-SNAPSHOT:
|
- 0.4.0-SNAPSHOT:
|
||||||
|
- **Breaking Change**: renamed `client.zone().record()` to `client.zone().getRecord()`
|
||||||
|
- Code quality improvements: Increasing test coverage
|
||||||
|
- 0.3.0:
|
||||||
- **Breaking Change**:
|
- **Breaking Change**:
|
||||||
- **New Fluent API**: Changed the initialization of the client(`new CfDnsClientBuilder().withApiTokenAuth("your-api-token").build()`)
|
- **New Fluent API**: Changed the initialization of the client(`new CfDnsClientBuilder().withApiTokenAuth("your-api-token").build()`)
|
||||||
- Authentication with API token.
|
- Authentication with API token.
|
||||||
@@ -61,7 +65,7 @@ The dependency is:
|
|||||||
- RecordEntity getter methods renamed for clarity: `getName()` → `getSld()`
|
- RecordEntity getter methods renamed for clarity: `getName()` → `getSld()`
|
||||||
- **New Fluent API**: Changed the initialization of the client(`new CfDnsClientBuilder().withApiTokenAuth("your-api-token").build()`) and added chainable method interface for more readable DNS operations (
|
- **New Fluent API**: Changed the initialization of the client(`new CfDnsClientBuilder().withApiTokenAuth("your-api-token").build()`) and added chainable method interface for more readable DNS operations (
|
||||||
`client.zone().record()...`)
|
`client.zone().record()...`)
|
||||||
- Code quality improvements: eliminated duplication in batch operations, improved type safety in HTTP methods,
|
- Code quality improvements: removed duplication in batch operations, improved type safety in HTTP methods,
|
||||||
optimized string concatenation, removed mutable setters from CfDnsClient
|
optimized string concatenation, removed mutable setters from CfDnsClient
|
||||||
- Enhanced type validation in `RecordEntity.build()` with better error messages
|
- Enhanced type validation in `RecordEntity.build()` with better error messages
|
||||||
- CfClient#recordList must return multiple RecordEntries
|
- CfClient#recordList must return multiple RecordEntries
|
||||||
@@ -366,7 +370,7 @@ that reduces verbosity and improves code readability.
|
|||||||
### Basic Usage
|
### Basic Usage
|
||||||
|
|
||||||
```java
|
```java
|
||||||
// Create a DNS record
|
// Create a DNS getRecord
|
||||||
client.zone("example.com")
|
client.zone("example.com")
|
||||||
.record("api")
|
.record("api")
|
||||||
.create(RecordType.A, "192.168.1.1",60);
|
.create(RecordType.A, "192.168.1.1",60);
|
||||||
@@ -380,7 +384,7 @@ List<RecordEntity> records = client.zone("example.com")
|
|||||||
List<RecordEntity> zoneRecords = client.zone("example.com")
|
List<RecordEntity> zoneRecords = client.zone("example.com")
|
||||||
.list(RecordType.A, RecordType.AAAA);
|
.list(RecordType.A, RecordType.AAAA);
|
||||||
|
|
||||||
// Update a DNS record
|
// Update a DNS getRecord
|
||||||
RecordEntity updated = client.zone("example.com")
|
RecordEntity updated = client.zone("example.com")
|
||||||
.record("api", RecordType.A)
|
.record("api", RecordType.A)
|
||||||
.update("192.168.1.2");
|
.update("192.168.1.2");
|
||||||
@@ -405,7 +409,7 @@ CfDnsClient client = new CfDnsClientBuilder()
|
|||||||
.withApiTokenAuth("your-api-token")
|
.withApiTokenAuth("your-api-token")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// Create a new record
|
// Create a new getRecord
|
||||||
client.zone("example.com")
|
client.zone("example.com")
|
||||||
.record("api")
|
.record("api")
|
||||||
.create(RecordType.A, "192.168.100.1",60);
|
.create(RecordType.A, "192.168.100.1",60);
|
||||||
@@ -416,7 +420,7 @@ List<RecordEntity> records = client.zone("example.com")
|
|||||||
.get();
|
.get();
|
||||||
System.out.println("IP: "+records.get(0).getContent());
|
System.out.println("IP: "+records.get(0).getContent());
|
||||||
|
|
||||||
// Update the record
|
// Update the getRecord
|
||||||
client.zone("example.com")
|
client.zone("example.com")
|
||||||
.record("api",RecordType.A)
|
.record("api",RecordType.A)
|
||||||
.update("192.168.100.2");
|
.update("192.168.100.2");
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
@@ -4,14 +4,14 @@
|
|||||||
|
|
||||||
<groupId>codes.thischwa</groupId>
|
<groupId>codes.thischwa</groupId>
|
||||||
<artifactId>cloudflaredns</artifactId>
|
<artifactId>cloudflaredns</artifactId>
|
||||||
<version>0.3.0</version>
|
<version>0.4.0</version>
|
||||||
<name>CloudflareDNS-java</name>
|
<name>CloudflareDNS-java</name>
|
||||||
<inceptionYear>2025</inceptionYear>
|
<inceptionYear>2025</inceptionYear>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<issueManagement>
|
<issueManagement>
|
||||||
<url>https://gitlab.com/th-schwarz/CloudflareDNS-java/-/issues</url>
|
<url>https://codeberg.org/th-schwarz/CloudflareDNS-java/issues</url>
|
||||||
<system>GitLab Issues</system>
|
<system>Codeberg Issues</system>
|
||||||
</issueManagement>
|
</issueManagement>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
@@ -34,11 +34,11 @@
|
|||||||
<linkXRef>false</linkXRef>
|
<linkXRef>false</linkXRef>
|
||||||
|
|
||||||
<!-- 3rd party dependencies -->
|
<!-- 3rd party dependencies -->
|
||||||
<jackson.version>2.19.1</jackson.version>
|
<jackson.version>2.21.1</jackson.version>
|
||||||
<httpclient5.version>5.5.1</httpclient5.version>
|
<httpclient5.version>5.5.1</httpclient5.version>
|
||||||
<lombok.version>1.18.36</lombok.version>
|
<lombok.version>1.18.36</lombok.version>
|
||||||
<slf4j.version>2.0.17</slf4j.version>
|
<slf4j.version>2.0.17</slf4j.version>
|
||||||
<logback-classic.version>1.5.18</logback-classic.version>
|
<logback-classic.version>1.5.25</logback-classic.version>
|
||||||
<junit5.version>5.14.2</junit5.version>
|
<junit5.version>5.14.2</junit5.version>
|
||||||
<mockito-junit5.version>5.21.0</mockito-junit5.version>
|
<mockito-junit5.version>5.21.0</mockito-junit5.version>
|
||||||
|
|
||||||
@@ -55,24 +55,27 @@
|
|||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<scm>
|
<scm>
|
||||||
<developerConnection>scm:git:git@gitlab.com:th-schwarz/CloudflareDNS-java.git</developerConnection>
|
<developerConnection>scm:git:git@codeberg.org:th-schwarz/CloudflareDNS-java.git</developerConnection>
|
||||||
<connection>scm:git:git@gitlab.com:th-schwarz/CloudflareDNS-java.git</connection>
|
<connection>scm:git:git@codeberg.org:th-schwarz/CloudflareDNS-java.git</connection>
|
||||||
<url>https://gitlab.com/th-schwarz/CloudflareDNS-java</url>
|
<url>https://codeberg.org/th-schwarz/CloudflareDNS-java</url>
|
||||||
<tag>v0.3.0</tag>
|
<tag>v0.4.0</tag>
|
||||||
</scm>
|
</scm>
|
||||||
|
|
||||||
<distributionManagement>
|
<distributionManagement>
|
||||||
<repository>
|
<repository>
|
||||||
<id>gitlab-cloudflaredns</id>
|
<id>codeberg-cloudflaredns</id>
|
||||||
<name>GitLab Maven Packages</name>
|
<url>https://codeberg.org/api/packages/th-schwarz/maven</url>
|
||||||
<url>https://gitlab.com/api/v4/projects/68509751/packages/maven</url>
|
|
||||||
<releases>
|
<releases>
|
||||||
<enabled>true</enabled>
|
<enabled>true</enabled>
|
||||||
</releases>
|
</releases>
|
||||||
<snapshots>
|
|
||||||
<enabled>false</enabled>
|
|
||||||
</snapshots>
|
|
||||||
</repository>
|
</repository>
|
||||||
|
<snapshotRepository>
|
||||||
|
<id>codeberg-cloudflaredns</id>
|
||||||
|
<url>https://codeberg.org/api/packages/th-schwarz/maven</url>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</snapshotRepository>
|
||||||
</distributionManagement>
|
</distributionManagement>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@@ -154,6 +157,7 @@
|
|||||||
<version>3.11.2</version>
|
<version>3.11.2</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<failOnError>false</failOnError>
|
<failOnError>false</failOnError>
|
||||||
|
<failOnWarnings>false</failOnWarnings>
|
||||||
<locale>en</locale>
|
<locale>en</locale>
|
||||||
<source>${java.version}</source>
|
<source>${java.version}</source>
|
||||||
</configuration>
|
</configuration>
|
||||||
@@ -278,7 +282,6 @@
|
|||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</project>
|
</project>
|
||||||
@@ -33,6 +33,9 @@ abstract class CfBasicHttpClient {
|
|||||||
private final CfDnsClientBuilder.CfAuth auth;
|
private final CfDnsClientBuilder.CfAuth auth;
|
||||||
private final ObjectMapper objectMapper;
|
private final ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
private record ResultWrapper(int statusCode, String responseBody) {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new Cloudflare HTTP client with the specified base URL and authentication.
|
* Creates a new Cloudflare HTTP client with the specified base URL and authentication.
|
||||||
*
|
*
|
||||||
@@ -97,7 +100,7 @@ abstract class CfBasicHttpClient {
|
|||||||
log.error("JSON parsing error for request to {}", logUri, e);
|
log.error("JSON parsing error for request to {}", logUri, e);
|
||||||
throw new CloudflareApiException("Error processing JSON response", e);
|
throw new CloudflareApiException("Error processing JSON response", e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new CloudflareApiException("Server error!", e);
|
throw new CloudflareApiException("Unexpected error!", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,7 +190,4 @@ abstract class CfBasicHttpClient {
|
|||||||
private String buildUrl(String endpoint) {
|
private String buildUrl(String endpoint) {
|
||||||
return baseUrl + endpoint;
|
return baseUrl + endpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
private record ResultWrapper(int statusCode, String responseBody) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,14 +116,14 @@ public class CfDnsClient extends CfBasicHttpClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides fluent API access to operations on a specific zone.
|
* Provides fluent API access to operations in a specific zone.
|
||||||
* This method returns a ZoneOperations interface that allows chaining operations
|
* This method returns a ZoneOperations interface that allows chaining operations
|
||||||
* on DNS records within the specified zone.
|
* on DNS records within the specified zone.
|
||||||
*
|
*
|
||||||
* <p>Example:
|
* <p>Example:
|
||||||
* <pre><code>
|
* <pre><code>
|
||||||
* client.zone("example.com")
|
* client.zone("example.com")
|
||||||
* .record("api")
|
* .getRecord("api")
|
||||||
* .create(RecordType.A, "192.168.1.1", 60);
|
* .create(RecordType.A, "192.168.1.1", 60);
|
||||||
* </code></pre>
|
* </code></pre>
|
||||||
*
|
*
|
||||||
@@ -177,6 +177,33 @@ public class CfDnsClient extends CfBasicHttpClient {
|
|||||||
return response.getResult().get(0);
|
return response.getResult().get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a list of DNS records for a specified zone, with optional paging support.
|
||||||
|
*
|
||||||
|
* @param zone The zone entity containing information about the target zone.
|
||||||
|
* @return A list of RecordEntity objects representing the DNS records of the specified zone.
|
||||||
|
* @throws CloudflareApiException If an error occurs during the API request or response processing.
|
||||||
|
*/
|
||||||
|
public List<RecordEntity> recordList(ZoneEntity zone) throws CloudflareApiException {
|
||||||
|
return recordList(zone, (PagingRequest) null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a list of DNS records for a specified zone, with optional paging support.
|
||||||
|
*
|
||||||
|
* @param zone The zone entity containing information about the target zone.
|
||||||
|
* @param pagingRequest The paging request containing parameters such as page size and number.
|
||||||
|
* @return A list of RecordEntity objects representing the DNS records of the specified zone.
|
||||||
|
* @throws CloudflareApiException If an error occurs during the API request or response processing.
|
||||||
|
*/
|
||||||
|
public List<RecordEntity> recordList(ZoneEntity zone, @Nullable PagingRequest pagingRequest) throws CloudflareApiException {
|
||||||
|
PagingRequest pr = pagingRequest == null ? PagingRequest.defaultPaging() : pagingRequest;
|
||||||
|
String endpoint = pr.addQueryString(CfRequest.RECORD_LIST.buildPath(zone.getId()));
|
||||||
|
RecordMultipleResponse resp = getRequest(endpoint, RecordMultipleResponse.class);
|
||||||
|
checkResponse(resp);
|
||||||
|
return resp.getResult();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves DNS records for the specified second-level domain (SLD) within a zone.
|
* Retrieves DNS records for the specified second-level domain (SLD) within a zone.
|
||||||
*
|
*
|
||||||
@@ -192,49 +219,31 @@ public class CfDnsClient extends CfBasicHttpClient {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves DNS records for the specified second-level domain (SLD) within a zone.
|
* Retrieves DNS records for the specified second-level domain (SLD) within a zone.
|
||||||
* Optionally filters by one or more DNS record types.
|
* Optionally, filters by one or more DNS getRecord types.
|
||||||
*
|
*
|
||||||
* @param zone The zone entity containing information about the domain zone.
|
* @param zone The zone entity containing information about the domain zone.
|
||||||
* @param sld The second-level domain (SLD) for which to retrieve DNS records.
|
* @param sld The second-level domain (SLD) for which to retrieve DNS records.
|
||||||
* @param types Optional parameter specifying one or more DNS record types to filter the results.
|
* @param types Optional parameter specifying one or more DNS getRecord types to filter the results.
|
||||||
* @return A list of {@code RecordEntity} objects representing the DNS records for the specified domain.
|
* @return A list of {@code RecordEntity} objects representing the DNS records for the specified domain.
|
||||||
* @throws CloudflareNotFoundException if the specified SLD is not found in the zone
|
* @throws CloudflareNotFoundException if the specified SLD is not found in the zone
|
||||||
* @throws CloudflareApiException if an error occurs while interacting with the Cloudflare API
|
* @throws CloudflareApiException if an error occurs while interacting with the Cloudflare API
|
||||||
*/
|
*/
|
||||||
public List<RecordEntity> recordList(ZoneEntity zone, String sld, @Nullable RecordType... types)
|
public List<RecordEntity> recordList(ZoneEntity zone, String sld, @Nullable RecordType... types)
|
||||||
throws CloudflareApiException {
|
throws CloudflareApiException {
|
||||||
PagingRequest pagingRequest = PagingRequest.defaultPaging();
|
|
||||||
List<RecordEntity> recs = recordList(zone, sld, pagingRequest);
|
|
||||||
return filterAndSetZoneRecords(zone, types, recs);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves all record entities for a specific second-level domain (SLD) within a given DNS
|
|
||||||
* zone using the provided paging request parameters.
|
|
||||||
*
|
|
||||||
* @param zone The DNS zone entity for which the SLD records are to be fetched.
|
|
||||||
* @param sld The second-level domain name for which the records are retrieved.
|
|
||||||
* @param pagingRequest The paging request.
|
|
||||||
* @return A list of {@code RecordEntity} associated with the desired SLD.
|
|
||||||
* @throws CloudflareApiException If an error occurs while interacting with the Cloudflare API.
|
|
||||||
*/
|
|
||||||
public List<RecordEntity> recordList(ZoneEntity zone, String sld, PagingRequest pagingRequest)
|
|
||||||
throws CloudflareApiException {
|
|
||||||
String fqdn = buildFqdn(zone, sld);
|
String fqdn = buildFqdn(zone, sld);
|
||||||
String endpoint =
|
String endpoint = CfRequest.RECORD_LIST_NAME.buildPath(zone.getId(), fqdn);
|
||||||
pagingRequest.addQueryString(CfRequest.RECORD_INFO_NAME.buildPath(zone.getId(), fqdn));
|
|
||||||
RecordMultipleResponse resp = getRequest(endpoint, RecordMultipleResponse.class);
|
RecordMultipleResponse resp = getRequest(endpoint, RecordMultipleResponse.class);
|
||||||
checkResponse(resp);
|
checkResponse(resp, false);
|
||||||
return resp.getResult();
|
List<RecordEntity> recs = resp.getResult();
|
||||||
|
return filterAndSetZoneRecords(zone, types, recs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves a list of all DNS records for a given zone.
|
* Retrieves a list of all DNS records for a given zone.
|
||||||
* Optionally filters by one or more DNS record types.
|
* Optionally, filters by one or more DNS getRecord types.
|
||||||
*
|
*
|
||||||
* @param zone The zone entity containing information about the domain zone.
|
* @param zone The zone entity containing information about the domain zone.
|
||||||
* @param types Optional parameter specifying one or more DNS record types to filter the results.
|
* @param types Optional parameter specifying one or more DNS getRecord types to filter the results.
|
||||||
* @return A list of {@code RecordEntity} objects representing the DNS records for the specified zone.
|
* @return A list of {@code RecordEntity} objects representing the DNS records for the specified zone.
|
||||||
* @throws CloudflareApiException if an error occurs while interacting with the Cloudflare API
|
* @throws CloudflareApiException if an error occurs while interacting with the Cloudflare API
|
||||||
*/
|
*/
|
||||||
@@ -248,17 +257,17 @@ public class CfDnsClient extends CfBasicHttpClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new DNS record for a given second-level domain (SLD) within the specified zone.
|
* Creates a new DNS getRecord for a given second-level domain (SLD) within the specified zone.
|
||||||
*
|
*
|
||||||
* @param zone The ZoneEntity representing the DNS zone where the record is to be created.
|
* @param zone The ZoneEntity representing the DNS zone where the getRecord is to be created.
|
||||||
* @param sld The second-level domain (SLD) for which the DNS record is being created.
|
* @param sld The second-level domain (SLD) for which the DNS getRecord is being created.
|
||||||
* @param ttl The time-to-live (TTL) value for the DNS record in seconds.
|
* @param ttl The time-to-live (TTL) value for the DNS getRecord in seconds.
|
||||||
* @param type The RecordType specifying the type of the DNS record (e.g., A, AAAA, CNAME).
|
* @param type The RecordType specifying the type of the DNS getRecord (e.g., A, AAAA, CNAME).
|
||||||
* @param content The content of the DNS record (e.g., IP address for A/AAAA records, target
|
* @param content The content of the DNS getRecord (e.g., IP address for A/AAAA records, target
|
||||||
* domain for CNAME).
|
* domain for CNAME).
|
||||||
* @return The created RecordEntity object containing details of the newly created DNS record.
|
* @return The created RecordEntity object containing details of the newly created DNS getRecord.
|
||||||
* @throws CloudflareApiException If an error occurs while communicating with the Cloudflare API
|
* @throws CloudflareApiException If an error occurs while communicating with the Cloudflare API
|
||||||
* or creating the record.
|
* or creating the getRecord.
|
||||||
*/
|
*/
|
||||||
public RecordEntity recordCreateSld(ZoneEntity zone, String sld, int ttl, RecordType type,
|
public RecordEntity recordCreateSld(ZoneEntity zone, String sld, int ttl, RecordType type,
|
||||||
String content) throws CloudflareApiException {
|
String content) throws CloudflareApiException {
|
||||||
@@ -267,14 +276,14 @@ public class CfDnsClient extends CfBasicHttpClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a DNS record in the specified DNS zone with the provided details.
|
* Creates a DNS getRecord in the specified DNS zone with the provided details.
|
||||||
*
|
*
|
||||||
* @param zone the DNS zone in which the record will be created
|
* @param zone the DNS zone in which the getRecord will be created
|
||||||
* @param name the name of the DNS record (e.g., www.example.com)
|
* @param name the name of the DNS getRecord (e.g., www.example.com)
|
||||||
* @param ttl the time-to-live (TTL) value for the DNS record
|
* @param ttl the time-to-live (TTL) value for the DNS getRecord
|
||||||
* @param type the type of the DNS record (e.g., A, AAAA, CNAME)
|
* @param type the type of the DNS getRecord (e.g., A, AAAA, CNAME)
|
||||||
* @param content the content or value of the DNS record
|
* @param content the content or value of the DNS getRecord
|
||||||
* @return the created DNS record as a {@link RecordEntity} object
|
* @return the created DNS getRecord as a {@link RecordEntity} object
|
||||||
* @throws CloudflareApiException if an error occurs while interacting with the Cloudflare API
|
* @throws CloudflareApiException if an error occurs while interacting with the Cloudflare API
|
||||||
*/
|
*/
|
||||||
public RecordEntity recordCreate(ZoneEntity zone, String name, int ttl, RecordType type,
|
public RecordEntity recordCreate(ZoneEntity zone, String name, int ttl, RecordType type,
|
||||||
@@ -284,13 +293,13 @@ public class CfDnsClient extends CfBasicHttpClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new DNS record in the specified zone using the Cloudflare API.
|
* Creates a new DNS getRecord in the specified zone using the Cloudflare API.
|
||||||
*
|
*
|
||||||
* @param zone The zone entity where the record will be created. Contains details such as zone
|
* @param zone The zone entity where the getRecord will be created. Contains details such as zone
|
||||||
* ID.
|
* ID.
|
||||||
* @param rec The record entity representing the DNS record to be created, including its
|
* @param rec The getRecord entity representing the DNS getRecord to be created, including its
|
||||||
* attributes.
|
* attributes.
|
||||||
* @return The created record entity as returned by the Cloudflare API.
|
* @return The created getRecord entity as returned by the Cloudflare API.
|
||||||
* @throws CloudflareApiException If an error occurs while interacting with the Cloudflare API.
|
* @throws CloudflareApiException If an error occurs while interacting with the Cloudflare API.
|
||||||
*/
|
*/
|
||||||
public RecordEntity recordCreate(ZoneEntity zone, RecordEntity rec)
|
public RecordEntity recordCreate(ZoneEntity zone, RecordEntity rec)
|
||||||
@@ -305,11 +314,11 @@ public class CfDnsClient extends CfBasicHttpClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes a DNS record of the specified type within a given zone on the Cloudflare API.
|
* Deletes a DNS getRecord of the specified type within a given zone on the Cloudflare API.
|
||||||
*
|
*
|
||||||
* @param zone The zone entity that specifies the zone in which the record exists.
|
* @param zone The zone entity that specifies the zone in which the getRecord exists.
|
||||||
* @param rec The record entity that represents the DNS record to be deleted.
|
* @param rec The getRecord entity that represents the DNS getRecord to be deleted.
|
||||||
* @return {@code true} if the DNS record was successfully deleted; {@code false} otherwise.
|
* @return {@code true} if the DNS getRecord was successfully deleted; {@code false} otherwise.
|
||||||
* @throws CloudflareApiException if there is an issue during the API communication, or the
|
* @throws CloudflareApiException if there is an issue during the API communication, or the
|
||||||
* request fails for any reason.
|
* request fails for any reason.
|
||||||
*/
|
*/
|
||||||
@@ -324,11 +333,11 @@ public class CfDnsClient extends CfBasicHttpClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes a DNS record of the specified type within a given zone on the Cloudflare API.
|
* Deletes a DNS getRecord of the specified type within a given zone on the Cloudflare API.
|
||||||
*
|
*
|
||||||
* @param zone The zone entity that specifies the zone in which the record exists.
|
* @param zone The zone entity that specifies the zone in which the getRecord exists.
|
||||||
* @param id The record entity that represents the DNS record to be deleted.
|
* @param id The getRecord entity that represents the DNS getRecord to be deleted.
|
||||||
* @return {@code true} if the DNS record was successfully deleted; {@code false} otherwise.
|
* @return {@code true} if the DNS getRecord was successfully deleted; {@code false} otherwise.
|
||||||
* @throws CloudflareApiException if there is an issue during the API communication or the request
|
* @throws CloudflareApiException if there is an issue during the API communication or the request
|
||||||
* fails for any reason.
|
* fails for any reason.
|
||||||
*/
|
*/
|
||||||
@@ -341,12 +350,12 @@ public class CfDnsClient extends CfBasicHttpClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates an existing DNS record in a specified Cloudflare zone.
|
* Updates an existing DNS getRecord in a specified Cloudflare zone.
|
||||||
*
|
*
|
||||||
* @param zone the zone entity containing the ID of the target zone
|
* @param zone the zone entity containing the ID of the target zone
|
||||||
* @param rec the record entity containing the ID of the DNS record to be updated and its updated
|
* @param rec the getRecord entity containing the ID of the DNS getRecord to be updated and its updated
|
||||||
* data
|
* data
|
||||||
* @return the updated record entity as returned by the Cloudflare API
|
* @return the updated getRecord entity as returned by the Cloudflare API
|
||||||
* @throws CloudflareApiException if an error occurs while interacting with the Cloudflare API
|
* @throws CloudflareApiException if an error occurs while interacting with the Cloudflare API
|
||||||
*/
|
*/
|
||||||
public RecordEntity recordUpdate(ZoneEntity zone, RecordEntity rec)
|
public RecordEntity recordUpdate(ZoneEntity zone, RecordEntity rec)
|
||||||
@@ -362,11 +371,11 @@ public class CfDnsClient extends CfBasicHttpClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes DNS records of a specific type within a given zone if they exist. If no record of the
|
* Deletes DNS records of a specific type within a given zone if they exist. If no getRecord of the
|
||||||
* specified type exists, it logs this occurrence without throwing an exception.
|
* specified type exists, it logs this occurrence without throwing an exception.
|
||||||
*
|
*
|
||||||
* @param zone The DNS zone entity in which the record exists.
|
* @param zone The DNS zone entity in which the getRecord exists.
|
||||||
* @param sld The second-level domain for which the record is being checked.
|
* @param sld The second-level domain for which the getRecord is being checked.
|
||||||
* @param recordTypes The types of DNS records that should be deleted if they exist.
|
* @param recordTypes The types of DNS records that should be deleted if they exist.
|
||||||
* @throws CloudflareApiException If an error occurs during API communication.
|
* @throws CloudflareApiException If an error occurs during API communication.
|
||||||
*/
|
*/
|
||||||
@@ -377,7 +386,7 @@ public class CfDnsClient extends CfBasicHttpClient {
|
|||||||
try {
|
try {
|
||||||
recs = recordList(zone, sld, recordTypes);
|
recs = recordList(zone, sld, recordTypes);
|
||||||
} catch (CloudflareNotFoundException e) {
|
} catch (CloudflareNotFoundException e) {
|
||||||
log.trace("No record of type {} found for domain {}.", recordTypes, fqdn);
|
log.trace("No getRecord of type {} found for domain {}.", recordTypes, fqdn);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (RecordEntity rec : recs) {
|
for (RecordEntity rec : recs) {
|
||||||
@@ -385,13 +394,13 @@ public class CfDnsClient extends CfBasicHttpClient {
|
|||||||
recordDelete(zone, rec);
|
recordDelete(zone, rec);
|
||||||
log.info("Record {} of type {} successful deleted.", fqdn, recordTypes);
|
log.info("Record {} of type {} successful deleted.", fqdn, recordTypes);
|
||||||
} catch (CloudflareApiException e) {
|
} catch (CloudflareApiException e) {
|
||||||
log.error("Failed to delete record {} of type {} for zone {}: {}", fqdn, recordTypes, zone.getName(), e.getMessage());
|
log.error("Failed to delete getRecord {} of type {} for zone {}: {}", fqdn, recordTypes, zone.getName(), e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes a batch of DNS record operations (POST, PUT, PATCH, DELETE) for a specified zone.
|
* Processes a batch of DNS getRecord operations (POST, PUT, PATCH, DELETE) for a specified zone.
|
||||||
* This method builds and cleans the input records, sends the batch request to the Cloudflare API,
|
* This method builds and cleans the input records, sends the batch request to the Cloudflare API,
|
||||||
* and returns a result containing processed batch entries.
|
* and returns a result containing processed batch entries.
|
||||||
*
|
*
|
||||||
@@ -407,7 +416,7 @@ public class CfDnsClient extends CfBasicHttpClient {
|
|||||||
@Nullable List<RecordEntity> patchRecords, @Nullable List<RecordEntity> deleteRecords)
|
@Nullable List<RecordEntity> patchRecords, @Nullable List<RecordEntity> deleteRecords)
|
||||||
throws CloudflareApiException {
|
throws CloudflareApiException {
|
||||||
BatchEntry batchEntry = new BatchEntry();
|
BatchEntry batchEntry = new BatchEntry();
|
||||||
// build 'clean' record entries
|
// build 'clean' getRecord entries
|
||||||
if (postRecords != null) {
|
if (postRecords != null) {
|
||||||
batchEntry.setPosts(cleanRecordsForPostOrPut(postRecords));
|
batchEntry.setPosts(cleanRecordsForPostOrPut(postRecords));
|
||||||
}
|
}
|
||||||
@@ -437,8 +446,7 @@ public class CfDnsClient extends CfBasicHttpClient {
|
|||||||
if (types != null && types.length > 0) {
|
if (types != null && types.length > 0) {
|
||||||
Set<RecordType> allowedTypes = new HashSet<>(Arrays.asList(types));
|
Set<RecordType> allowedTypes = new HashSet<>(Arrays.asList(types));
|
||||||
filtered = recs.stream()
|
filtered = recs.stream()
|
||||||
.filter(rec -> allowedTypes.contains(RecordType.valueOf(rec.getType())))
|
.filter(rec -> allowedTypes.contains(RecordType.valueOf(rec.getType()))).toList();
|
||||||
.collect(Collectors.toList());;
|
|
||||||
} else {
|
} else {
|
||||||
filtered = new ArrayList<>(recs);
|
filtered = new ArrayList<>(recs);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,19 +22,6 @@ public class CfDnsClientBuilder {
|
|||||||
@Nullable
|
@Nullable
|
||||||
private String baseUrl;
|
private String baseUrl;
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new instance of `CfDnsClientBuilder`.
|
|
||||||
*
|
|
||||||
* <p>This class serves as a builder for creating and configuring instances of a CfDnsClient. It provides
|
|
||||||
* a fluent API to set various optional configurations, such as API authentication methods and base
|
|
||||||
* URL, before constructing the client.
|
|
||||||
*
|
|
||||||
* <p>By using this constructor, you can initiate the building process with default settings, which can
|
|
||||||
* later be overridden using the provided builder methods.
|
|
||||||
*/
|
|
||||||
public CfDnsClientBuilder() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures whether an exception should be thrown when an empty result is encountered
|
* Configures whether an exception should be thrown when an empty result is encountered
|
||||||
* during operations performed by the `CfDnsClient`.
|
* during operations performed by the `CfDnsClient`.
|
||||||
|
|||||||
@@ -27,24 +27,23 @@ public enum CfRequest {
|
|||||||
*/
|
*/
|
||||||
RECORD_LIST("/zones/%s/dns_records"),
|
RECORD_LIST("/zones/%s/dns_records"),
|
||||||
/**
|
/**
|
||||||
* Represents the API endpoint path for creating a new DNS record within a specific DNS zone. The
|
* Represents the API endpoint path for retrieving information about a DNS getRecord within a
|
||||||
|
* specific DNS zone by its name. The endpoint path includes placeholders for the zone identifier
|
||||||
|
* and the getRecord name, which need to be provided to construct the complete path.
|
||||||
|
*/
|
||||||
|
RECORD_LIST_NAME("/zones/%s/dns_records?name=%s"),
|
||||||
|
/**
|
||||||
|
* Represents the API endpoint path for creating a new DNS getRecord within a specific DNS zone. The
|
||||||
* endpoint path includes a placeholder for the zone identifier, which needs to be provided to
|
* endpoint path includes a placeholder for the zone identifier, which needs to be provided to
|
||||||
* construct the complete path.
|
* construct the complete path.
|
||||||
*/
|
*/
|
||||||
RECORD_CREATE("/zones/%s/dns_records"),
|
RECORD_CREATE("/zones/%s/dns_records"),
|
||||||
/**
|
/**
|
||||||
* Represents the API endpoint path for retrieving information about a DNS record within a
|
* Represents the API endpoint path for updating an existing DNS getRecord within a specific DNS
|
||||||
* specific DNS zone by its name. The endpoint path includes placeholders for the zone identifier
|
* zone. The endpoint path includes placeholders for the zone identifier and the getRecord
|
||||||
* and the record name, which need to be provided to construct the complete path.
|
|
||||||
*/
|
|
||||||
RECORD_INFO_NAME("/zones/%s/dns_records?name=%s"),
|
|
||||||
/**
|
|
||||||
* Represents the API endpoint path for updating an existing DNS record within a specific DNS
|
|
||||||
* zone. The endpoint path includes placeholders for the zone identifier and the record
|
|
||||||
* identifier, which need to be provided to construct the complete path.
|
* identifier, which need to be provided to construct the complete path.
|
||||||
*/
|
*/
|
||||||
RECORD_UPDATE("/zones/%s/dns_records/%s"),
|
RECORD_UPDATE("/zones/%s/dns_records/%s"),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the API endpoint path for performing batch operations on DNS records within a specific zone.
|
* Represents the API endpoint path for performing batch operations on DNS records within a specific zone.
|
||||||
* The placeholder "%s" in the path is intended to be replaced by a zone identifier.
|
* The placeholder "%s" in the path is intended to be replaced by a zone identifier.
|
||||||
@@ -52,8 +51,8 @@ public enum CfRequest {
|
|||||||
*/
|
*/
|
||||||
RECORD_BATCH("/zones/%s/dns_records/batch"),
|
RECORD_BATCH("/zones/%s/dns_records/batch"),
|
||||||
/**
|
/**
|
||||||
* Represents the API endpoint path for deleting an existing DNS record within a specific DNS
|
* Represents the API endpoint path for deleting an existing DNS getRecord within a specific DNS
|
||||||
* zone. The endpoint path includes placeholders for the zone identifier and the record
|
* zone. The endpoint path includes placeholders for the zone identifier and the getRecord
|
||||||
* identifier, which need to be provided to construct the complete path.
|
* identifier, which need to be provided to construct the complete path.
|
||||||
*/
|
*/
|
||||||
RECORD_DELETE("/zones/%s/dns_records/%s");
|
RECORD_DELETE("/zones/%s/dns_records/%s");
|
||||||
|
|||||||
@@ -18,17 +18,4 @@ public class CloudflareNotFoundException extends CloudflareApiException {
|
|||||||
public CloudflareNotFoundException(String message) {
|
public CloudflareNotFoundException(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new CloudflareNotFoundException with the specified detail message and cause.
|
|
||||||
*
|
|
||||||
* @param message the detail message, which provides additional context about the "not found"
|
|
||||||
* error encountered during interaction with the Cloudflare API.
|
|
||||||
* @param cause the cause of this exception, which is the underlying throwable that triggered this
|
|
||||||
* exception.
|
|
||||||
*/
|
|
||||||
public CloudflareNotFoundException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class JsonConf {
|
|||||||
static ObjectMapper initObjectMapper() {
|
static ObjectMapper initObjectMapper() {
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
mapper.registerModule(new JavaTimeModule());
|
mapper.registerModule(new JavaTimeModule());
|
||||||
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
|
mapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_NULL);
|
||||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||||
mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
|
mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
|
||||||
return mapper;
|
return mapper;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import codes.thischwa.cf.model.RecordType;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fluent interface for record-level operations.
|
* Fluent interface for getRecord-level operations.
|
||||||
* Provides a chainable API for CRUD operations on DNS records.
|
* Provides a chainable API for CRUD operations on DNS records.
|
||||||
*/
|
*/
|
||||||
public interface RecordOperations {
|
public interface RecordOperations {
|
||||||
@@ -20,29 +20,29 @@ public interface RecordOperations {
|
|||||||
List<RecordEntity> get() throws CloudflareApiException;
|
List<RecordEntity> get() throws CloudflareApiException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new DNS record with the specified parameters.
|
* Creates a new DNS getRecord with the specified parameters.
|
||||||
*
|
*
|
||||||
* @param type the DNS record type (e.g., A, AAAA, CNAME)
|
* @param type the DNS getRecord type (e.g., A, AAAA, CNAME)
|
||||||
* @param content the content of the DNS record (e.g., IP address)
|
* @param content the content of the DNS getRecord (e.g., IP address)
|
||||||
* @param ttl the time-to-live value in seconds
|
* @param ttl the time-to-live value in seconds
|
||||||
* @return the created RecordEntity
|
* @return the created RecordEntity
|
||||||
* @throws CloudflareApiException if an error occurs while creating the record
|
* @throws CloudflareApiException if an error occurs while creating the getRecord
|
||||||
*/
|
*/
|
||||||
RecordEntity create(RecordType type, String content, int ttl) throws CloudflareApiException;
|
RecordEntity create(RecordType type, String content, int ttl) throws CloudflareApiException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates an existing DNS record with new content.
|
* Updates an existing DNS getRecord with new content.
|
||||||
*
|
*
|
||||||
* @param newContent the new content for the DNS record
|
* @param newContent the new content for the DNS getRecord
|
||||||
* @return the updated RecordEntity
|
* @return the updated RecordEntity
|
||||||
* @throws CloudflareApiException if an error occurs while updating the record
|
* @throws CloudflareApiException if an error occurs while updating the getRecord
|
||||||
*/
|
*/
|
||||||
RecordEntity update(String newContent) throws CloudflareApiException;
|
RecordEntity update(String newContent) throws CloudflareApiException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes DNS records of the specified types.
|
* Deletes DNS records of the specified types.
|
||||||
*
|
*
|
||||||
* @param types the DNS record types to delete
|
* @param types the DNS getRecord types to delete
|
||||||
* @throws CloudflareApiException if an error occurs while deleting records
|
* @throws CloudflareApiException if an error occurs while deleting records
|
||||||
*/
|
*/
|
||||||
void delete(RecordType... types) throws CloudflareApiException;
|
void delete(RecordType... types) throws CloudflareApiException;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import java.util.List;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of RecordOperations for fluent API access to record-level operations.
|
* Implementation of RecordOperations for fluent API access to getRecord-level operations.
|
||||||
*/
|
*/
|
||||||
public class RecordOperationsImpl implements RecordOperations {
|
public class RecordOperationsImpl implements RecordOperations {
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public interface ZoneOperations {
|
|||||||
* @return a RecordOperations instance for chaining record-specific operations
|
* @return a RecordOperations instance for chaining record-specific operations
|
||||||
* @throws CloudflareApiException if the zone cannot be found or accessed
|
* @throws CloudflareApiException if the zone cannot be found or accessed
|
||||||
*/
|
*/
|
||||||
RecordOperations record(String sld) throws CloudflareApiException;
|
RecordOperations getRecord(String sld) throws CloudflareApiException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects a record with specific types within the zone for further operations.
|
* Selects a record with specific types within the zone for further operations.
|
||||||
@@ -27,7 +27,7 @@ public interface ZoneOperations {
|
|||||||
* @return a RecordOperations instance for chaining record-specific operations
|
* @return a RecordOperations instance for chaining record-specific operations
|
||||||
* @throws CloudflareApiException if the zone cannot be found or accessed
|
* @throws CloudflareApiException if the zone cannot be found or accessed
|
||||||
*/
|
*/
|
||||||
RecordOperations record(String sld, @Nullable RecordType... types) throws CloudflareApiException;
|
RecordOperations getRecord(String sld, @Nullable RecordType... types) throws CloudflareApiException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lists all DNS records within the zone, optionally filtered by types.
|
* Lists all DNS records within the zone, optionally filtered by types.
|
||||||
|
|||||||
@@ -28,12 +28,12 @@ public class ZoneOperationsImpl implements ZoneOperations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RecordOperations record(String sld) throws CloudflareApiException {
|
public RecordOperations getRecord(String sld) throws CloudflareApiException {
|
||||||
return new RecordOperationsImpl(client, zone, sld, null);
|
return new RecordOperationsImpl(client, zone, sld, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RecordOperations record(String sld, @Nullable RecordType... types) throws CloudflareApiException {
|
public RecordOperations getRecord(String sld, @Nullable RecordType... types) throws CloudflareApiException {
|
||||||
return new RecordOperationsImpl(client, zone, sld, types);
|
return new RecordOperationsImpl(client, zone, sld, types);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,24 +6,24 @@
|
|||||||
*
|
*
|
||||||
* <p>Example usage:
|
* <p>Example usage:
|
||||||
* <pre><code>
|
* <pre><code>
|
||||||
* // Create a DNS record
|
* // Create a DNS getRecord
|
||||||
* client.zone("example.com")
|
* client.zone("example.com")
|
||||||
* .record("api")
|
* .getRecord("api")
|
||||||
* .create(RecordType.A, "192.168.1.1", 60);
|
* .create(RecordType.A, "192.168.1.1", 60);
|
||||||
*
|
*
|
||||||
* // Get DNS records
|
* // Get DNS records
|
||||||
* List<RecordEntity> records = client.zone("example.com")
|
* List<RecordEntity> records = client.zone("example.com")
|
||||||
* .record("www", RecordType.A)
|
* .getRecord("www", RecordType.A)
|
||||||
* .get();
|
* .get();
|
||||||
*
|
*
|
||||||
* // Update a DNS record
|
* // Update a DNS getRecord
|
||||||
* client.zone("example.com")
|
* client.zone("example.com")
|
||||||
* .record("api", RecordType.A)
|
* .getRecord("api", RecordType.A)
|
||||||
* .update("192.168.1.2");
|
* .update("192.168.1.2");
|
||||||
*
|
*
|
||||||
* // Delete DNS records
|
* // Delete DNS records
|
||||||
* client.zone("example.com")
|
* client.zone("example.com")
|
||||||
* .record("old-service")
|
* .getRecord("old-service")
|
||||||
* .delete(RecordType.A, RecordType.AAAA);
|
* .delete(RecordType.A, RecordType.AAAA);
|
||||||
* </code></pre>
|
* </code></pre>
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ import lombok.Data;
|
|||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a batch entry containing different types of operations on record entities.
|
* Represents a batch entry containing different types of operations on getRecord entities.
|
||||||
*
|
*
|
||||||
* <p>A BatchEntry groups together collections of operations (patches, posts, puts, and deletes)
|
* <p>A BatchEntry groups together collections of operations (patches, posts, puts, and deletes)
|
||||||
* intended to be performed as part of a single batch process. Each operation corresponds to a specific
|
* intended to be performed as part of a single batch process. Each operation corresponds to a specific
|
||||||
* type of action on DNS record entities.
|
* type of action on DNS getRecord entities.
|
||||||
*
|
*
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li><b>patches</b>: A list of {@link RecordEntity} objects representing partial updates to existing records.
|
* <li><b>patches</b>: A list of {@link RecordEntity} objects representing partial updates to existing records.
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ package codes.thischwa.cf.model;
|
|||||||
*
|
*
|
||||||
* <p>This class is used for API responses where the primary result is a batch entry,
|
* <p>This class is used for API responses where the primary result is a batch entry,
|
||||||
* which includes collections of operations such as patches, posts, puts, and deletes
|
* which includes collections of operations such as patches, posts, puts, and deletes
|
||||||
* performed on DNS record entities.
|
* performed on DNS getRecord entities.
|
||||||
*
|
*
|
||||||
* <p>Extends {@code AbstractSingleResponse} with {@code BatchEntry} as the generic type,
|
* <p>Extends {@code AbstractSingleResponse} with {@code BatchEntry} as the generic type,
|
||||||
* ensuring that the response result is a batch of operations.
|
* ensuring that the response result is a batch of operations.
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public class PagingRequest {
|
|||||||
* Default page size for retrieving all records in a single request.
|
* Default page size for retrieving all records in a single request.
|
||||||
* Set to a very high value to effectively disable pagination when fetching all records.
|
* Set to a very high value to effectively disable pagination when fetching all records.
|
||||||
*/
|
*/
|
||||||
private static final int DEFAULT_ALL_RECORDS_PAGE_SIZE = 5_000_000;
|
private static final int DEFAULT_ALL_RECORDS_PAGE_SIZE = 1000;
|
||||||
|
|
||||||
private int page;
|
private int page;
|
||||||
private int perPage;
|
private int perPage;
|
||||||
@@ -77,7 +77,7 @@ public class PagingRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String queryString(boolean add) {
|
private String queryString(boolean add) {
|
||||||
String qs = "page=" + page + "&perPage=" + perPage;
|
String qs = "page=" + page + "&per_page=" + perPage;
|
||||||
return add ? "&" + qs : "?" + qs;
|
return add ? "&" + qs : "?" + qs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,22 +6,22 @@ import lombok.EqualsAndHashCode;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a DNS record entity within a specific zone.
|
* Represents a DNS getRecord entity within a specific zone.
|
||||||
*
|
*
|
||||||
* <p>Attributes defined in this class include:
|
* <p>Attributes defined in this class include:
|
||||||
*
|
*
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>DNS record type such as "A" or "CNAME".
|
* <li>DNS getRecord type such as "A" or "CNAME".
|
||||||
* <li>Name of the DNS record.
|
* <li>Name of the DNS getRecord.
|
||||||
* <li>Content of the DNS record, such as an IP address.
|
* <li>Content of the DNS getRecord, such as an IP address.
|
||||||
* <li>Flags indicating whether the record is proxiable or proxied.
|
* <li>Flags indicating whether the getRecord is proxiable or proxied.
|
||||||
* <li>TTL (Time-To-Live) for the DNS record.
|
* <li>TTL (Time-To-Live) for the DNS getRecord.
|
||||||
* <li>A locked status to indicate the immutability of the record.
|
* <li>A locked status to indicate the immutability of the getRecord.
|
||||||
* <li>Zone-specific metadata including zone ID and name.
|
* <li>Zone-specific metadata including zone ID and name.
|
||||||
* <li>Timestamps for creation and modification.
|
* <li>Timestamps for creation and modification.
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* <p>Provides a static factory method {@code build} for creating a DNS record with specific
|
* <p>Provides a static factory method {@code build} for creating a DNS getRecord with specific
|
||||||
* attributes.
|
* attributes.
|
||||||
*/
|
*/
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@@ -45,7 +45,7 @@ public class RecordEntity extends AbstractEntity {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a new instance of the RecordEntity class and invokes the parent constructor from
|
* Initializes a new instance of the RecordEntity class and invokes the parent constructor from
|
||||||
* the AbstractEntity class. The RecordEntity class represents a DNS record entity within a
|
* the AbstractEntity class. The RecordEntity class represents a DNS getRecord entity within a
|
||||||
* specific zone, encapsulating attributes such as type, name, content, TTL, and other related
|
* specific zone, encapsulating attributes such as type, name, content, TTL, and other related
|
||||||
* metadata.
|
* metadata.
|
||||||
*/
|
*/
|
||||||
@@ -56,10 +56,10 @@ public class RecordEntity extends AbstractEntity {
|
|||||||
/**
|
/**
|
||||||
* Builds and returns a {@link RecordEntity} instance with the specified attributes.
|
* Builds and returns a {@link RecordEntity} instance with the specified attributes.
|
||||||
*
|
*
|
||||||
* @param name the name of the DNS record
|
* @param name the name of the DNS getRecord
|
||||||
* @param type the {@link RecordType} of the DNS record
|
* @param type the {@link RecordType} of the DNS getRecord
|
||||||
* @param ttl the time-to-live (TTL) value for the DNS record
|
* @param ttl the time-to-live (TTL) value for the DNS getRecord
|
||||||
* @param content the content of the DNS record, typically an IP address
|
* @param content the content of the DNS getRecord, typically an IP address
|
||||||
* @return a {@link RecordEntity} populated with the provided attributes
|
* @return a {@link RecordEntity} populated with the provided attributes
|
||||||
*/
|
*/
|
||||||
public static RecordEntity build(String name, RecordType type, Integer ttl, String content) {
|
public static RecordEntity build(String name, RecordType type, Integer ttl, String content) {
|
||||||
@@ -74,8 +74,8 @@ public class RecordEntity extends AbstractEntity {
|
|||||||
/**
|
/**
|
||||||
* Builds and returns a {@link RecordEntity} instance with the specified ID and content.
|
* Builds and returns a {@link RecordEntity} instance with the specified ID and content.
|
||||||
*
|
*
|
||||||
* @param id the unique identifier for the DNS record
|
* @param id the unique identifier for the DNS getRecord
|
||||||
* @param content the content of the DNS record, typically an IP address or other record data
|
* @param content the content of the DNS getRecord, typically an IP address or other getRecord data
|
||||||
* @return a {@link RecordEntity} populated with the provided ID and content
|
* @return a {@link RecordEntity} populated with the provided ID and content
|
||||||
*/
|
*/
|
||||||
public static RecordEntity build(String id, String content) {
|
public static RecordEntity build(String id, String content) {
|
||||||
@@ -88,11 +88,11 @@ public class RecordEntity extends AbstractEntity {
|
|||||||
/**
|
/**
|
||||||
* Builds and returns a {@link RecordEntity} instance with the specified attributes.
|
* Builds and returns a {@link RecordEntity} instance with the specified attributes.
|
||||||
*
|
*
|
||||||
* @param id the unique identifier for the DNS record
|
* @param id the unique identifier for the DNS getRecord
|
||||||
* @param name the name of the DNS record
|
* @param name the name of the DNS getRecord
|
||||||
* @param type the type of the DNS record, represented as a string (e.g., "A", "CNAME")
|
* @param type the type of the DNS getRecord, represented as a string (e.g., "A", "CNAME")
|
||||||
* @param ttl the time-to-live (TTL) value for the DNS record
|
* @param ttl the time-to-live (TTL) value for the DNS getRecord
|
||||||
* @param content the content of the DNS record, typically an IP address or other record data
|
* @param content the content of the DNS getRecord, typically an IP address or other getRecord data
|
||||||
* @return a {@link RecordEntity} populated with the provided attributes
|
* @return a {@link RecordEntity} populated with the provided attributes
|
||||||
* @throws IllegalArgumentException if the type string is not a valid RecordType
|
* @throws IllegalArgumentException if the type string is not a valid RecordType
|
||||||
*/
|
*/
|
||||||
@@ -101,7 +101,7 @@ public class RecordEntity extends AbstractEntity {
|
|||||||
try {
|
try {
|
||||||
recordType = RecordType.valueOf(type);
|
recordType = RecordType.valueOf(type);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
throw new IllegalArgumentException("Invalid record type: " + type + ". Must be one of: "
|
throw new IllegalArgumentException("Invalid getRecord type: " + type + ". Must be one of: "
|
||||||
+ java.util.Arrays.toString(RecordType.values()), e);
|
+ java.util.Arrays.toString(RecordType.values()), e);
|
||||||
}
|
}
|
||||||
RecordEntity rec = new RecordEntity();
|
RecordEntity rec = new RecordEntity();
|
||||||
@@ -114,11 +114,11 @@ public class RecordEntity extends AbstractEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the short name (subdomain) of the DNS record.
|
* Retrieves the short name (subdomain) of the DNS getRecord.
|
||||||
* If the name contains a dot ('.'), only the substring before the first dot is returned.
|
* If the name contains a dot ('.'), only the substring before the first dot is returned.
|
||||||
* This is useful for getting the subdomain part of a fully qualified domain name.
|
* This is useful for getting the subdomain part of a fully qualified domain name.
|
||||||
*
|
*
|
||||||
* @return the short name of the DNS record (substring before the first dot),
|
* @return the short name of the DNS getRecord (substring before the first dot),
|
||||||
* or the full name if no dot is present
|
* or the full name if no dot is present
|
||||||
*/
|
*/
|
||||||
public String getSld() {
|
public String getSld() {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ public class RecordMultipleResponse extends AbstractMultipleResponse<RecordEntit
|
|||||||
/**
|
/**
|
||||||
* Constructs an instance of RecordMultipleResponse.
|
* Constructs an instance of RecordMultipleResponse.
|
||||||
*
|
*
|
||||||
* <p>This class represents a response containing multiple DNS record entities from the
|
* <p>This class represents a response containing multiple DNS getRecord entities from the
|
||||||
* Cloudflare API. It inherits functionality from AbstractMultipleResponse to handle multiple
|
* Cloudflare API. It inherits functionality from AbstractMultipleResponse to handle multiple
|
||||||
* records of type RecordEntity.
|
* records of type RecordEntity.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ public class RecordSingleResponse extends AbstractSingleResponse<RecordEntity> {
|
|||||||
*
|
*
|
||||||
* <p>This constructor initializes the RecordSingleResponse object by invoking the superclass
|
* <p>This constructor initializes the RecordSingleResponse object by invoking the superclass
|
||||||
* constructor. The RecordSingleResponse represents a specific API response structure that
|
* constructor. The RecordSingleResponse represents a specific API response structure that
|
||||||
* encapsulates a single DNS record entity, providing mechanisms to interact with such data in the
|
* encapsulates a single DNS getRecord entity, providing mechanisms to interact with such data in the
|
||||||
* context of the Cloudflare API.
|
* context of the Cloudflare API.
|
||||||
*/
|
*/
|
||||||
public RecordSingleResponse() {
|
public RecordSingleResponse() {
|
||||||
|
|||||||
@@ -3,86 +3,86 @@ package codes.thischwa.cf.model;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enum representing various DNS record types.
|
* Enum representing various DNS getRecord types.
|
||||||
*
|
*
|
||||||
* <p>Each constant in this enum corresponds to a specific DNS record type, such as "A", "AAAA",
|
* <p>Each constant in this enum corresponds to a specific DNS getRecord type, such as "A", "AAAA",
|
||||||
* "CNAME", or "TXT". This enum provides a means to standardize the representation of these record
|
* "CNAME", or "TXT". This enum provides a means to standardize the representation of these getRecord
|
||||||
* types throughout the application while allowing easy retrieval of their string representation.
|
* types throughout the application while allowing easy retrieval of their string representation.
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
public enum RecordType {
|
public enum RecordType {
|
||||||
/**
|
/**
|
||||||
* Represents the DNS A record type.
|
* Represents the DNS A getRecord type.
|
||||||
*
|
*
|
||||||
* <p>The "A" record type is used to map a domain name to an IPv4 address.
|
* <p>The "A" getRecord type is used to map a domain name to an IPv4 address.
|
||||||
*/
|
*/
|
||||||
A("A"),
|
A("A"),
|
||||||
/**
|
/**
|
||||||
* Represents the DNS AAAA record type.
|
* Represents the DNS AAAA getRecord type.
|
||||||
*
|
*
|
||||||
* <p>The "AAAA" record type maps a domain name to an IPv6 address.
|
* <p>The "AAAA" getRecord type maps a domain name to an IPv6 address.
|
||||||
*/
|
*/
|
||||||
AAAA("AAAA"),
|
AAAA("AAAA"),
|
||||||
/**
|
/**
|
||||||
* Represents the DNS CAA (Certificate Authority Authorization) record type.
|
* Represents the DNS CAA (Certificate Authority Authorization) getRecord type.
|
||||||
*
|
*
|
||||||
* <p>The "CAA" record type is used to specify which certificate authorities (CAs) are allowed to
|
* <p>The "CAA" getRecord type is used to specify which certificate authorities (CAs) are allowed to
|
||||||
* issue SSL/TLS certificates for a domain.
|
* issue SSL/TLS certificates for a domain.
|
||||||
*/
|
*/
|
||||||
CAA("CAA"),
|
CAA("CAA"),
|
||||||
/**
|
/**
|
||||||
* Represents the DNS CERT record type.
|
* Represents the DNS CERT getRecord type.
|
||||||
*
|
*
|
||||||
* <p>The "CERT" record type is used to store certificates and related certificate revocation
|
* <p>The "CERT" getRecord type is used to store certificates and related certificate revocation
|
||||||
* lists or certificate authority data in DNS zones.
|
* lists or certificate authority data in DNS zones.
|
||||||
*/
|
*/
|
||||||
CERT("CERT"),
|
CERT("CERT"),
|
||||||
/**
|
/**
|
||||||
* Represents the DNS CNAME (Canonical Name) record type.
|
* Represents the DNS CNAME (Canonical Name) getRecord type.
|
||||||
*
|
*
|
||||||
* <p>The "CNAME" record type is used to alias one domain name to another.
|
* <p>The "CNAME" getRecord type is used to alias one domain name to another.
|
||||||
*/
|
*/
|
||||||
CNAME("CNAME"),
|
CNAME("CNAME"),
|
||||||
/**
|
/**
|
||||||
* Represents the DNSKEY record type.
|
* Represents the DNSKEY getRecord type.
|
||||||
*
|
*
|
||||||
* <p>The "DNSKEY" record type is used for storing public keys in DNS, as part of the DNS Security
|
* <p>The "DNSKEY" getRecord type is used for storing public keys in DNS, as part of the DNS Security
|
||||||
* Extensions (DNSSEC). It helps in verifying the authenticity of DNS responses through digital
|
* Extensions (DNSSEC). It helps in verifying the authenticity of DNS responses through digital
|
||||||
* signatures.
|
* signatures.
|
||||||
*/
|
*/
|
||||||
DNSKEY("DNSKEY"),
|
DNSKEY("DNSKEY"),
|
||||||
/**
|
/**
|
||||||
* Represents the DNS DS (Delegation Signer) record type.
|
* Represents the DNS DS (Delegation Signer) getRecord type.
|
||||||
*
|
*
|
||||||
* <p>The "DS" record type is used in the DNSSEC (Domain Name System Security Extensions)
|
* <p>The "DS" getRecord type is used in the DNSSEC (Domain Name System Security Extensions)
|
||||||
* protocol. It contains a hash of a DNSKEY record which is utilized in establishing a chain of
|
* protocol. It contains a hash of a DNSKEY getRecord which is utilized in establishing a chain of
|
||||||
* trust from a parent zone to a child zone.
|
* trust from a parent zone to a child zone.
|
||||||
*/
|
*/
|
||||||
DS("DS"),
|
DS("DS"),
|
||||||
/**
|
/**
|
||||||
* Represents the DNS HTTPS (HTTP Service) record type.
|
* Represents the DNS HTTPS (HTTP Service) getRecord type.
|
||||||
*
|
*
|
||||||
* <p>The "HTTPS" record type is used to specify information about the HTTP/3 and related services
|
* <p>The "HTTPS" getRecord type is used to specify information about the HTTP/3 and related services
|
||||||
* offered by a domain.
|
* offered by a domain.
|
||||||
*/
|
*/
|
||||||
HTTPS("HTTPS"),
|
HTTPS("HTTPS"),
|
||||||
/**
|
/**
|
||||||
* Represents the DNS LOC (Location) record type.
|
* Represents the DNS LOC (Location) getRecord type.
|
||||||
*
|
*
|
||||||
* <p>The "LOC" record type is used to store geographical location information for a domain,
|
* <p>The "LOC" getRecord type is used to store geographical location information for a domain,
|
||||||
* including latitude, longitude, altitude, and other details. It enables associating domains with
|
* including latitude, longitude, altitude, and other details. It enables associating domains with
|
||||||
* physical locations.
|
* physical locations.
|
||||||
*/
|
*/
|
||||||
LOC("LOC"),
|
LOC("LOC"),
|
||||||
/**
|
/**
|
||||||
* Represents the DNS MX (Mail Exchange) record type.
|
* Represents the DNS MX (Mail Exchange) getRecord type.
|
||||||
*
|
*
|
||||||
* <p>The "MX" record type is used to specify the mail servers responsible for receiving email
|
* <p>The "MX" getRecord type is used to specify the mail servers responsible for receiving email
|
||||||
* messages on behalf of a domain.
|
* messages on behalf of a domain.
|
||||||
*/
|
*/
|
||||||
MX("MX"),
|
MX("MX"),
|
||||||
/**
|
/**
|
||||||
* Represents the NAPTR record type for DNS configurations.
|
* Represents the NAPTR getRecord type for DNS configurations.
|
||||||
*
|
*
|
||||||
* <p>This constant is used to specify NAPTR (Naming Authority Pointer) DNS records, which allow
|
* <p>This constant is used to specify NAPTR (Naming Authority Pointer) DNS records, which allow
|
||||||
* for service discovery through flexible DNS-based mechanisms. NAPTR records are commonly used in
|
* for service discovery through flexible DNS-based mechanisms. NAPTR records are commonly used in
|
||||||
@@ -99,7 +99,7 @@ public enum RecordType {
|
|||||||
*/
|
*/
|
||||||
NS("NS"),
|
NS("NS"),
|
||||||
/**
|
/**
|
||||||
* Represents the "OPENPGPKEY" DNS record type.
|
* Represents the "OPENPGPKEY" DNS getRecord type.
|
||||||
*
|
*
|
||||||
* <p>This constant is primarily used to identify DNS records of the type "OPENPGPKEY". It may be
|
* <p>This constant is primarily used to identify DNS records of the type "OPENPGPKEY". It may be
|
||||||
* utilized within the system for operations such as creating, retrieving, updating, or managing
|
* utilized within the system for operations such as creating, retrieving, updating, or managing
|
||||||
@@ -107,17 +107,17 @@ public enum RecordType {
|
|||||||
*/
|
*/
|
||||||
OPENPGPKEY("OPENPGPKEY"),
|
OPENPGPKEY("OPENPGPKEY"),
|
||||||
/**
|
/**
|
||||||
* Represents a DNS record type.
|
* Represents a DNS getRecord type.
|
||||||
*
|
*
|
||||||
* <p>The `PTR` value specifically refers to a "pointer record" in the DNS system, which is
|
* <p>The `PTR` value specifically refers to a "pointer getRecord" in the DNS system, which is
|
||||||
* typically used for reverse DNS lookups.
|
* typically used for reverse DNS lookups.
|
||||||
*/
|
*/
|
||||||
PTR("PTR"),
|
PTR("PTR"),
|
||||||
/**
|
/**
|
||||||
* Represents the SMIMEA DNS record type.
|
* Represents the SMIMEA DNS getRecord type.
|
||||||
*
|
*
|
||||||
* <p>The SMIMEA resource record is used to associate a user's certificate information for email
|
* <p>The SMIMEA resource getRecord is used to associate a user's certificate information for email
|
||||||
* message signing or encryption. This type of DNS record is part of the DNS-based Authentication
|
* message signing or encryption. This type of DNS getRecord is part of the DNS-based Authentication
|
||||||
* of Named Entities (DANE) protocol.
|
* of Named Entities (DANE) protocol.
|
||||||
*
|
*
|
||||||
* <p>SMIMEA records provide a mechanism for utilizing certificates in email communication
|
* <p>SMIMEA records provide a mechanism for utilizing certificates in email communication
|
||||||
@@ -134,41 +134,41 @@ public enum RecordType {
|
|||||||
*/
|
*/
|
||||||
SMIMEA("SMIMEA"),
|
SMIMEA("SMIMEA"),
|
||||||
/**
|
/**
|
||||||
* Represents a service record (SRV) type in the DNS configuration model.
|
* Represents a service getRecord (SRV) type in the DNS configuration model.
|
||||||
*
|
*
|
||||||
* <p>This constant may be used to identify and work with SRV record types in various DNS-related
|
* <p>This constant may be used to identify and work with SRV getRecord types in various DNS-related
|
||||||
* operations or integrations.
|
* operations or integrations.
|
||||||
*/
|
*/
|
||||||
SRV("SRV"),
|
SRV("SRV"),
|
||||||
/**
|
/**
|
||||||
* Represents the DNS record type "SSHFP" (SSH Fingerprint), used in DNS to store cryptographic
|
* Represents the DNS getRecord type "SSHFP" (SSH Fingerprint), used in DNS to store cryptographic
|
||||||
* fingerprints associated with SSH host keys.
|
* fingerprints associated with SSH host keys.
|
||||||
*
|
*
|
||||||
* <p>This DNS record type provides a mechanism for verifying the authenticity of an SSH server
|
* <p>This DNS getRecord type provides a mechanism for verifying the authenticity of an SSH server
|
||||||
* before initiating a connection, enhancing the security of SSH communications.
|
* before initiating a connection, enhancing the security of SSH communications.
|
||||||
*/
|
*/
|
||||||
SSHFP("SSHFP"),
|
SSHFP("SSHFP"),
|
||||||
/**
|
/**
|
||||||
* Represents the Service Binding (SVCB) DNS record type.
|
* Represents the Service Binding (SVCB) DNS getRecord type.
|
||||||
*
|
*
|
||||||
* <p>The SVCB record is a DNS resource record used to indicate alternative endpoints or specific
|
* <p>The SVCB getRecord is a DNS resource getRecord used to indicate alternative endpoints or specific
|
||||||
* configuration details for services. It is commonly applied in service discovery and
|
* configuration details for services. It is commonly applied in service discovery and
|
||||||
* protocol-specific configurations.
|
* protocol-specific configurations.
|
||||||
*/
|
*/
|
||||||
SVCB("SVCB"),
|
SVCB("SVCB"),
|
||||||
/**
|
/**
|
||||||
* Represents a constant for the DNS-based Authentication of Named Entities (DANE) TLSA record
|
* Represents a constant for the DNS-based Authentication of Named Entities (DANE) TLSA getRecord
|
||||||
* type.
|
* type.
|
||||||
*
|
*
|
||||||
* <p>The TLSA record is used to associate a TLS server certificate or public key with the domain
|
* <p>The TLSA getRecord is used to associate a TLS server certificate or public key with the domain
|
||||||
* name (e.g., via DNSSEC). It enables cryptographically secured connections by attaching
|
* name (e.g., via DNSSEC). It enables cryptographically secured connections by attaching
|
||||||
* certificate and key constraints to the specific domain.
|
* certificate and key constraints to the specific domain.
|
||||||
*/
|
*/
|
||||||
TLSA("TLSA"),
|
TLSA("TLSA"),
|
||||||
/**
|
/**
|
||||||
* Represents the TXT DNS record type.
|
* Represents the TXT DNS getRecord type.
|
||||||
*
|
*
|
||||||
* <p>The TXT DNS record type is commonly used to store text-based information for various
|
* <p>The TXT DNS getRecord type is commonly used to store text-based information for various
|
||||||
* verification and configuration purposes, such as domain ownership verification or email
|
* verification and configuration purposes, such as domain ownership verification or email
|
||||||
* authentication protocols (e.g., SPF, DKIM).
|
* authentication protocols (e.g., SPF, DKIM).
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,157 @@
|
|||||||
|
package codes.thischwa.cf;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import codes.thischwa.cf.model.RecordEntity;
|
||||||
|
import codes.thischwa.cf.model.RecordSingleResponse;
|
||||||
|
import codes.thischwa.cf.model.RecordType;
|
||||||
|
import org.apache.hc.client5.http.classic.methods.HttpGet;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for CfBasicHttpClient using mocked HTTP components.
|
||||||
|
* Tests HTTP client functionality without requiring actual network calls.
|
||||||
|
*/
|
||||||
|
class CfBasicHttpClientTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test implementation of CfBasicHttpClient for testing purposes.
|
||||||
|
*/
|
||||||
|
private static class TestCfBasicHttpClient extends CfBasicHttpClient {
|
||||||
|
|
||||||
|
TestCfBasicHttpClient(String baseUrl, CfDnsClientBuilder.CfAuth auth) {
|
||||||
|
super(baseUrl, auth);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expose protected methods for testing
|
||||||
|
public <T extends codes.thischwa.cf.model.AbstractResponse> T testGetRequest(String endpoint, Class<T> responseType)
|
||||||
|
throws CloudflareApiException {
|
||||||
|
return getRequest(endpoint, responseType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends codes.thischwa.cf.model.AbstractResponse> T testPostRequest(String endpoint, Object payload, Class<T> responseType)
|
||||||
|
throws CloudflareApiException {
|
||||||
|
return postRequest(endpoint, payload, responseType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends codes.thischwa.cf.model.AbstractResponse> T testPutRequest(String endpoint, Object payload, Class<T> responseType)
|
||||||
|
throws CloudflareApiException {
|
||||||
|
return putRequest(endpoint, payload, responseType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends codes.thischwa.cf.model.AbstractResponse> T testPatchRequest(String endpoint, Object payload, Class<T> responseType)
|
||||||
|
throws CloudflareApiException {
|
||||||
|
return patchRequest(endpoint, payload, responseType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends codes.thischwa.cf.model.AbstractResponse> T testDeleteRequest(String endpoint, Class<T> responseType)
|
||||||
|
throws CloudflareApiException {
|
||||||
|
return deleteRequest(endpoint, responseType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testConstructor_WithApiToken() {
|
||||||
|
CfDnsClientBuilder.ApiTokenAuth auth = new CfDnsClientBuilder.ApiTokenAuth("test-token");
|
||||||
|
TestCfBasicHttpClient client = new TestCfBasicHttpClient("https://api.cloudflare.com", auth);
|
||||||
|
assertNotNull(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testConstructor_WithEmailKey() {
|
||||||
|
CfDnsClientBuilder.EmailKeyAuth auth = new CfDnsClientBuilder.EmailKeyAuth("test@example.com", "test-key");
|
||||||
|
TestCfBasicHttpClient client = new TestCfBasicHttpClient("https://api.cloudflare.com", auth);
|
||||||
|
assertNotNull(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testApiException_unknowEndpoint() {
|
||||||
|
CfDnsClientBuilder.ApiTokenAuth auth = new CfDnsClientBuilder.ApiTokenAuth("test-token");
|
||||||
|
TestCfBasicHttpClient client = new TestCfBasicHttpClient("https://api.cloudflare.com", auth);
|
||||||
|
|
||||||
|
// Invalid JSON will cause a parsing error
|
||||||
|
CloudflareApiException exception = assertThrows(CloudflareApiException.class, () -> {
|
||||||
|
client.testGetRequest("/invalid-endpoint", RecordSingleResponse.class);
|
||||||
|
});
|
||||||
|
|
||||||
|
assertNotNull(exception);
|
||||||
|
assertTrue(exception.getMessage().contains("Unexpected error"));
|
||||||
|
Throwable cause = exception.getCause();
|
||||||
|
assertInstanceOf(CloudflareApiException.class, cause);
|
||||||
|
assertTrue(cause.getMessage().contains("No route for that URI"), "Expected error message: No route for that URI, but it was: " + cause.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testResultWrapper() throws Exception {
|
||||||
|
// Test the private ResultWrapper record indirectly through client behavior
|
||||||
|
CfDnsClientBuilder.ApiTokenAuth auth = new CfDnsClientBuilder.ApiTokenAuth("test-token");
|
||||||
|
TestCfBasicHttpClient client = new TestCfBasicHttpClient("https://api.cloudflare.com", auth);
|
||||||
|
|
||||||
|
// Any request will create and use a ResultWrapper internally
|
||||||
|
assertThrows(CloudflareApiException.class, () -> {
|
||||||
|
client.testGetRequest("/test", RecordSingleResponse.class);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testAuthApplicationHeader_ApiToken() {
|
||||||
|
CfDnsClientBuilder.ApiTokenAuth auth = new CfDnsClientBuilder.ApiTokenAuth("my-token");
|
||||||
|
HttpGet request = new HttpGet("https://api.cloudflare.com/test");
|
||||||
|
|
||||||
|
auth.applyAuth(request);
|
||||||
|
|
||||||
|
assertTrue(request.containsHeader("Authorization"));
|
||||||
|
assertEquals("Bearer my-token", request.getFirstHeader("Authorization").getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testAuthApplicationHeader_EmailKey() {
|
||||||
|
CfDnsClientBuilder.EmailKeyAuth auth = new CfDnsClientBuilder.EmailKeyAuth("test@example.com", "my-key");
|
||||||
|
HttpGet request = new HttpGet("https://api.cloudflare.com/test");
|
||||||
|
|
||||||
|
auth.applyAuth(request);
|
||||||
|
|
||||||
|
assertTrue(request.containsHeader("X-Auth-Email"));
|
||||||
|
assertTrue(request.containsHeader("X-Auth-Key"));
|
||||||
|
assertEquals("test@example.com", request.getFirstHeader("X-Auth-Email").getValue());
|
||||||
|
assertEquals("my-key", request.getFirstHeader("X-Auth-Key").getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testBaseUrlConstruction() {
|
||||||
|
CfDnsClientBuilder.ApiTokenAuth auth = new CfDnsClientBuilder.ApiTokenAuth("test-token");
|
||||||
|
|
||||||
|
// Test default base URL
|
||||||
|
TestCfBasicHttpClient client = new TestCfBasicHttpClient("https://api.cloudflare.com", auth);
|
||||||
|
assertNotNull(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testObjectMapperInitialization() {
|
||||||
|
// ObjectMapper is initialized in constructor via JsonConf
|
||||||
|
CfDnsClientBuilder.ApiTokenAuth auth = new CfDnsClientBuilder.ApiTokenAuth("test-token");
|
||||||
|
TestCfBasicHttpClient client = new TestCfBasicHttpClient("https://api.cloudflare.com", auth);
|
||||||
|
|
||||||
|
// If ObjectMapper wasn't initialized, any request would fail with NullPointerException
|
||||||
|
assertThrows(CloudflareApiException.class, () -> {
|
||||||
|
client.testGetRequest("/test", RecordSingleResponse.class);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRequestPayloadSerialization() {
|
||||||
|
CfDnsClientBuilder.ApiTokenAuth auth = new CfDnsClientBuilder.ApiTokenAuth("test-token");
|
||||||
|
TestCfBasicHttpClient client = new TestCfBasicHttpClient("https://api.cloudflare.com", auth);
|
||||||
|
|
||||||
|
RecordEntity record = RecordEntity.build("test.example.com", RecordType.A, 300, "1.2.3.4");
|
||||||
|
|
||||||
|
// The payload serialization happens inside postRequest
|
||||||
|
assertThrows(CloudflareApiException.class, () -> {
|
||||||
|
client.testPostRequest("/test", record, RecordSingleResponse.class);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -66,7 +66,7 @@ public class CfClientPenTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Invalid record content and TTL boundaries must be rejected by API")
|
@DisplayName("Invalid getRecord content and TTL boundaries must be rejected by API")
|
||||||
void testInvalidRecordCreateInputsRejected() throws Exception {
|
void testInvalidRecordCreateInputsRejected() throws Exception {
|
||||||
CfDnsClient client = newClient();
|
CfDnsClient client = newClient();
|
||||||
ZoneEntity zone = client.zoneGet(ZONE_STR);
|
ZoneEntity zone = client.zoneGet(ZONE_STR);
|
||||||
@@ -81,11 +81,11 @@ public class CfClientPenTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// A record with invalid IPv4
|
// A getRecord with invalid IPv4
|
||||||
assertThrows(CloudflareApiException.class,
|
assertThrows(CloudflareApiException.class,
|
||||||
() -> client.recordCreate(zone, fqdn, 60, RecordType.A, "999.999.999.999"));
|
() -> client.recordCreate(zone, fqdn, 60, RecordType.A, "999.999.999.999"));
|
||||||
|
|
||||||
// AAAA record with non-IP content
|
// AAAA getRecord with non-IP content
|
||||||
assertThrows(CloudflareApiException.class,
|
assertThrows(CloudflareApiException.class,
|
||||||
() -> client.recordCreate(zone, fqdn, 60, RecordType.AAAA, "not-an-ipv6"));
|
() -> client.recordCreate(zone, fqdn, 60, RecordType.AAAA, "not-an-ipv6"));
|
||||||
|
|
||||||
|
|||||||
@@ -9,14 +9,18 @@ import static org.junit.jupiter.api.Assertions.fail;
|
|||||||
import static org.junit.jupiter.api.Assumptions.assumeTrue;
|
import static org.junit.jupiter.api.Assumptions.assumeTrue;
|
||||||
|
|
||||||
import codes.thischwa.cf.model.BatchEntry;
|
import codes.thischwa.cf.model.BatchEntry;
|
||||||
|
import codes.thischwa.cf.model.PagingRequest;
|
||||||
import codes.thischwa.cf.model.RecordEntity;
|
import codes.thischwa.cf.model.RecordEntity;
|
||||||
import codes.thischwa.cf.model.RecordType;
|
import codes.thischwa.cf.model.RecordType;
|
||||||
import codes.thischwa.cf.model.ZoneEntity;
|
import codes.thischwa.cf.model.ZoneEntity;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@@ -91,6 +95,19 @@ public class CfClientTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testZoneList() throws CloudflareApiException {
|
||||||
|
List<ZoneEntity> zones = client.zoneList();
|
||||||
|
assertNotNull(zones);
|
||||||
|
assertFalse(zones.isEmpty());
|
||||||
|
assertEquals(ZONE_STR, zones.get(0).getName());
|
||||||
|
|
||||||
|
zones = client.zoneList(PagingRequest.of(1, 100));
|
||||||
|
assertNotNull(zones);
|
||||||
|
assertFalse(zones.isEmpty());
|
||||||
|
assertEquals(ZONE_STR, zones.get(0).getName());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testZoneListAnlFailedSldList() throws Exception {
|
void testZoneListAnlFailedSldList() throws Exception {
|
||||||
List<ZoneEntity> zList = client.zoneList();
|
List<ZoneEntity> zList = client.zoneList();
|
||||||
@@ -127,7 +144,7 @@ public class CfClientTest {
|
|||||||
// ensure clean state
|
// ensure clean state
|
||||||
client.recordDeleteTypeIfExists(z, randomSld, RecordType.A, RecordType.AAAA);
|
client.recordDeleteTypeIfExists(z, randomSld, RecordType.A, RecordType.AAAA);
|
||||||
|
|
||||||
// create A record using recordCreate with full domain
|
// create A getRecord using recordCreate with full domain
|
||||||
createdRe1 =
|
createdRe1 =
|
||||||
client.recordCreate(z, RecordEntity.build(domain, RecordType.A, TTL, "130.0.0.3"));
|
client.recordCreate(z, RecordEntity.build(domain, RecordType.A, TTL, "130.0.0.3"));
|
||||||
assertNotNull(createdRe1.getId());
|
assertNotNull(createdRe1.getId());
|
||||||
@@ -146,7 +163,7 @@ public class CfClientTest {
|
|||||||
r = aRecords.get(0);
|
r = aRecords.get(0);
|
||||||
assertEquals("130.0.0.3", r.getContent());
|
assertEquals("130.0.0.3", r.getContent());
|
||||||
|
|
||||||
// create AAAA record using recordCreateSld
|
// create AAAA getRecord using recordCreateSld
|
||||||
createdRe2 =
|
createdRe2 =
|
||||||
client.recordCreateSld(z, randomSld, TTL, RecordType.AAAA, "2a0a:4cc0:c0:2e4::1");
|
client.recordCreateSld(z, randomSld, TTL, RecordType.AAAA, "2a0a:4cc0:c0:2e4::1");
|
||||||
List<RecordEntity> aaaaRecords = client.recordList(z, randomSld, RecordType.AAAA);
|
List<RecordEntity> aaaaRecords = client.recordList(z, randomSld, RecordType.AAAA);
|
||||||
@@ -166,7 +183,7 @@ public class CfClientTest {
|
|||||||
} else if (Objects.equals(re.getType(), RecordType.AAAA.getType())) {
|
} else if (Objects.equals(re.getType(), RecordType.AAAA.getType())) {
|
||||||
assertEquals("2a0a:4cc0:c0:2e4::1", re.getContent());
|
assertEquals("2a0a:4cc0:c0:2e4::1", re.getContent());
|
||||||
} else {
|
} else {
|
||||||
fail(String.format("Unexpected record type: %s", re.getType()));
|
fail(String.format("Unexpected getRecord type: %s", re.getType()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,7 +198,6 @@ public class CfClientTest {
|
|||||||
// test recordList with types without SLD
|
// test recordList with types without SLD
|
||||||
List<RecordEntity> aList = client.recordList(z, RecordType.A);
|
List<RecordEntity> aList = client.recordList(z, RecordType.A);
|
||||||
assertFalse(aList.isEmpty());
|
assertFalse(aList.isEmpty());
|
||||||
assertTrue(aList.size() >= 1);
|
|
||||||
assertTrue(aList.stream().anyMatch(re -> re.getId().equals(createdRe1.getId())));
|
assertTrue(aList.stream().anyMatch(re -> re.getId().equals(createdRe1.getId())));
|
||||||
assertTrue(aList.stream().noneMatch(re -> re.getId().equals(createdRe2.getId())));
|
assertTrue(aList.stream().noneMatch(re -> re.getId().equals(createdRe2.getId())));
|
||||||
assertTrue(aList.stream().allMatch(re -> re.getType().equals(RecordType.A.getType())));
|
assertTrue(aList.stream().allMatch(re -> re.getType().equals(RecordType.A.getType())));
|
||||||
@@ -191,7 +207,7 @@ public class CfClientTest {
|
|||||||
assertFalse(fluentList.isEmpty());
|
assertFalse(fluentList.isEmpty());
|
||||||
assertTrue(fluentList.stream().anyMatch(re -> re.getId().equals(createdRe1.getId())));
|
assertTrue(fluentList.stream().anyMatch(re -> re.getId().equals(createdRe1.getId())));
|
||||||
|
|
||||||
// update AAAA record
|
// update AAAA getRecord
|
||||||
createdRe2.setContent("2a0a:4cc0:c0:2e4::2");
|
createdRe2.setContent("2a0a:4cc0:c0:2e4::2");
|
||||||
client.recordUpdate(z, createdRe2);
|
client.recordUpdate(z, createdRe2);
|
||||||
aaaaRecords = client.recordList(z, randomSld, RecordType.AAAA);
|
aaaaRecords = client.recordList(z, randomSld, RecordType.AAAA);
|
||||||
@@ -199,18 +215,18 @@ public class CfClientTest {
|
|||||||
r = aaaaRecords.get(0);
|
r = aaaaRecords.get(0);
|
||||||
assertEquals("2a0a:4cc0:c0:2e4::2", r.getContent());
|
assertEquals("2a0a:4cc0:c0:2e4::2", r.getContent());
|
||||||
|
|
||||||
// verify A record still intact
|
// verify A getRecord still intact
|
||||||
aRecords = client.recordList(z, randomSld, RecordType.A);
|
aRecords = client.recordList(z, randomSld, RecordType.A);
|
||||||
assertEquals(1, aRecords.size());
|
assertEquals(1, aRecords.size());
|
||||||
r = aRecords.get(0);
|
r = aRecords.get(0);
|
||||||
assertEquals("130.0.0.3", r.getContent());
|
assertEquals("130.0.0.3", r.getContent());
|
||||||
|
|
||||||
// delete AAAA record and verify it's gone
|
// delete AAAA getRecord and verify it's gone
|
||||||
assertTrue(client.recordDelete(z, createdRe2));
|
assertTrue(client.recordDelete(z, createdRe2));
|
||||||
assertThrows(CloudflareNotFoundException.class,
|
assertThrows(CloudflareNotFoundException.class,
|
||||||
() -> client.recordList(z, randomSld, RecordType.AAAA));
|
() -> client.recordList(z, randomSld, RecordType.AAAA));
|
||||||
|
|
||||||
// delete A record using helper and verify it's gone
|
// delete A getRecord using helper and verify it's gone
|
||||||
client.recordDeleteTypeIfExists(z, randomSld, RecordType.A);
|
client.recordDeleteTypeIfExists(z, randomSld, RecordType.A);
|
||||||
assertThrows(CloudflareNotFoundException.class,
|
assertThrows(CloudflareNotFoundException.class,
|
||||||
() -> client.recordList(z, randomSld, RecordType.A));
|
() -> client.recordList(z, randomSld, RecordType.A));
|
||||||
@@ -226,7 +242,7 @@ public class CfClientTest {
|
|||||||
void testRecordEntityInvalidType() {
|
void testRecordEntityInvalidType() {
|
||||||
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class,
|
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class,
|
||||||
() -> RecordEntity.build("id123", "example.com", "INVALID_TYPE", 60, "192.168.1.1"));
|
() -> RecordEntity.build("id123", "example.com", "INVALID_TYPE", 60, "192.168.1.1"));
|
||||||
assertTrue(exception.getMessage().contains("Invalid record type: INVALID_TYPE"));
|
assertTrue(exception.getMessage().contains("Invalid getRecord type: INVALID_TYPE"));
|
||||||
assertTrue(exception.getMessage().contains("Must be one of:"));
|
assertTrue(exception.getMessage().contains("Must be one of:"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,7 +389,7 @@ public class CfClientTest {
|
|||||||
try {
|
try {
|
||||||
// Test fluent create
|
// Test fluent create
|
||||||
RecordEntity created = client.zone(ZONE_STR)
|
RecordEntity created = client.zone(ZONE_STR)
|
||||||
.record(fluentSld)
|
.getRecord(fluentSld)
|
||||||
.create(RecordType.A, "192.168.100.1", TTL);
|
.create(RecordType.A, "192.168.100.1", TTL);
|
||||||
|
|
||||||
assertNotNull(created.getId());
|
assertNotNull(created.getId());
|
||||||
@@ -382,7 +398,7 @@ public class CfClientTest {
|
|||||||
|
|
||||||
// Test fluent get
|
// Test fluent get
|
||||||
List<RecordEntity> records = client.zone(ZONE_STR)
|
List<RecordEntity> records = client.zone(ZONE_STR)
|
||||||
.record(fluentSld, RecordType.A)
|
.getRecord(fluentSld, RecordType.A)
|
||||||
.get();
|
.get();
|
||||||
|
|
||||||
assertEquals(1, records.size());
|
assertEquals(1, records.size());
|
||||||
@@ -390,18 +406,18 @@ public class CfClientTest {
|
|||||||
|
|
||||||
// Test fluent update
|
// Test fluent update
|
||||||
RecordEntity updated = client.zone(ZONE_STR)
|
RecordEntity updated = client.zone(ZONE_STR)
|
||||||
.record(fluentSld, RecordType.A)
|
.getRecord(fluentSld, RecordType.A)
|
||||||
.update("192.168.100.2");
|
.update("192.168.100.2");
|
||||||
|
|
||||||
assertEquals("192.168.100.2", updated.getContent());
|
assertEquals("192.168.100.2", updated.getContent());
|
||||||
|
|
||||||
// Test fluent delete
|
// Test fluent delete
|
||||||
client.zone(ZONE_STR)
|
client.zone(ZONE_STR)
|
||||||
.record(fluentSld)
|
.getRecord(fluentSld)
|
||||||
.delete(RecordType.A);
|
.delete(RecordType.A);
|
||||||
|
|
||||||
assertThrows(CloudflareNotFoundException.class,
|
assertThrows(CloudflareNotFoundException.class,
|
||||||
() -> client.zone(ZONE_STR).record(fluentSld, RecordType.A).get());
|
() -> client.zone(ZONE_STR).getRecord(fluentSld, RecordType.A).get());
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
@@ -425,7 +441,7 @@ public class CfClientTest {
|
|||||||
assertNotNull(groupedRecords, "Resulting map should not be null.");
|
assertNotNull(groupedRecords, "Resulting map should not be null.");
|
||||||
assertEquals(2, groupedRecords.size(), "The grouping should result in 2 FQDN keys.");
|
assertEquals(2, groupedRecords.size(), "The grouping should result in 2 FQDN keys.");
|
||||||
assertEquals(2, groupedRecords.get("example.com.").size(), "The key 'example.com.' should have 2 records.");
|
assertEquals(2, groupedRecords.get("example.com.").size(), "The key 'example.com.' should have 2 records.");
|
||||||
assertEquals(1, groupedRecords.get("sub.example.com.").size(), "The key 'sub.example.com.' should have 1 record.");
|
assertEquals(1, groupedRecords.get("sub.example.com.").size(), "The key 'sub.example.com.' should have 1 getRecord.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -445,4 +461,68 @@ public class CfClientTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testPaging() throws Exception {
|
||||||
|
ZoneEntity zone = client.zoneGet(ZONE_STR);
|
||||||
|
String pagingSld = "paging-" + System.currentTimeMillis();
|
||||||
|
|
||||||
|
try {
|
||||||
|
int existingCount = 0;
|
||||||
|
try {
|
||||||
|
List<RecordEntity> allRecords = client.recordList(zone);
|
||||||
|
existingCount = allRecords.size();
|
||||||
|
} catch (CloudflareApiException e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate how many records we need to create to reach at least 12 total A records
|
||||||
|
// (to test paging with pageSize 5: page 1 = 5, page 2 = 5, page 3 = 2+)
|
||||||
|
int targetCount = 12;
|
||||||
|
int recordsToCreate = Math.max(0, targetCount - existingCount);
|
||||||
|
|
||||||
|
// Create additional A records if needed
|
||||||
|
List<RecordEntity> createdRecords = new ArrayList<>();
|
||||||
|
for (int i = 1; i <= recordsToCreate; i++) {
|
||||||
|
RecordEntity record = RecordEntity.build(pagingSld, RecordType.A, TTL, "127.0.0." + i);
|
||||||
|
RecordEntity created = client.recordCreate(zone, record);
|
||||||
|
createdRecords.add(created);
|
||||||
|
assertNotNull(created.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test paging with page size of 5
|
||||||
|
PagingRequest page1Request = PagingRequest.of(1, 5);
|
||||||
|
List<RecordEntity> page1Records = client.recordList(zone, page1Request);
|
||||||
|
assertEquals(5, page1Records.size(), "First page should contain 5 records");
|
||||||
|
|
||||||
|
// 2nd page should also contain 5 records (if we have at least 12 total)
|
||||||
|
PagingRequest page2Request = PagingRequest.of(2, 5);
|
||||||
|
List<RecordEntity> page2Records = client.recordList(zone, page2Request);
|
||||||
|
assertEquals(5, page2Records.size(), "Second page should contain at least 5 records");
|
||||||
|
|
||||||
|
// 3rd page should contain 2 records
|
||||||
|
PagingRequest page3Request = PagingRequest.of(3, 5);
|
||||||
|
List<RecordEntity> page3Records = client.recordList(zone, page3Request);
|
||||||
|
assertEquals(2, page3Records.size(), "Third page should contain 2 records");
|
||||||
|
|
||||||
|
// Verify no overlap between pages
|
||||||
|
List<String> page1Ids = page1Records.stream().map(RecordEntity::getId).toList();
|
||||||
|
List<String> page2Ids = page2Records.stream().map(RecordEntity::getId).toList();
|
||||||
|
List<String> page3Ids = page3Records.stream().map(RecordEntity::getId).toList();
|
||||||
|
Set<String> generatedRecordIds = new HashSet<>(page1Ids);
|
||||||
|
generatedRecordIds.addAll(page2Ids);
|
||||||
|
generatedRecordIds.addAll(page3Ids);
|
||||||
|
assertEquals(createdRecords.size(), generatedRecordIds.size());
|
||||||
|
|
||||||
|
// Verify our created records are in the zone
|
||||||
|
List<RecordEntity> allRecords = client.recordList(zone);
|
||||||
|
Set<String> allRecordIds = allRecords.stream().map(RecordEntity::getId).collect(Collectors.toSet());
|
||||||
|
assertEquals(createdRecords.size(), allRecordIds.size());
|
||||||
|
assertTrue(allRecordIds.containsAll(generatedRecordIds));
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
client.recordDeleteTypeIfExists(zone, pagingSld, RecordType.A);
|
||||||
|
} catch (Exception e) { /* ignore */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,150 @@
|
|||||||
|
package codes.thischwa.cf;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for CfDnsClientBuilder and its authentication classes.
|
||||||
|
*/
|
||||||
|
class CfDnsClientBuilderTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testBuildWithApiToken() {
|
||||||
|
CfDnsClient client = new CfDnsClientBuilder()
|
||||||
|
.withApiTokenAuth("test-token")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assertNotNull(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testBuildWithEmailKey() {
|
||||||
|
CfDnsClient client = new CfDnsClientBuilder()
|
||||||
|
.withEmailKeyAuth("test@example.com", "test-key")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assertNotNull(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testBuildWithCustomBaseUrl() {
|
||||||
|
CfDnsClient client = new CfDnsClientBuilder()
|
||||||
|
.withApiTokenAuth("test-token")
|
||||||
|
.withBaseUrl("https://custom-api.example.com")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assertNotNull(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testBuildWithDefaultBaseUrl() {
|
||||||
|
CfDnsClient client = new CfDnsClientBuilder()
|
||||||
|
.withApiTokenAuth("test-token")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assertNotNull(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testBuildWithEmptyResultThrowsException() {
|
||||||
|
CfDnsClient client = new CfDnsClientBuilder()
|
||||||
|
.withApiTokenAuth("test-token")
|
||||||
|
.withEmptyResultThrowsException(true)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assertNotNull(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testBuildWithEmptyResultDoesNotThrowException() {
|
||||||
|
CfDnsClient client = new CfDnsClientBuilder()
|
||||||
|
.withApiTokenAuth("test-token")
|
||||||
|
.withEmptyResultThrowsException(false)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assertNotNull(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testBuilderMethodChaining() {
|
||||||
|
CfDnsClient client = new CfDnsClientBuilder()
|
||||||
|
.withApiTokenAuth("test-token")
|
||||||
|
.withBaseUrl("https://custom-api.example.com")
|
||||||
|
.withEmptyResultThrowsException(true)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assertNotNull(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testApiTokenAuth_BlankToken() {
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> new CfDnsClientBuilder.ApiTokenAuth(" "));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testEmailKeyAuth_ValidCredentials() {
|
||||||
|
CfDnsClientBuilder.EmailKeyAuth auth = new CfDnsClientBuilder.EmailKeyAuth(
|
||||||
|
"test@example.com",
|
||||||
|
"valid-key"
|
||||||
|
);
|
||||||
|
assertNotNull(auth);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testEmailKeyAuth_BlankEmail() {
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> new CfDnsClientBuilder.EmailKeyAuth(" ", "valid-key"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testEmailKeyAuth_BlankKey() {
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> new CfDnsClientBuilder.EmailKeyAuth("test@example.com", " "));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testEmailKeyAuth_BothBlank() {
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> new CfDnsClientBuilder.EmailKeyAuth(" ", " "));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDefaultBaseUrl() {
|
||||||
|
assertEquals("https://api.cloudflare.com/client/v4", CfDnsClientBuilder.DEFAULT_BASEURL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testBuilderWithMultipleConfigurations() {
|
||||||
|
// Test switching auth methods in the same builder (last one wins)
|
||||||
|
CfDnsClient client = new CfDnsClientBuilder()
|
||||||
|
.withEmailKeyAuth("test@example.com", "old-key")
|
||||||
|
.withApiTokenAuth("new-token") // This should override the email/key auth
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assertNotNull(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testBuilderWithMultipleBaseUrls() {
|
||||||
|
// Test setting base URL multiple times (last one wins)
|
||||||
|
CfDnsClient client = new CfDnsClientBuilder()
|
||||||
|
.withApiTokenAuth("test-token")
|
||||||
|
.withBaseUrl("https://old-api.example.com")
|
||||||
|
.withBaseUrl("https://new-api.example.com") // This should override
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assertNotNull(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testEmptyResultThrowsExceptionToggle() {
|
||||||
|
// Test toggling the flag multiple times (last one wins)
|
||||||
|
CfDnsClient client = new CfDnsClientBuilder()
|
||||||
|
.withApiTokenAuth("test-token")
|
||||||
|
.withEmptyResultThrowsException(true)
|
||||||
|
.withEmptyResultThrowsException(false) // This should override
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assertNotNull(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,399 @@
|
|||||||
|
package codes.thischwa.cf;
|
||||||
|
|
||||||
|
import codes.thischwa.cf.fluent.ZoneOperations;
|
||||||
|
import codes.thischwa.cf.model.*;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
import static org.mockito.ArgumentMatchers.*;
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for CfDnsClient using mocked HTTP client responses.
|
||||||
|
* Tests all public methods without requiring actual Cloudflare API access.
|
||||||
|
*/
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
class CfDnsClientMockTest {
|
||||||
|
|
||||||
|
private CfDnsClient client;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private CfBasicHttpClient mockHttpClient;
|
||||||
|
|
||||||
|
private static final String TEST_ZONE_ID = "zone123";
|
||||||
|
private static final String TEST_ZONE_NAME = "example.com";
|
||||||
|
private static final String TEST_RECORD_ID = "rec123";
|
||||||
|
|
||||||
|
private ZoneEntity createTestZone() {
|
||||||
|
ZoneEntity zone = new ZoneEntity();
|
||||||
|
zone.setId(TEST_ZONE_ID);
|
||||||
|
zone.setName(TEST_ZONE_NAME);
|
||||||
|
return zone;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResponseResultInfo createSuccessResultInfo() {
|
||||||
|
ResponseResultInfo resultInfo = new ResponseResultInfo();
|
||||||
|
resultInfo.setSuccess(true);
|
||||||
|
return resultInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BatchResponse createBatchResponse() throws Exception {
|
||||||
|
// Use reflection to access package-private constructor
|
||||||
|
java.lang.reflect.Constructor<BatchResponse> constructor = BatchResponse.class.getDeclaredConstructor();
|
||||||
|
constructor.setAccessible(true);
|
||||||
|
return constructor.newInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResultInfo createResultInfo(int count) {
|
||||||
|
return new ResultInfo(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() throws Exception {
|
||||||
|
// Create a real client with API token auth
|
||||||
|
client = new CfDnsClientBuilder()
|
||||||
|
.withApiTokenAuth("test-token")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Replace the internal HTTP client with our mock using reflection
|
||||||
|
// Note: This is a workaround since CfBasicHttpClient methods are package-private
|
||||||
|
Field responseValidatorField = CfDnsClient.class.getDeclaredField("responseValidator");
|
||||||
|
responseValidatorField.setAccessible(true);
|
||||||
|
responseValidatorField.set(client, new ResponseValidator(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGroupRecordsByFqdn() {
|
||||||
|
RecordEntity rec1 = RecordEntity.build("test.example.com", RecordType.A, 300, "1.2.3.4");
|
||||||
|
RecordEntity rec2 = RecordEntity.build("test.example.com", RecordType.AAAA, 300, "::1");
|
||||||
|
RecordEntity rec3 = RecordEntity.build("www.example.com", RecordType.A, 300, "1.2.3.5");
|
||||||
|
|
||||||
|
List<RecordEntity> records = List.of(rec1, rec2, rec3);
|
||||||
|
Map<String, List<RecordEntity>> grouped = CfDnsClient.groupRecordsByFqdn(records);
|
||||||
|
|
||||||
|
assertEquals(2, grouped.size());
|
||||||
|
assertEquals(2, grouped.get("test.example.com").size());
|
||||||
|
assertEquals(1, grouped.get("www.example.com").size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGroupRecordsByFqdn_NullInput() {
|
||||||
|
Map<String, List<RecordEntity>> grouped = CfDnsClient.groupRecordsByFqdn(null);
|
||||||
|
assertNotNull(grouped);
|
||||||
|
assertTrue(grouped.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testZoneList() throws Exception {
|
||||||
|
// Create mock zone response
|
||||||
|
ZoneMultipleResponse mockResponse = new ZoneMultipleResponse();
|
||||||
|
ZoneEntity zone1 = new ZoneEntity();
|
||||||
|
zone1.setId("zone1");
|
||||||
|
zone1.setName("example.com");
|
||||||
|
ZoneEntity zone2 = new ZoneEntity();
|
||||||
|
zone2.setId("zone2");
|
||||||
|
zone2.setName("test.com");
|
||||||
|
mockResponse.setResult(List.of(zone1, zone2));
|
||||||
|
ResponseResultInfo resultInfo = new ResponseResultInfo();
|
||||||
|
resultInfo.setSuccess(true);
|
||||||
|
mockResponse.setResponseResultInfo(resultInfo);
|
||||||
|
|
||||||
|
// Mock the HTTP client via spy
|
||||||
|
CfDnsClient spyClient = spy(client);
|
||||||
|
doReturn(mockResponse).when(spyClient).getRequest(anyString(), eq(ZoneMultipleResponse.class));
|
||||||
|
|
||||||
|
List<ZoneEntity> zones = spyClient.zoneList();
|
||||||
|
|
||||||
|
assertNotNull(zones);
|
||||||
|
assertEquals(2, zones.size());
|
||||||
|
assertEquals("example.com", zones.get(0).getName());
|
||||||
|
assertEquals("test.com", zones.get(1).getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testZoneGet() throws Exception {
|
||||||
|
// Create mock zone response
|
||||||
|
ZoneMultipleResponse mockResponse = new ZoneMultipleResponse();
|
||||||
|
ZoneEntity zone = new ZoneEntity();
|
||||||
|
zone.setId(TEST_ZONE_ID);
|
||||||
|
zone.setName(TEST_ZONE_NAME);
|
||||||
|
mockResponse.setResult(List.of(zone));
|
||||||
|
ResponseResultInfo resultInfo = new ResponseResultInfo();
|
||||||
|
resultInfo.setSuccess(true);
|
||||||
|
mockResponse.setResponseResultInfo(resultInfo);
|
||||||
|
|
||||||
|
CfDnsClient spyClient = spy(client);
|
||||||
|
doReturn(mockResponse).when(spyClient).getRequest(anyString(), eq(ZoneMultipleResponse.class));
|
||||||
|
|
||||||
|
ZoneEntity result = spyClient.zoneGet(TEST_ZONE_NAME);
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals(TEST_ZONE_ID, result.getId());
|
||||||
|
assertEquals(TEST_ZONE_NAME, result.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testZoneOperations() throws Exception {
|
||||||
|
// Create mock zone response
|
||||||
|
ZoneMultipleResponse mockResponse = new ZoneMultipleResponse();
|
||||||
|
ZoneEntity zone = new ZoneEntity();
|
||||||
|
zone.setId(TEST_ZONE_ID);
|
||||||
|
zone.setName(TEST_ZONE_NAME);
|
||||||
|
mockResponse.setResult(List.of(zone));
|
||||||
|
ResponseResultInfo resultInfo = new ResponseResultInfo();
|
||||||
|
resultInfo.setSuccess(true);
|
||||||
|
mockResponse.setResponseResultInfo(resultInfo);
|
||||||
|
|
||||||
|
CfDnsClient spyClient = spy(client);
|
||||||
|
doReturn(mockResponse).when(spyClient).getRequest(anyString(), eq(ZoneMultipleResponse.class));
|
||||||
|
|
||||||
|
ZoneOperations ops = spyClient.zone(TEST_ZONE_NAME);
|
||||||
|
|
||||||
|
assertNotNull(ops);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRecordList_Zone() throws Exception {
|
||||||
|
ZoneEntity zone = new ZoneEntity();
|
||||||
|
zone.setId(TEST_ZONE_ID);
|
||||||
|
zone.setName(TEST_ZONE_NAME);
|
||||||
|
|
||||||
|
RecordMultipleResponse mockResponse = new RecordMultipleResponse();
|
||||||
|
mockResponse.setResultInfo(createResultInfo(1));
|
||||||
|
RecordEntity rec1 = RecordEntity.build("test.example.com", RecordType.A, 300, "1.2.3.4");
|
||||||
|
RecordEntity rec2 = RecordEntity.build("www.example.com", RecordType.A, 300, "1.2.3.5");
|
||||||
|
mockResponse.setResult(List.of(rec1, rec2));
|
||||||
|
ResponseResultInfo resultInfo = new ResponseResultInfo();
|
||||||
|
resultInfo.setSuccess(true);
|
||||||
|
mockResponse.setResponseResultInfo(resultInfo);
|
||||||
|
|
||||||
|
CfDnsClient spyClient = spy(client);
|
||||||
|
doReturn(mockResponse).when(spyClient).getRequest(anyString(), eq(RecordMultipleResponse.class));
|
||||||
|
|
||||||
|
List<RecordEntity> records = spyClient.recordList(zone);
|
||||||
|
|
||||||
|
assertNotNull(records);
|
||||||
|
assertEquals(2, records.size());
|
||||||
|
assertEquals("1.2.3.4", records.get(0).getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRecordList_WithPaging() throws Exception {
|
||||||
|
ZoneEntity zone = createTestZone();
|
||||||
|
PagingRequest pagingRequest = PagingRequest.of(10, 1);
|
||||||
|
|
||||||
|
RecordMultipleResponse mockResponse = new RecordMultipleResponse();
|
||||||
|
mockResponse.setResultInfo(createResultInfo(1));
|
||||||
|
RecordEntity rec1 = RecordEntity.build("test.example.com", RecordType.A, 300, "1.2.3.4");
|
||||||
|
mockResponse.setResult(List.of(rec1));
|
||||||
|
mockResponse.setResponseResultInfo(createSuccessResultInfo());
|
||||||
|
|
||||||
|
CfDnsClient spyClient = spy(client);
|
||||||
|
doReturn(mockResponse).when(spyClient).getRequest(anyString(), eq(RecordMultipleResponse.class));
|
||||||
|
|
||||||
|
List<RecordEntity> records = spyClient.recordList(zone, pagingRequest);
|
||||||
|
|
||||||
|
assertNotNull(records);
|
||||||
|
assertEquals(1, records.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRecordList_BySld() throws Exception {
|
||||||
|
ZoneEntity zone = createTestZone();
|
||||||
|
|
||||||
|
RecordMultipleResponse mockResponse = new RecordMultipleResponse();
|
||||||
|
mockResponse.setResultInfo(createResultInfo(1));
|
||||||
|
RecordEntity rec1 = RecordEntity.build("test.example.com", RecordType.A, 300, "1.2.3.4");
|
||||||
|
mockResponse.setResult(List.of(rec1));
|
||||||
|
mockResponse.setResponseResultInfo(createSuccessResultInfo());
|
||||||
|
|
||||||
|
CfDnsClient spyClient = spy(client);
|
||||||
|
doReturn(mockResponse).when(spyClient).getRequest(anyString(), eq(RecordMultipleResponse.class));
|
||||||
|
|
||||||
|
List<RecordEntity> records = spyClient.recordList(zone, "test");
|
||||||
|
|
||||||
|
assertNotNull(records);
|
||||||
|
assertEquals(1, records.size());
|
||||||
|
assertEquals(TEST_ZONE_ID, records.get(0).getZoneId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRecordList_BySldAndType() throws Exception {
|
||||||
|
ZoneEntity zone = createTestZone();
|
||||||
|
|
||||||
|
RecordMultipleResponse mockResponse = new RecordMultipleResponse();
|
||||||
|
mockResponse.setResultInfo(createResultInfo(1));
|
||||||
|
RecordEntity rec1 = RecordEntity.build("test.example.com", RecordType.A, 300, "1.2.3.4");
|
||||||
|
RecordEntity rec2 = RecordEntity.build("test.example.com", RecordType.AAAA, 300, "::1");
|
||||||
|
mockResponse.setResult(List.of(rec1, rec2));
|
||||||
|
mockResponse.setResponseResultInfo(createSuccessResultInfo());
|
||||||
|
|
||||||
|
CfDnsClient spyClient = spy(client);
|
||||||
|
doReturn(mockResponse).when(spyClient).getRequest(anyString(), eq(RecordMultipleResponse.class));
|
||||||
|
|
||||||
|
List<RecordEntity> records = spyClient.recordList(zone, "test", RecordType.A);
|
||||||
|
|
||||||
|
assertNotNull(records);
|
||||||
|
assertEquals(1, records.size());
|
||||||
|
assertEquals(RecordType.A, RecordType.valueOf(records.get(0).getType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRecordList_ByType() throws Exception {
|
||||||
|
ZoneEntity zone = createTestZone();
|
||||||
|
|
||||||
|
RecordMultipleResponse mockResponse = new RecordMultipleResponse();
|
||||||
|
mockResponse.setResultInfo(createResultInfo(1));
|
||||||
|
RecordEntity rec1 = RecordEntity.build("test.example.com", RecordType.A, 300, "1.2.3.4");
|
||||||
|
RecordEntity rec2 = RecordEntity.build("www.example.com", RecordType.AAAA, 300, "::1");
|
||||||
|
mockResponse.setResult(List.of(rec1, rec2));
|
||||||
|
mockResponse.setResponseResultInfo(createSuccessResultInfo());
|
||||||
|
|
||||||
|
CfDnsClient spyClient = spy(client);
|
||||||
|
doReturn(mockResponse).when(spyClient).getRequest(anyString(), eq(RecordMultipleResponse.class));
|
||||||
|
|
||||||
|
List<RecordEntity> records = spyClient.recordList(zone, RecordType.A);
|
||||||
|
|
||||||
|
assertNotNull(records);
|
||||||
|
assertEquals(1, records.size());
|
||||||
|
assertEquals(RecordType.A, RecordType.valueOf(records.get(0).getType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRecordCreateSld() throws Exception {
|
||||||
|
ZoneEntity zone = createTestZone();
|
||||||
|
|
||||||
|
RecordSingleResponse mockResponse = new RecordSingleResponse();
|
||||||
|
RecordEntity createdRecord = RecordEntity.build("test.example.com", RecordType.A, 300, "1.2.3.4");
|
||||||
|
createdRecord.setId(TEST_RECORD_ID);
|
||||||
|
mockResponse.setResult(createdRecord);
|
||||||
|
mockResponse.setResponseResultInfo(createSuccessResultInfo());
|
||||||
|
|
||||||
|
CfDnsClient spyClient = spy(client);
|
||||||
|
doReturn(mockResponse).when(spyClient).postRequest(anyString(), any(), eq(RecordSingleResponse.class));
|
||||||
|
|
||||||
|
RecordEntity result = spyClient.recordCreate(zone, "test.example.com", 300, RecordType.A, "1.2.3.4");
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals(TEST_RECORD_ID, result.getId());
|
||||||
|
assertEquals(TEST_ZONE_ID, result.getZoneId());
|
||||||
|
assertEquals("1.2.3.4", result.getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRecordDelete() throws Exception {
|
||||||
|
ZoneEntity zone = createTestZone();
|
||||||
|
|
||||||
|
RecordSingleResponse mockResponse = new RecordSingleResponse();
|
||||||
|
RecordEntity deletedRecord = RecordEntity.build("test.example.com", RecordType.A, 300, "1.2.3.4");
|
||||||
|
deletedRecord.setId(TEST_RECORD_ID);
|
||||||
|
mockResponse.setResult(deletedRecord);
|
||||||
|
mockResponse.setResponseResultInfo(createSuccessResultInfo());
|
||||||
|
|
||||||
|
CfDnsClient spyClient = spy(client);
|
||||||
|
doReturn(mockResponse).when(spyClient).deleteRequest(anyString(), eq(RecordSingleResponse.class));
|
||||||
|
|
||||||
|
boolean result = spyClient.recordDelete(zone, TEST_RECORD_ID);
|
||||||
|
|
||||||
|
assertTrue(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRecordUpdate() throws Exception {
|
||||||
|
ZoneEntity zone = createTestZone();
|
||||||
|
RecordEntity record = RecordEntity.build("test.example.com", RecordType.A, 300, "1.2.3.4");
|
||||||
|
record.setId(TEST_RECORD_ID);
|
||||||
|
|
||||||
|
RecordSingleResponse mockResponse = new RecordSingleResponse();
|
||||||
|
RecordEntity updatedRecord = RecordEntity.build("test.example.com", RecordType.A, 300, "1.2.3.5");
|
||||||
|
updatedRecord.setId(TEST_RECORD_ID);
|
||||||
|
mockResponse.setResult(updatedRecord);
|
||||||
|
mockResponse.setResponseResultInfo(createSuccessResultInfo());
|
||||||
|
|
||||||
|
CfDnsClient spyClient = spy(client);
|
||||||
|
doReturn(mockResponse).when(spyClient).patchRequest(anyString(), any(), eq(RecordSingleResponse.class));
|
||||||
|
|
||||||
|
RecordEntity result = spyClient.recordUpdate(zone, record);
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals(TEST_RECORD_ID, result.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRecordDeleteTypeIfExists() throws Exception {
|
||||||
|
ZoneEntity zone = createTestZone();
|
||||||
|
|
||||||
|
RecordMultipleResponse listResponse = new RecordMultipleResponse();
|
||||||
|
listResponse.setResultInfo(createResultInfo(1));
|
||||||
|
RecordEntity rec1 = RecordEntity.build("test.example.com", RecordType.A, 300, "1.2.3.4");
|
||||||
|
rec1.setId(TEST_RECORD_ID);
|
||||||
|
listResponse.setResult(List.of(rec1));
|
||||||
|
listResponse.setResponseResultInfo(createSuccessResultInfo());
|
||||||
|
|
||||||
|
RecordSingleResponse deleteResponse = new RecordSingleResponse();
|
||||||
|
RecordEntity deletedRecord = RecordEntity.build("test.example.com", RecordType.A, 300, "1.2.3.4");
|
||||||
|
deletedRecord.setId(TEST_RECORD_ID);
|
||||||
|
deleteResponse.setResult(deletedRecord);
|
||||||
|
deleteResponse.setResponseResultInfo(createSuccessResultInfo());
|
||||||
|
|
||||||
|
CfDnsClient spyClient = spy(client);
|
||||||
|
doReturn(listResponse).when(spyClient).getRequest(anyString(), eq(RecordMultipleResponse.class));
|
||||||
|
doReturn(deleteResponse).when(spyClient).deleteRequest(anyString(), eq(RecordSingleResponse.class));
|
||||||
|
|
||||||
|
// Should not throw exception
|
||||||
|
spyClient.recordDeleteTypeIfExists(zone, "test", RecordType.A);
|
||||||
|
|
||||||
|
verify(spyClient, times(1)).getRequest(anyString(), eq(RecordMultipleResponse.class));
|
||||||
|
verify(spyClient, times(1)).deleteRequest(anyString(), eq(RecordSingleResponse.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRecordDeleteTypeIfExists_NotFound() throws Exception {
|
||||||
|
ZoneEntity zone = createTestZone();
|
||||||
|
|
||||||
|
CfDnsClient spyClient = spy(client);
|
||||||
|
doThrow(new CloudflareNotFoundException("Not found")).when(spyClient).recordList(any(), anyString(), any());
|
||||||
|
|
||||||
|
// Should not throw exception when record doesn't exist
|
||||||
|
assertDoesNotThrow(() -> spyClient.recordDeleteTypeIfExists(zone, "test", RecordType.A));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRecordBatch() throws Exception {
|
||||||
|
ZoneEntity zone = createTestZone();
|
||||||
|
|
||||||
|
RecordEntity postRecord = RecordEntity.build("new.example.com", RecordType.A, 300, "1.2.3.4");
|
||||||
|
RecordEntity patchRecord = RecordEntity.build(TEST_RECORD_ID, "1.2.3.5");
|
||||||
|
RecordEntity deleteRecord = RecordEntity.build("old.example.com", RecordType.A, 300, "1.2.3.6");
|
||||||
|
deleteRecord.setId("rec999");
|
||||||
|
|
||||||
|
BatchResponse mockResponse = createBatchResponse();
|
||||||
|
BatchEntry resultEntry = new BatchEntry();
|
||||||
|
resultEntry.setPosts(List.of(postRecord));
|
||||||
|
resultEntry.setPatches(List.of(patchRecord));
|
||||||
|
mockResponse.setResult(resultEntry);
|
||||||
|
mockResponse.setResponseResultInfo(createSuccessResultInfo());
|
||||||
|
|
||||||
|
CfDnsClient spyClient = spy(client);
|
||||||
|
doReturn(mockResponse).when(spyClient).postRequest(anyString(), any(), eq(BatchResponse.class));
|
||||||
|
|
||||||
|
BatchEntry result = spyClient.recordBatch(zone,
|
||||||
|
List.of(postRecord),
|
||||||
|
null,
|
||||||
|
List.of(patchRecord),
|
||||||
|
List.of(deleteRecord));
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
assertNotNull(result.getPosts());
|
||||||
|
assertEquals(1, result.getPosts().size());
|
||||||
|
assertEquals(TEST_ZONE_ID, result.getPosts().get(0).getZoneId());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,7 +27,7 @@ public class CfRequestTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBuildRecordInfoName() {
|
public void testBuildRecordInfoName() {
|
||||||
String result = CfRequest.RECORD_INFO_NAME.buildPath("zone123", "sub.domain.com");
|
String result = CfRequest.RECORD_LIST_NAME.buildPath("zone123", "sub.domain.com");
|
||||||
assertEquals("/zones/zone123/dns_records?name=sub.domain.com", result);
|
assertEquals("/zones/zone123/dns_records?name=sub.domain.com", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ public class CfRequestTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBuildRecordInfo() {
|
public void testBuildRecordInfo() {
|
||||||
String result = CfRequest.RECORD_INFO_NAME.buildPath("zone123", "sld.domain.com");
|
String result = CfRequest.RECORD_LIST_NAME.buildPath("zone123", "sld.domain.com");
|
||||||
assertEquals("/zones/zone123/dns_records?name=sld.domain.com", result);
|
assertEquals("/zones/zone123/dns_records?name=sld.domain.com", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,248 @@
|
|||||||
|
package codes.thischwa.cf.fluent;
|
||||||
|
|
||||||
|
import codes.thischwa.cf.CfDnsClient;
|
||||||
|
import codes.thischwa.cf.CloudflareApiException;
|
||||||
|
import codes.thischwa.cf.model.*;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
import static org.mockito.ArgumentMatchers.*;
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for the Fluent API package (ZoneOperations and RecordOperations).
|
||||||
|
*/
|
||||||
|
class FluentApiTest {
|
||||||
|
|
||||||
|
private CfDnsClient mockClient;
|
||||||
|
private ZoneEntity testZone;
|
||||||
|
|
||||||
|
private static final String TEST_ZONE_ID = "zone123";
|
||||||
|
private static final String TEST_ZONE_NAME = "example.com";
|
||||||
|
private static final String TEST_SLD = "test";
|
||||||
|
private static final String TEST_RECORD_ID = "rec123";
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
mockClient = mock(CfDnsClient.class);
|
||||||
|
testZone = new ZoneEntity();
|
||||||
|
testZone.setId(TEST_ZONE_ID);
|
||||||
|
testZone.setName(TEST_ZONE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testZoneOperations_GetRecord() throws CloudflareApiException {
|
||||||
|
ZoneOperations zoneOps = new ZoneOperationsImpl(mockClient, testZone);
|
||||||
|
|
||||||
|
RecordOperations recordOps = zoneOps.getRecord(TEST_SLD);
|
||||||
|
|
||||||
|
assertNotNull(recordOps);
|
||||||
|
assertInstanceOf(RecordOperationsImpl.class, recordOps);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testZoneOperations_GetRecordWithTypes() throws CloudflareApiException {
|
||||||
|
ZoneOperations zoneOps = new ZoneOperationsImpl(mockClient, testZone);
|
||||||
|
|
||||||
|
RecordOperations recordOps = zoneOps.getRecord(TEST_SLD, RecordType.A, RecordType.AAAA);
|
||||||
|
|
||||||
|
assertNotNull(recordOps);
|
||||||
|
assertInstanceOf(RecordOperationsImpl.class, recordOps);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testZoneOperations_List() throws CloudflareApiException {
|
||||||
|
RecordEntity rec1 = RecordEntity.build("test.example.com", RecordType.A, 300, "1.2.3.4");
|
||||||
|
RecordEntity rec2 = RecordEntity.build("www.example.com", RecordType.A, 300, "1.2.3.5");
|
||||||
|
List<RecordEntity> expectedRecords = List.of(rec1, rec2);
|
||||||
|
|
||||||
|
when(mockClient.recordList(eq(testZone), any(RecordType[].class)))
|
||||||
|
.thenReturn(expectedRecords);
|
||||||
|
|
||||||
|
ZoneOperations zoneOps = new ZoneOperationsImpl(mockClient, testZone);
|
||||||
|
List<RecordEntity> result = zoneOps.list();
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals(2, result.size());
|
||||||
|
verify(mockClient, times(1)).recordList(eq(testZone), any(RecordType[].class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testZoneOperations_ListWithTypes() throws CloudflareApiException {
|
||||||
|
RecordEntity rec1 = RecordEntity.build("test.example.com", RecordType.A, 300, "1.2.3.4");
|
||||||
|
List<RecordEntity> expectedRecords = List.of(rec1);
|
||||||
|
|
||||||
|
when(mockClient.recordList(eq(testZone), any(RecordType[].class)))
|
||||||
|
.thenReturn(expectedRecords);
|
||||||
|
|
||||||
|
ZoneOperations zoneOps = new ZoneOperationsImpl(mockClient, testZone);
|
||||||
|
List<RecordEntity> result = zoneOps.list(RecordType.A);
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals(1, result.size());
|
||||||
|
verify(mockClient, times(1)).recordList(eq(testZone), any(RecordType[].class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRecordOperations_Get() throws CloudflareApiException {
|
||||||
|
RecordEntity rec1 = RecordEntity.build("test.example.com", RecordType.A, 300, "1.2.3.4");
|
||||||
|
List<RecordEntity> expectedRecords = List.of(rec1);
|
||||||
|
|
||||||
|
when(mockClient.recordList(eq(testZone), eq(TEST_SLD), any()))
|
||||||
|
.thenReturn(expectedRecords);
|
||||||
|
|
||||||
|
RecordOperations recordOps = new RecordOperationsImpl(mockClient, testZone, TEST_SLD, null);
|
||||||
|
List<RecordEntity> result = recordOps.get();
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals(1, result.size());
|
||||||
|
assertEquals("1.2.3.4", result.get(0).getContent());
|
||||||
|
verify(mockClient, times(1)).recordList(eq(testZone), eq(TEST_SLD), any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRecordOperations_GetWithTypes() throws CloudflareApiException {
|
||||||
|
RecordEntity rec1 = RecordEntity.build("test.example.com", RecordType.A, 300, "1.2.3.4");
|
||||||
|
List<RecordEntity> expectedRecords = List.of(rec1);
|
||||||
|
|
||||||
|
RecordType[] types = {RecordType.A};
|
||||||
|
when(mockClient.recordList(eq(testZone), eq(TEST_SLD), eq(types)))
|
||||||
|
.thenReturn(expectedRecords);
|
||||||
|
|
||||||
|
RecordOperations recordOps = new RecordOperationsImpl(mockClient, testZone, TEST_SLD, types);
|
||||||
|
List<RecordEntity> result = recordOps.get();
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals(1, result.size());
|
||||||
|
verify(mockClient, times(1)).recordList(eq(testZone), eq(TEST_SLD), eq(types));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRecordOperations_Create() throws CloudflareApiException {
|
||||||
|
RecordEntity createdRecord = RecordEntity.build("test.example.com", RecordType.A, 300, "1.2.3.4");
|
||||||
|
createdRecord.setId(TEST_RECORD_ID);
|
||||||
|
|
||||||
|
when(mockClient.recordCreateSld(eq(testZone), eq(TEST_SLD), eq(300), eq(RecordType.A), eq("1.2.3.4")))
|
||||||
|
.thenReturn(createdRecord);
|
||||||
|
|
||||||
|
RecordOperations recordOps = new RecordOperationsImpl(mockClient, testZone, TEST_SLD, null);
|
||||||
|
RecordEntity result = recordOps.create(RecordType.A, "1.2.3.4", 300);
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals(TEST_RECORD_ID, result.getId());
|
||||||
|
assertEquals("1.2.3.4", result.getContent());
|
||||||
|
verify(mockClient, times(1)).recordCreateSld(eq(testZone), eq(TEST_SLD), eq(300), eq(RecordType.A), eq("1.2.3.4"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRecordOperations_Update_Success() throws CloudflareApiException {
|
||||||
|
RecordEntity existingRecord = RecordEntity.build("test.example.com", RecordType.A, 300, "1.2.3.4");
|
||||||
|
existingRecord.setId(TEST_RECORD_ID);
|
||||||
|
|
||||||
|
RecordEntity updatedRecord = RecordEntity.build("test.example.com", RecordType.A, 300, "1.2.3.5");
|
||||||
|
updatedRecord.setId(TEST_RECORD_ID);
|
||||||
|
|
||||||
|
when(mockClient.recordList(eq(testZone), eq(TEST_SLD), any()))
|
||||||
|
.thenReturn(List.of(existingRecord));
|
||||||
|
when(mockClient.recordUpdate(eq(testZone), any(RecordEntity.class)))
|
||||||
|
.thenReturn(updatedRecord);
|
||||||
|
|
||||||
|
RecordOperations recordOps = new RecordOperationsImpl(mockClient, testZone, TEST_SLD, null);
|
||||||
|
RecordEntity result = recordOps.update("1.2.3.5");
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals("1.2.3.5", result.getContent());
|
||||||
|
verify(mockClient, times(1)).recordList(eq(testZone), eq(TEST_SLD), any());
|
||||||
|
verify(mockClient, times(1)).recordUpdate(eq(testZone), any(RecordEntity.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRecordOperations_Update_NoRecordsFound() throws CloudflareApiException {
|
||||||
|
when(mockClient.recordList(eq(testZone), eq(TEST_SLD), any()))
|
||||||
|
.thenReturn(List.of());
|
||||||
|
|
||||||
|
RecordOperations recordOps = new RecordOperationsImpl(mockClient, testZone, TEST_SLD, null);
|
||||||
|
|
||||||
|
CloudflareApiException exception = assertThrows(CloudflareApiException.class, () -> {
|
||||||
|
recordOps.update("1.2.3.5");
|
||||||
|
});
|
||||||
|
|
||||||
|
assertTrue(exception.getMessage().contains("No recs found"));
|
||||||
|
verify(mockClient, times(1)).recordList(eq(testZone), eq(TEST_SLD), any());
|
||||||
|
verify(mockClient, never()).recordUpdate(any(), any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRecordOperations_Update_MultipleRecordsFound() throws CloudflareApiException {
|
||||||
|
RecordEntity rec1 = RecordEntity.build("test.example.com", RecordType.A, 300, "1.2.3.4");
|
||||||
|
RecordEntity rec2 = RecordEntity.build("test.example.com", RecordType.AAAA, 300, "::1");
|
||||||
|
|
||||||
|
when(mockClient.recordList(eq(testZone), eq(TEST_SLD), any()))
|
||||||
|
.thenReturn(List.of(rec1, rec2));
|
||||||
|
|
||||||
|
RecordOperations recordOps = new RecordOperationsImpl(mockClient, testZone, TEST_SLD, null);
|
||||||
|
|
||||||
|
CloudflareApiException exception = assertThrows(CloudflareApiException.class, () -> {
|
||||||
|
recordOps.update("1.2.3.5");
|
||||||
|
});
|
||||||
|
|
||||||
|
assertTrue(exception.getMessage().contains("Multiple recs found"));
|
||||||
|
verify(mockClient, times(1)).recordList(eq(testZone), eq(TEST_SLD), any());
|
||||||
|
verify(mockClient, never()).recordUpdate(any(), any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRecordOperations_Delete() throws CloudflareApiException {
|
||||||
|
doNothing().when(mockClient).recordDeleteTypeIfExists(eq(testZone), eq(TEST_SLD), any(RecordType[].class));
|
||||||
|
|
||||||
|
RecordOperations recordOps = new RecordOperationsImpl(mockClient, testZone, TEST_SLD, null);
|
||||||
|
recordOps.delete(RecordType.A, RecordType.AAAA);
|
||||||
|
|
||||||
|
verify(mockClient, times(1)).recordDeleteTypeIfExists(eq(testZone), eq(TEST_SLD), any(RecordType[].class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRecordOperations_DeleteSingleType() throws CloudflareApiException {
|
||||||
|
doNothing().when(mockClient).recordDeleteTypeIfExists(eq(testZone), eq(TEST_SLD), any(RecordType[].class));
|
||||||
|
|
||||||
|
RecordOperations recordOps = new RecordOperationsImpl(mockClient, testZone, TEST_SLD, null);
|
||||||
|
recordOps.delete(RecordType.A);
|
||||||
|
|
||||||
|
verify(mockClient, times(1)).recordDeleteTypeIfExists(eq(testZone), eq(TEST_SLD), any(RecordType[].class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testFluentApiChaining() throws CloudflareApiException {
|
||||||
|
// Test that fluent API chaining works correctly
|
||||||
|
RecordEntity createdRecord = RecordEntity.build("test.example.com", RecordType.A, 300, "1.2.3.4");
|
||||||
|
createdRecord.setId(TEST_RECORD_ID);
|
||||||
|
|
||||||
|
when(mockClient.recordCreateSld(eq(testZone), eq(TEST_SLD), eq(300), eq(RecordType.A), eq("1.2.3.4")))
|
||||||
|
.thenReturn(createdRecord);
|
||||||
|
|
||||||
|
ZoneOperations zoneOps = new ZoneOperationsImpl(mockClient, testZone);
|
||||||
|
RecordEntity result = zoneOps.getRecord(TEST_SLD).create(RecordType.A, "1.2.3.4", 300);
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals(TEST_RECORD_ID, result.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testConstructorFields() {
|
||||||
|
// Test that constructor properly initializes fields
|
||||||
|
RecordType[] types = {RecordType.A, RecordType.AAAA};
|
||||||
|
RecordOperationsImpl recordOps = new RecordOperationsImpl(mockClient, testZone, TEST_SLD, types);
|
||||||
|
|
||||||
|
assertNotNull(recordOps);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testZoneOperationsImplConstructor() {
|
||||||
|
ZoneOperationsImpl zoneOps = new ZoneOperationsImpl(mockClient, testZone);
|
||||||
|
|
||||||
|
assertNotNull(zoneOps);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package codes.thischwa.cf.model;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
public class BatchEntryTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testBatchEntry() {
|
||||||
|
BatchEntry entry = new BatchEntry();
|
||||||
|
assertEquals("", entry.getId());
|
||||||
|
|
||||||
|
List<RecordEntity> patches = new ArrayList<>();
|
||||||
|
List<RecordEntity> posts = new ArrayList<>();
|
||||||
|
List<RecordEntity> puts = new ArrayList<>();
|
||||||
|
List<RecordEntity> deletes = new ArrayList<>();
|
||||||
|
|
||||||
|
entry.setPatches(patches);
|
||||||
|
entry.setPosts(posts);
|
||||||
|
entry.setPuts(puts);
|
||||||
|
entry.setDeletes(deletes);
|
||||||
|
|
||||||
|
assertSame(patches, entry.getPatches());
|
||||||
|
assertSame(posts, entry.getPosts());
|
||||||
|
assertSame(puts, entry.getPuts());
|
||||||
|
assertSame(deletes, entry.getDeletes());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testLombokMethods() {
|
||||||
|
BatchEntry entry1 = new BatchEntry();
|
||||||
|
BatchEntry entry2 = new BatchEntry();
|
||||||
|
assertEquals(entry1, entry2);
|
||||||
|
assertEquals(entry1.hashCode(), entry2.hashCode());
|
||||||
|
|
||||||
|
List<RecordEntity> patches = List.of(new RecordEntity());
|
||||||
|
entry1.setPatches(patches);
|
||||||
|
assertNotEquals(entry1, entry2);
|
||||||
|
|
||||||
|
entry2.setPatches(patches);
|
||||||
|
assertEquals(entry1, entry2);
|
||||||
|
|
||||||
|
assertTrue(entry1.toString().contains("patches="));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,15 +7,37 @@ import static org.junit.jupiter.api.Assertions.*;
|
|||||||
public class PagingRequestTest {
|
public class PagingRequestTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBuildPath() {
|
void testBuildPath() {
|
||||||
String result = PagingRequest.defaultPaging().addQueryString("/zones");
|
String result = PagingRequest.defaultPaging().addQueryString("/zones");
|
||||||
assertEquals("/zones?page=1&perPage=5000000", result);
|
assertEquals("/zones?page=1&per_page=1000", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBuildPathAdditional() {
|
void testBuildPathAdditional() {
|
||||||
String result = new PagingRequest( 10, 100).addQueryString("/zones?foo=bar");
|
String result = new PagingRequest( 10, 100).addQueryString("/zones?foo=bar");
|
||||||
assertEquals("/zones?foo=bar&page=10&perPage=100", result);
|
assertEquals("/zones?foo=bar&page=10&per_page=100", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetPagingParams() {
|
||||||
|
PagingRequest request = PagingRequest.of(2, 50);
|
||||||
|
java.util.Map<String, String> params = request.getPagingParams();
|
||||||
|
assertEquals("2", params.get("page"));
|
||||||
|
assertEquals("50", params.get("perPage"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testLombokMethods() {
|
||||||
|
PagingRequest req1 = PagingRequest.of(1, 10);
|
||||||
|
PagingRequest req2 = PagingRequest.of(1, 10);
|
||||||
|
assertEquals(req1, req2);
|
||||||
|
assertEquals(req1.hashCode(), req2.hashCode());
|
||||||
|
assertTrue(req1.toString().contains("page=1"));
|
||||||
|
|
||||||
|
req1.setPage(5);
|
||||||
|
assertEquals(5, req1.getPage());
|
||||||
|
req1.setPerPage(20);
|
||||||
|
assertEquals(20, req1.getPerPage());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package codes.thischwa.cf.model;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
public class RecordEntityTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testBuildWithAttributes() {
|
||||||
|
RecordEntity rec = RecordEntity.build("example.com", RecordType.A, 120, "1.2.3.4");
|
||||||
|
assertEquals("example.com", rec.getName());
|
||||||
|
assertEquals("A", rec.getType());
|
||||||
|
assertEquals(120, rec.getTtl());
|
||||||
|
assertEquals("1.2.3.4", rec.getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testBuildWithIdAndContent() {
|
||||||
|
RecordEntity rec = RecordEntity.build("id-123", "1.2.3.4");
|
||||||
|
assertEquals("id-123", rec.getId());
|
||||||
|
assertEquals("1.2.3.4", rec.getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testBuildWithIdAndAttributes() {
|
||||||
|
RecordEntity rec = RecordEntity.build("id-123", "example.com", "A", 120, "1.2.3.4");
|
||||||
|
assertEquals("id-123", rec.getId());
|
||||||
|
assertEquals("example.com", rec.getName());
|
||||||
|
assertEquals("A", rec.getType());
|
||||||
|
assertEquals(120, rec.getTtl());
|
||||||
|
assertEquals("1.2.3.4", rec.getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testBuildWithInvalidType() {
|
||||||
|
assertThrows(IllegalArgumentException.class, () ->
|
||||||
|
RecordEntity.build("id-123", "example.com", "INVALID", 120, "1.2.3.4")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetSld() {
|
||||||
|
RecordEntity rec = new RecordEntity();
|
||||||
|
assertNull(rec.getSld());
|
||||||
|
|
||||||
|
rec.setName("sub.example.com");
|
||||||
|
assertEquals("sub", rec.getSld());
|
||||||
|
|
||||||
|
rec.setName("example.com");
|
||||||
|
assertEquals("example", rec.getSld());
|
||||||
|
|
||||||
|
rec.setName("host");
|
||||||
|
assertEquals("host", rec.getSld());
|
||||||
|
|
||||||
|
rec.setName(".dotstart");
|
||||||
|
assertEquals(".dotstart", rec.getSld());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetSldWithZoneName() {
|
||||||
|
RecordEntity rec = new RecordEntity();
|
||||||
|
rec.setName("sub.example.com");
|
||||||
|
rec.setZoneName("example.com");
|
||||||
|
assertEquals("sub", rec.getSld());
|
||||||
|
|
||||||
|
rec.setName("my.sub.example.com");
|
||||||
|
rec.setZoneName("example.com");
|
||||||
|
assertEquals("my.sub", rec.getSld());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package codes.thischwa.cf.model;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
public class RecordTypeTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetType() {
|
||||||
|
assertEquals("A", RecordType.A.getType());
|
||||||
|
assertEquals("AAAA", RecordType.AAAA.getType());
|
||||||
|
assertEquals("CNAME", RecordType.CNAME.getType());
|
||||||
|
assertEquals("TXT", RecordType.TXT.getType());
|
||||||
|
assertEquals("SRV", RecordType.SRV.getType());
|
||||||
|
assertEquals("LOC", RecordType.LOC.getType());
|
||||||
|
assertEquals("MX", RecordType.MX.getType());
|
||||||
|
assertEquals("NS", RecordType.NS.getType());
|
||||||
|
assertEquals("CAA", RecordType.CAA.getType());
|
||||||
|
assertEquals("CERT", RecordType.CERT.getType());
|
||||||
|
assertEquals("DNSKEY", RecordType.DNSKEY.getType());
|
||||||
|
assertEquals("DS", RecordType.DS.getType());
|
||||||
|
assertEquals("NAPTR", RecordType.NAPTR.getType());
|
||||||
|
assertEquals("SMIMEA", RecordType.SMIMEA.getType());
|
||||||
|
assertEquals("SSHFP", RecordType.SSHFP.getType());
|
||||||
|
assertEquals("TLSA", RecordType.TLSA.getType());
|
||||||
|
assertEquals("URI", RecordType.URI.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testToString() {
|
||||||
|
assertEquals("A", RecordType.A.toString());
|
||||||
|
assertEquals("CNAME", RecordType.CNAME.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testValueOf() {
|
||||||
|
assertEquals(RecordType.A, RecordType.valueOf("A"));
|
||||||
|
assertEquals(RecordType.CNAME, RecordType.valueOf("CNAME"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package codes.thischwa.cf.model;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Set;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class ZoneEntityTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testZoneEntity() {
|
||||||
|
ZoneEntity zone = new ZoneEntity();
|
||||||
|
zone.setId("zone-id");
|
||||||
|
zone.setName("example.com");
|
||||||
|
zone.setDevelopmentMode(7200);
|
||||||
|
Set<String> ns = Set.of("ns1.cloudflare.com", "ns2.cloudflare.com");
|
||||||
|
zone.setNameServers(ns);
|
||||||
|
zone.setOriginalNameServers(ns);
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
zone.setCreatedOn(now);
|
||||||
|
zone.setModifiedOn(now);
|
||||||
|
zone.setActivatedOn(now);
|
||||||
|
zone.setStatus("active");
|
||||||
|
zone.setPaused(false);
|
||||||
|
zone.setType("full");
|
||||||
|
|
||||||
|
assertEquals("zone-id", zone.getId());
|
||||||
|
assertEquals("example.com", zone.getName());
|
||||||
|
assertEquals(7200, zone.getDevelopmentMode());
|
||||||
|
assertEquals(ns, zone.getNameServers());
|
||||||
|
assertEquals(ns, zone.getOriginalNameServers());
|
||||||
|
assertEquals(now, zone.getCreatedOn());
|
||||||
|
assertEquals(now, zone.getModifiedOn());
|
||||||
|
assertEquals(now, zone.getActivatedOn());
|
||||||
|
assertEquals("active", zone.getStatus());
|
||||||
|
assertFalse(zone.getPaused());
|
||||||
|
assertEquals("full", zone.getType());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<configuration>
|
<configuration debug="true">
|
||||||
|
|
||||||
<appender name="current"
|
<appender name="current"
|
||||||
class="ch.qos.logback.core.ConsoleAppender">
|
class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
|||||||
Reference in New Issue
Block a user