Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 62b86ca22f | |||
| f12f5d6db1 | |||
| c435a80966 | |||
| 1e8fe53891 | |||
| 10ad4bd7f3 | |||
| 84a454f656 | |||
| 4a3ec42fa5 | |||
| 9e09b12dc3 | |||
| d0802fc01d | |||
| 607b634b35 | |||
| b593ca7311 | |||
| 773573bd39 | |||
| b890ae9d17 |
+1
-1
@@ -32,7 +32,7 @@ build:
|
|||||||
- mkdir public
|
- mkdir public
|
||||||
- cp -rv docs/* public/
|
- cp -rv docs/* public/
|
||||||
- mkdir public/apidocs
|
- mkdir public/apidocs
|
||||||
- cp -rv target/apidocs public/
|
- cp -rv target/reports/apidocs public/
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- target/surefire-reports/*.xml
|
- target/surefire-reports/*.xml
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ 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
|
```xml<p>
|
||||||
<repositories>
|
<repositories>
|
||||||
<repository>
|
<repository>
|
||||||
<id>gitlab-cloudflare</id>
|
<id>gitlab-cloudflare</id>
|
||||||
@@ -49,14 +49,18 @@ The dependency is:
|
|||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
- 0.2.0-beta-SNAPSHOT:
|
- 0.3.0-SNAPSHOT:
|
||||||
- **New Fluent API**: Added chainable method interface for more readable DNS operations (
|
- **Breaking Change**:
|
||||||
`client.zone().record()...`)
|
- **New Fluent API**: Changed the initialization of the client(`new CfDnsClientBuilder().withApiTokenAuth("your-api-token").build()`)
|
||||||
|
- Authentication with API token.
|
||||||
|
- 0.2.0:
|
||||||
- **Breaking Change**: `emptyResultThrowsException` default changed from `true` to `false`. Now applies to both
|
- **Breaking Change**: `emptyResultThrowsException` default changed from `true` to `false`. Now applies to both
|
||||||
single and multiple result requests. Empty results will be returned by default without throwing exceptions.
|
single and multiple result requests. Empty results will be returned by default without throwing exceptions.
|
||||||
- API method names refactored for consistency: `zoneListAll` → `zoneList`, `zoneInfo` → `zoneGet`, `sldListAll` →
|
- API method names refactored for consistency: `zoneListAll` → `zoneList`, `zoneInfo` → `zoneGet`, `sldListAll` →
|
||||||
`recordList`
|
`recordList`
|
||||||
- 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 (
|
||||||
|
`client.zone().record()...`)
|
||||||
- Code quality improvements: eliminated duplication in batch operations, improved type safety in HTTP methods,
|
- Code quality improvements: eliminated 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
|
||||||
@@ -88,10 +92,18 @@ the [javadoc of the CfDnsClient](https://cloudflaredns-java-f4ee3a.gitlab.io/api
|
|||||||
|
|
||||||
### Instantiation of `CfDnsClient`
|
### Instantiation of `CfDnsClient`
|
||||||
|
|
||||||
|
#### With API Token (recommended):
|
||||||
```java
|
```java
|
||||||
CfDnsClient cfDnsClient = new CfDnsClient(
|
CfDnsClient cfDnsClient = new CfDnsClientBuilder()
|
||||||
"email@example.com", "yourApiKey"
|
.withApiTokenAuth("your-api-token")
|
||||||
);
|
.build();
|
||||||
|
```
|
||||||
|
|
||||||
|
#### With Email/Key (legacy):
|
||||||
|
```java
|
||||||
|
CfDnsClient cfDnsClient = new CfDnsClientBuilder()
|
||||||
|
.withEmailKeyAuth("email@example.com", "yourApiKey")
|
||||||
|
.build();
|
||||||
```
|
```
|
||||||
|
|
||||||
### `zoneList`
|
### `zoneList`
|
||||||
@@ -389,7 +401,9 @@ client.zone("example.com")
|
|||||||
### Complete Example
|
### Complete Example
|
||||||
|
|
||||||
```java
|
```java
|
||||||
CfDnsClient client = new CfDnsClient("email@example.com", "yourApiKey");
|
CfDnsClient client = new CfDnsClientBuilder()
|
||||||
|
.withApiTokenAuth("your-api-token")
|
||||||
|
.build();
|
||||||
|
|
||||||
// Create a new record
|
// Create a new record
|
||||||
client.zone("example.com")
|
client.zone("example.com")
|
||||||
@@ -424,7 +438,10 @@ The `CfDnsClient` provides internal error-handling mechanisms through exceptions
|
|||||||
To enable exception throwing for empty results:
|
To enable exception throwing for empty results:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
CfDnsClient client = new CfDnsClient(true, "email@example.com", "yourApiKey");
|
CfDnsClient client = new CfDnsClientBuilder()
|
||||||
|
.withApiTokenAuth("your-api-token")
|
||||||
|
.withEmptyResultThrowsException(true)
|
||||||
|
.build();
|
||||||
```
|
```
|
||||||
|
|
||||||
## Example:
|
## Example:
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
<groupId>codes.thischwa</groupId>
|
<groupId>codes.thischwa</groupId>
|
||||||
<artifactId>cloudflaredns</artifactId>
|
<artifactId>cloudflaredns</artifactId>
|
||||||
<version>0.2.0</version>
|
<version>0.3.0</version>
|
||||||
<name>CloudflareDNS-java</name>
|
<name>CloudflareDNS-java</name>
|
||||||
<inceptionYear>2025</inceptionYear>
|
<inceptionYear>2025</inceptionYear>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
@@ -21,24 +21,26 @@
|
|||||||
<project.reporting.outputEncoding>${file.encoding}</project.reporting.outputEncoding>
|
<project.reporting.outputEncoding>${file.encoding}</project.reporting.outputEncoding>
|
||||||
|
|
||||||
<!-- checkstyle -->
|
<!-- checkstyle -->
|
||||||
<checkstyle.version>10.21.3</checkstyle.version>
|
<checkstyle.version>12.3.0</checkstyle.version>
|
||||||
<checkstyle.plugin.version>3.6.0</checkstyle.plugin.version>
|
<checkstyle.plugin.version>3.6.0</checkstyle.plugin.version>
|
||||||
<checkstyle.config.location>${project.basedir}/src/checkstyle/google_custom_checks.xml
|
<checkstyle.config.location>${project.basedir}/src/checkstyle/google_custom_checks.xml
|
||||||
</checkstyle.config.location>
|
</checkstyle.config.location>
|
||||||
<checkstyle.includeTestResources>false</checkstyle.includeTestResources>
|
<checkstyle.includeTestResources>false</checkstyle.includeTestResources>
|
||||||
<checkstyle.violationSeverity>warning</checkstyle.violationSeverity>
|
<checkstyle.violationSeverity>warning</checkstyle.violationSeverity>
|
||||||
<checkstyle.failOnViolation>false</checkstyle.failOnViolation>
|
<checkstyle.failOnViolation>false</checkstyle.failOnViolation>
|
||||||
|
<checkstyle.propertyExpansion>config_loc=${basedir}
|
||||||
|
</checkstyle.propertyExpansion>
|
||||||
<checkstyle.consoleOutput>true</checkstyle.consoleOutput>
|
<checkstyle.consoleOutput>true</checkstyle.consoleOutput>
|
||||||
<linkX-Ref>false</linkX-Ref>
|
<linkXRef>false</linkXRef>
|
||||||
|
|
||||||
<!-- 3rd party dependencies -->
|
<!-- 3rd party dependencies -->
|
||||||
<jackson.version>2.18.2</jackson.version>
|
<jackson.version>2.19.1</jackson.version>
|
||||||
<httpclient5.version>5.4.3</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.18</logback-classic.version>
|
||||||
<junit5.version>5.12.2</junit5.version>
|
<junit5.version>5.14.2</junit5.version>
|
||||||
<mockito-junit5.version>5.17.0</mockito-junit5.version>
|
<mockito-junit5.version>5.21.0</mockito-junit5.version>
|
||||||
|
|
||||||
<!-- sonarqube -->
|
<!-- sonarqube -->
|
||||||
<sonar.organization>th-schwarz</sonar.organization>
|
<sonar.organization>th-schwarz</sonar.organization>
|
||||||
@@ -56,7 +58,7 @@
|
|||||||
<developerConnection>scm:git:git@gitlab.com:th-schwarz/CloudflareDNS-java.git</developerConnection>
|
<developerConnection>scm:git:git@gitlab.com:th-schwarz/CloudflareDNS-java.git</developerConnection>
|
||||||
<connection>scm:git:git@gitlab.com:th-schwarz/CloudflareDNS-java.git</connection>
|
<connection>scm:git:git@gitlab.com:th-schwarz/CloudflareDNS-java.git</connection>
|
||||||
<url>https://gitlab.com/th-schwarz/CloudflareDNS-java</url>
|
<url>https://gitlab.com/th-schwarz/CloudflareDNS-java</url>
|
||||||
<tag>v0.2.0</tag>
|
<tag>v0.3.0</tag>
|
||||||
</scm>
|
</scm>
|
||||||
|
|
||||||
<distributionManagement>
|
<distributionManagement>
|
||||||
@@ -149,7 +151,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
<version>3.6.3</version>
|
<version>3.11.2</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<failOnError>false</failOnError>
|
<failOnError>false</failOnError>
|
||||||
<locale>en</locale>
|
<locale>en</locale>
|
||||||
@@ -168,7 +170,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-release-plugin</artifactId>
|
<artifactId>maven-release-plugin</artifactId>
|
||||||
<version>3.1.1</version>
|
<version>3.3.1</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<tagNameFormat>v@{project.version}</tagNameFormat>
|
<tagNameFormat>v@{project.version}</tagNameFormat>
|
||||||
<arguments>-DskipTests</arguments>
|
<arguments>-DskipTests</arguments>
|
||||||
@@ -202,7 +204,7 @@
|
|||||||
<!-- generates the code coverage report for sonar cube -->
|
<!-- generates the code coverage report for sonar cube -->
|
||||||
<groupId>org.jacoco</groupId>
|
<groupId>org.jacoco</groupId>
|
||||||
<artifactId>jacoco-maven-plugin</artifactId>
|
<artifactId>jacoco-maven-plugin</artifactId>
|
||||||
<version>0.8.12</version>
|
<version>0.8.13</version>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>prepare-agent</id>
|
<id>prepare-agent</id>
|
||||||
@@ -261,6 +263,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<version>3.4.2</version>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>attach-delomboked-sources</id>
|
<id>attach-delomboked-sources</id>
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import org.apache.hc.core5.http.HttpHeaders;
|
|||||||
import org.apache.hc.core5.http.io.entity.EntityUtils;
|
import org.apache.hc.core5.http.io.entity.EntityUtils;
|
||||||
import org.apache.hc.core5.http.io.entity.StringEntity;
|
import org.apache.hc.core5.http.io.entity.StringEntity;
|
||||||
import org.apache.hc.core5.http.message.BasicClassicHttpRequest;
|
import org.apache.hc.core5.http.message.BasicClassicHttpRequest;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract base class for creating HTTP clients to interact with the Cloudflare API. Provides
|
* Abstract base class for creating HTTP clients to interact with the Cloudflare API. Provides
|
||||||
@@ -27,23 +28,20 @@ import org.apache.hc.core5.http.message.BasicClassicHttpRequest;
|
|||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
abstract class CfBasicHttpClient {
|
abstract class CfBasicHttpClient {
|
||||||
private final String baseUrl;
|
|
||||||
private final String authEmail;
|
|
||||||
private final String authKey;
|
|
||||||
|
|
||||||
|
private final String baseUrl;
|
||||||
|
private final CfDnsClientBuilder.CfAuth auth;
|
||||||
private final ObjectMapper objectMapper;
|
private final ObjectMapper objectMapper;
|
||||||
|
|
||||||
CfBasicHttpClient(String baseUrl, String authEmail, String authKey)
|
/**
|
||||||
throws IllegalArgumentException {
|
* Creates a new Cloudflare HTTP client with the specified base URL and authentication.
|
||||||
if (authEmail == null || authEmail.isBlank()) {
|
*
|
||||||
throw new IllegalArgumentException("Authentication email must not be null or blank!");
|
* @param baseUrl the base URL for the Cloudflare API
|
||||||
}
|
* @param auth the authentication mechanism to use
|
||||||
if (authKey == null || authKey.isBlank()) {
|
*/
|
||||||
throw new IllegalArgumentException("Authentication key must not be null or blank!");
|
CfBasicHttpClient(@NotNull String baseUrl, @NotNull CfDnsClientBuilder.CfAuth auth) {
|
||||||
}
|
|
||||||
this.baseUrl = baseUrl;
|
this.baseUrl = baseUrl;
|
||||||
this.authEmail = authEmail;
|
this.auth = auth;
|
||||||
this.authKey = authKey;
|
|
||||||
this.objectMapper = JsonConf.initObjectMapper();
|
this.objectMapper = JsonConf.initObjectMapper();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,8 +51,9 @@ abstract class CfBasicHttpClient {
|
|||||||
request.addHeader(HttpHeaders.ACCEPT_ENCODING, "gzip");
|
request.addHeader(HttpHeaders.ACCEPT_ENCODING, "gzip");
|
||||||
request.addHeader(HttpHeaders.ACCEPT, ContentType.APPLICATION_JSON.getMimeType());
|
request.addHeader(HttpHeaders.ACCEPT, ContentType.APPLICATION_JSON.getMimeType());
|
||||||
request.addHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.getMimeType());
|
request.addHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.getMimeType());
|
||||||
request.addHeader("X-Auth-Email", authEmail);
|
if (request instanceof ClassicHttpRequest classicRequest) {
|
||||||
request.addHeader("X-Auth-Key", authKey);
|
auth.applyAuth(classicRequest);
|
||||||
|
}
|
||||||
}).build();
|
}).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,10 @@ import codes.thischwa.cf.model.ZoneMultipleResponse;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -26,74 +28,59 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
* records and zones within the Cloudflare system, including creating, updating, retrieving, and
|
* records and zones within the Cloudflare system, including creating, updating, retrieving, and
|
||||||
* deleting DNS records.
|
* deleting DNS records.
|
||||||
*
|
*
|
||||||
* <p>Example:
|
* <p>Example with API token authentication (recommended):
|
||||||
* <pre><code>
|
* <pre><code>
|
||||||
* // Create a new CfDnsClient instance
|
* // Create a new CfDnsClient instance with API token
|
||||||
* CfDnsClient cfDnsClient = new CfDnsClient(
|
* CfDnsClient cfDnsClient = new CfDnsClientBuilder()
|
||||||
* "email@example.com",
|
* .withApiTokenAuth("your-api-token")
|
||||||
* "yourApiKey"
|
* .build();
|
||||||
* );
|
*
|
||||||
* // Retrieve a zone
|
* // Retrieve a zone
|
||||||
* ZoneEntity zone = cfDnsClient.zoneGet("example.com");
|
* ZoneEntity zone = cfDnsClient.zoneGet("example.com");
|
||||||
* System.out.println("Zone ID: " + zone.getId());
|
* System.out.println("Zone ID: " + zone.getId());
|
||||||
|
*
|
||||||
* // Retrieve records of a subdomain
|
* // Retrieve records of a subdomain
|
||||||
* List<{@link RecordEntity}> records = cfDnsClient.recordGet(zone, "sld");
|
* List<RecordEntity> records = cfDnsClient.recordList(zone, "sld");
|
||||||
* records.forEach(record ->
|
* records.forEach(record ->
|
||||||
* System.out.println("Record Type: " + record.getType() + ", Value: " + record.getContent())
|
* System.out.println("Record Type: " + record.getType() + ", Value: " + record.getContent())
|
||||||
* );
|
* );
|
||||||
|
*
|
||||||
* // Create a record for the subdomain "api"
|
* // Create a record for the subdomain "api"
|
||||||
* RecordEntity created = cfDnsClient.recordCreateSld(zone, "api", 60, RecordType.A, "192.168.1.10");
|
* RecordEntity created = cfDnsClient.recordCreateSld(zone, "api", 60, RecordType.A, "192.168.1.10");
|
||||||
* System.out.println("Created Record ID: " + created.getId());
|
* System.out.println("Created Record ID: " + created.getId());
|
||||||
* </code></pre>
|
* </code></pre>
|
||||||
|
*
|
||||||
|
* <p>Example with email/key authentication (legacy):
|
||||||
|
* <pre><code>
|
||||||
|
* CfDnsClient cfDnsClient = new CfDnsClientBuilder()
|
||||||
|
* .withEmailKeyAuth("email@example.com", "your-api-key")
|
||||||
|
* .build();
|
||||||
|
* </code></pre>
|
||||||
|
*
|
||||||
|
* <p>Example with exception throwing enabled:
|
||||||
|
* <pre><code>
|
||||||
|
* // Throws exception when results are empty
|
||||||
|
* CfDnsClient cfDnsClient = new CfDnsClientBuilder()
|
||||||
|
* .withApiTokenAuth("your-api-token")
|
||||||
|
* .withEmptyResultThrowsException(true)
|
||||||
|
* .build();
|
||||||
|
* </code></pre>
|
||||||
|
*
|
||||||
|
* <p>Example with custom base URL:
|
||||||
|
* <pre><code>
|
||||||
|
* CfDnsClient cfDnsClient = new CfDnsClientBuilder()
|
||||||
|
* .withApiTokenAuth("your-api-token")
|
||||||
|
* .withBaseUrl("https://custom-api.example.com")
|
||||||
|
* .build();
|
||||||
|
* </code></pre>
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class CfDnsClient extends CfBasicHttpClient {
|
public class CfDnsClient extends CfBasicHttpClient {
|
||||||
private static final String DEFAULT_BASEURL = "https://api.cloudflare.com/client/v4";
|
|
||||||
|
|
||||||
private final ResponseValidator responseValidator;
|
private final ResponseValidator responseValidator;
|
||||||
|
|
||||||
private final boolean emptyResultThrowsException;
|
private final boolean emptyResultThrowsException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new instance of {@code CfDnsClient}.
|
|
||||||
*
|
|
||||||
* @param authEmail The email address associated with the Cloudflare account, used for
|
|
||||||
* authentication.
|
|
||||||
* @param authKey The API key of the Cloudflare account, used as part of the authentication
|
|
||||||
* process.
|
|
||||||
*/
|
|
||||||
public CfDnsClient(String authEmail, String authKey) {
|
|
||||||
this(DEFAULT_BASEURL, authEmail, authKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new instance of {@code CfDnsClient}.
|
|
||||||
*
|
|
||||||
* @param baseUrl The base URL of the Cloudflare API to be used for requests.
|
|
||||||
* @param authEmail The email address associated with the Cloudflare account, used for
|
|
||||||
* authentication.
|
|
||||||
* @param authKey The API key of the Cloudflare account, used as part of the authentication
|
|
||||||
* process.
|
|
||||||
*/
|
|
||||||
public CfDnsClient(String baseUrl, String authEmail, String authKey) {
|
|
||||||
this(false, baseUrl, authEmail, authKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new instance of {@code CfDnsClient}.
|
|
||||||
*
|
|
||||||
* @param emptyResultThrowsException A boolean value indicating whether an exception should be
|
|
||||||
* thrown when the result is empty. Applies to both single and
|
|
||||||
* multiple result requests. Default is false.
|
|
||||||
* @param authEmail The email address associated with the Cloudflare account,
|
|
||||||
* used for authentication.
|
|
||||||
* @param authKey The API key of the Cloudflare account, used as part of the
|
|
||||||
* authentication process.
|
|
||||||
*/
|
|
||||||
public CfDnsClient(boolean emptyResultThrowsException, String authEmail, String authKey) {
|
|
||||||
this(emptyResultThrowsException, DEFAULT_BASEURL, authEmail, authKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new instance of {@code CfDnsClient}.
|
* Constructs a new instance of {@code CfDnsClient}.
|
||||||
*
|
*
|
||||||
@@ -101,14 +88,10 @@ public class CfDnsClient extends CfBasicHttpClient {
|
|||||||
* thrown when the result is empty. Applies to both single and
|
* thrown when the result is empty. Applies to both single and
|
||||||
* multiple result requests. Default is false.
|
* multiple result requests. Default is false.
|
||||||
* @param baseUrl The base URL for the Cloudflare API endpoint.
|
* @param baseUrl The base URL for the Cloudflare API endpoint.
|
||||||
* @param authEmail The email associated with the Cloudflare account for
|
* @param auth The authentication mechanism to use (ApiTokenAuth or EmailKeyAuth)
|
||||||
* authentication.
|
|
||||||
* @param authKey The API key for authenticating the client with Cloudflare
|
|
||||||
* services.
|
|
||||||
*/
|
*/
|
||||||
public CfDnsClient(boolean emptyResultThrowsException, String baseUrl, String authEmail,
|
CfDnsClient(boolean emptyResultThrowsException, String baseUrl, CfDnsClientBuilder.CfAuth auth) {
|
||||||
String authKey) {
|
super(baseUrl, auth);
|
||||||
super(baseUrl, authEmail, authKey);
|
|
||||||
this.responseValidator = new ResponseValidator(emptyResultThrowsException);
|
this.responseValidator = new ResponseValidator(emptyResultThrowsException);
|
||||||
this.emptyResultThrowsException = emptyResultThrowsException;
|
this.emptyResultThrowsException = emptyResultThrowsException;
|
||||||
}
|
}
|
||||||
@@ -316,9 +299,9 @@ public class CfDnsClient extends CfBasicHttpClient {
|
|||||||
RecordSingleResponse resp = postRequest(endpoint, rec, RecordSingleResponse.class);
|
RecordSingleResponse resp = postRequest(endpoint, rec, RecordSingleResponse.class);
|
||||||
checkResponse(resp);
|
checkResponse(resp);
|
||||||
log.info("Record {} of type {} successful created.", rec.getSld(), rec.getType());
|
log.info("Record {} of type {} successful created.", rec.getSld(), rec.getType());
|
||||||
RecordEntity record = resp.getResult();
|
RecordEntity retRec = resp.getResult();
|
||||||
record.setZoneId(zone.getId());
|
retRec.setZoneId(zone.getId());
|
||||||
return record;
|
return retRec;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -452,7 +435,10 @@ public class CfDnsClient extends CfBasicHttpClient {
|
|||||||
throws CloudflareNotFoundException {
|
throws CloudflareNotFoundException {
|
||||||
List<RecordEntity> filtered;
|
List<RecordEntity> filtered;
|
||||||
if (types != null && types.length > 0) {
|
if (types != null && types.length > 0) {
|
||||||
filtered = recs.stream().filter(rec -> Arrays.asList(types).contains(RecordType.valueOf(rec.getType()))).collect(Collectors.toList());
|
Set<RecordType> allowedTypes = new HashSet<>(Arrays.asList(types));
|
||||||
|
filtered = recs.stream()
|
||||||
|
.filter(rec -> allowedTypes.contains(RecordType.valueOf(rec.getType())))
|
||||||
|
.collect(Collectors.toList());;
|
||||||
} else {
|
} else {
|
||||||
filtered = new ArrayList<>(recs);
|
filtered = new ArrayList<>(recs);
|
||||||
}
|
}
|
||||||
@@ -506,4 +492,5 @@ public class CfDnsClient extends CfBasicHttpClient {
|
|||||||
throws CloudflareApiException {
|
throws CloudflareApiException {
|
||||||
responseValidator.validate(resp, singleResultExpected);
|
responseValidator.validate(resp, singleResultExpected);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,190 @@
|
|||||||
|
package codes.thischwa.cf;
|
||||||
|
|
||||||
|
import org.apache.hc.core5.http.ClassicHttpRequest;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder class for configuring and creating instances of {@link CfDnsClient}.
|
||||||
|
* This class provides a fluent API for customizing the client settings,
|
||||||
|
* such as the base URL and authentication mechanism.
|
||||||
|
*/
|
||||||
|
public class CfDnsClientBuilder {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default base URL for the Cloudflare v4 API requests made by the {@code CfDnsClient}.
|
||||||
|
*/
|
||||||
|
public static final String DEFAULT_BASEURL = "https://api.cloudflare.com/client/v4";
|
||||||
|
|
||||||
|
private boolean emptyResultThrowsException;
|
||||||
|
private CfAuth auth;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
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
|
||||||
|
* during operations performed by the `CfDnsClient`.
|
||||||
|
*
|
||||||
|
* @param emptyResultThrowsException a boolean flag indicating if an exception should be thrown
|
||||||
|
* when an empty result is returned. If set to `true`, operations
|
||||||
|
* that result in an empty response will throw an exception;
|
||||||
|
* otherwise, they will not.
|
||||||
|
* @return the current instance of {@code CfDnsClientBuilder}, allowing for method chaining
|
||||||
|
* to further configure the builder.
|
||||||
|
*/
|
||||||
|
public CfDnsClientBuilder withEmptyResultThrowsException(boolean emptyResultThrowsException) {
|
||||||
|
this.emptyResultThrowsException = emptyResultThrowsException;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the base URL to be used by the {@code CfDnsClient}.
|
||||||
|
* This method allows configuring the base URL for API requests, overriding any default value.
|
||||||
|
*
|
||||||
|
* @param baseUrl the base URL to be used for API requests
|
||||||
|
* @return the current instance of {@code CfDnsClientBuilder}, enabling method chaining
|
||||||
|
*/
|
||||||
|
public CfDnsClientBuilder withBaseUrl(String baseUrl) {
|
||||||
|
this.baseUrl = baseUrl;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the authentication method for the {@code CfDnsClient} to use an API token.
|
||||||
|
* This is the recommended way to authenticate with the Cloudflare API, as it provides
|
||||||
|
* enhanced security and ease of use compared to other authentication mechanisms.
|
||||||
|
*
|
||||||
|
* @param apiToken the Cloudflare API token. This token is required for authenticating
|
||||||
|
* API requests and must not be null or blank.
|
||||||
|
* @return the current instance of {@code CfDnsClientBuilder}, allowing for method chaining
|
||||||
|
* to further configure the builder.
|
||||||
|
* @throws IllegalArgumentException if the {@code apiToken} is null or blank.
|
||||||
|
*/
|
||||||
|
public CfDnsClientBuilder withApiTokenAuth(String apiToken) {
|
||||||
|
this.auth = new ApiTokenAuth(apiToken);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the authentication method for the {@code CfDnsClient} to use an email and API key.
|
||||||
|
* This approach uses the legacy authentication mechanism provided by Cloudflare, where requests
|
||||||
|
* are authenticated with a combination of an account's email address and API key.
|
||||||
|
*
|
||||||
|
* @param authEmail the email address associated with the Cloudflare account. This must not be null or blank.
|
||||||
|
* @param authKey the API key of the Cloudflare account. This must not be null or blank.
|
||||||
|
* @return the current instance of {@code CfDnsClientBuilder}, allowing for method chaining
|
||||||
|
* to further configure the builder.
|
||||||
|
* @throws IllegalArgumentException if {@code authEmail} or {@code authKey} is null or blank.
|
||||||
|
*/
|
||||||
|
public CfDnsClientBuilder withEmailKeyAuth(String authEmail, String authKey) {
|
||||||
|
this.auth = new EmailKeyAuth(authEmail, authKey);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds and returns a configured instance of {@code CfDnsClient}.
|
||||||
|
*
|
||||||
|
* <p>The method constructs a new {@code CfDnsClient} object based on the
|
||||||
|
* options set in the {@code CfDnsClientBuilder}. If no base URL has been
|
||||||
|
* explicitly configured, a default base URL will be used.
|
||||||
|
*
|
||||||
|
* @return a new instance of {@code CfDnsClient} configured with the
|
||||||
|
* specified options such as base URL, authentication details,
|
||||||
|
* and the exception-handling policy for empty results.
|
||||||
|
*/
|
||||||
|
public CfDnsClient build() {
|
||||||
|
String url = baseUrl == null ? DEFAULT_BASEURL : baseUrl;
|
||||||
|
return new CfDnsClient(emptyResultThrowsException, url, auth);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for Cloudflare authentication mechanisms.
|
||||||
|
* Implementations of this interface provide different methods of authentication
|
||||||
|
* with the Cloudflare API (e.g., API token, email/key combination).
|
||||||
|
*/
|
||||||
|
interface CfAuth {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies authentication headers to the given HTTP request.
|
||||||
|
*
|
||||||
|
* @param request the HTTP request to authenticate
|
||||||
|
*/
|
||||||
|
void applyAuth(ClassicHttpRequest request);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authentication mechanism using Cloudflare API token.
|
||||||
|
* This is the recommended authentication method for the Cloudflare API.
|
||||||
|
*/
|
||||||
|
static class ApiTokenAuth implements CfAuth {
|
||||||
|
|
||||||
|
private final String apiToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new API token authentication object.
|
||||||
|
*
|
||||||
|
* @param apiToken the Cloudflare API token
|
||||||
|
* @throws IllegalArgumentException if the API token is null or blank
|
||||||
|
*/
|
||||||
|
ApiTokenAuth(@NotNull String apiToken) {
|
||||||
|
if (apiToken.isBlank()) {
|
||||||
|
throw new IllegalArgumentException("API token must not be null or blank!");
|
||||||
|
}
|
||||||
|
this.apiToken = apiToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyAuth(ClassicHttpRequest request) {
|
||||||
|
request.addHeader("Authorization", "Bearer " + apiToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authentication mechanism using Cloudflare account email and API key.
|
||||||
|
* This is the legacy authentication method for the Cloudflare API.
|
||||||
|
*/
|
||||||
|
static class EmailKeyAuth implements CfAuth {
|
||||||
|
|
||||||
|
private final String authEmail;
|
||||||
|
private final String authKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new email/key authentication object.
|
||||||
|
*
|
||||||
|
* @param authEmail the email address associated with the Cloudflare account
|
||||||
|
* @param authKey the API key of the Cloudflare account
|
||||||
|
* @throws IllegalArgumentException if email or key is null or blank
|
||||||
|
*/
|
||||||
|
EmailKeyAuth(@NotNull String authEmail, @NotNull String authKey) {
|
||||||
|
if (authEmail.isBlank()) {
|
||||||
|
throw new IllegalArgumentException("Authentication email must not be null or blank!");
|
||||||
|
}
|
||||||
|
if (authKey.isBlank()) {
|
||||||
|
throw new IllegalArgumentException("Authentication key must not be null or blank!");
|
||||||
|
}
|
||||||
|
this.authEmail = authEmail;
|
||||||
|
this.authKey = authKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyAuth(ClassicHttpRequest request) {
|
||||||
|
request.addHeader("X-Auth-Email", authEmail);
|
||||||
|
request.addHeader("X-Auth-Key", authKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -46,18 +46,28 @@ class ResponseValidator {
|
|||||||
private void validateResultCount(AbstractResponse resp, boolean singleResultExpected)
|
private void validateResultCount(AbstractResponse resp, boolean singleResultExpected)
|
||||||
throws CloudflareApiException {
|
throws CloudflareApiException {
|
||||||
if (resp instanceof RecordMultipleResponse respMulti) {
|
if (resp instanceof RecordMultipleResponse respMulti) {
|
||||||
if (singleResultExpected && respMulti.getResultInfo().totalCount() > 1) {
|
validateMultipleResponse(respMulti, singleResultExpected);
|
||||||
throw new CloudflareApiException(
|
|
||||||
"Unexpected result count: " + respMulti.getResultInfo().totalCount());
|
|
||||||
}
|
|
||||||
if (emptyResultThrowsException && respMulti.getResultInfo().totalCount() == 0) {
|
|
||||||
throw new CloudflareNotFoundException("No result found");
|
|
||||||
}
|
|
||||||
} else if (resp instanceof AbstractSingleResponse<?> respSingle) {
|
} else if (resp instanceof AbstractSingleResponse<?> respSingle) {
|
||||||
if (emptyResultThrowsException && respSingle.getResult() == null) {
|
validateSingleResponse(respSingle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateMultipleResponse(RecordMultipleResponse response, boolean singleResultExpected)
|
||||||
|
throws CloudflareApiException {
|
||||||
|
int totalCount = response.getResultInfo().totalCount();
|
||||||
|
if (singleResultExpected && totalCount > 1) {
|
||||||
|
throw new CloudflareApiException("Unexpected result count: " + totalCount);
|
||||||
|
}
|
||||||
|
if (emptyResultThrowsException && totalCount == 0) {
|
||||||
throw new CloudflareNotFoundException("No result found");
|
throw new CloudflareNotFoundException("No result found");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void validateSingleResponse(AbstractSingleResponse<?> response)
|
||||||
|
throws CloudflareNotFoundException {
|
||||||
|
if (emptyResultThrowsException && response.getResult() == null) {
|
||||||
|
throw new CloudflareNotFoundException("No result found");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,16 +45,16 @@ public class RecordOperationsImpl implements RecordOperations {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RecordEntity update(String newContent) throws CloudflareApiException {
|
public RecordEntity update(String newContent) throws CloudflareApiException {
|
||||||
List<RecordEntity> records = get();
|
List<RecordEntity> recs = get();
|
||||||
if (records.isEmpty()) {
|
if (recs.isEmpty()) {
|
||||||
throw new CloudflareApiException("No records found to update for subdomain: " + sld);
|
throw new CloudflareApiException("No recs found to update for subdomain: " + sld);
|
||||||
}
|
}
|
||||||
if (records.size() > 1) {
|
if (recs.size() > 1) {
|
||||||
throw new CloudflareApiException("Multiple records found. Please use recordUpdate() directly for precise control.");
|
throw new CloudflareApiException("Multiple recs found. Please use recordUpdate() directly for precise control.");
|
||||||
}
|
}
|
||||||
RecordEntity record = records.get(0);
|
RecordEntity rec = recs.get(0);
|
||||||
record.setContent(newContent);
|
rec.setContent(newContent);
|
||||||
return client.recordUpdate(zone, record);
|
return client.recordUpdate(zone, rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -64,10 +64,10 @@ public class RecordEntity extends AbstractEntity {
|
|||||||
*/
|
*/
|
||||||
public static RecordEntity build(String name, RecordType type, Integer ttl, String content) {
|
public static RecordEntity build(String name, RecordType type, Integer ttl, String content) {
|
||||||
RecordEntity rec = new RecordEntity();
|
RecordEntity rec = new RecordEntity();
|
||||||
rec.setName(name);
|
rec.name = name;
|
||||||
rec.setType(type.getType());
|
rec.type = type.getType();
|
||||||
rec.setTtl(ttl);
|
rec.ttl = ttl;
|
||||||
rec.setContent(content);
|
rec.content = content;
|
||||||
return rec;
|
return rec;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ public class RecordEntity extends AbstractEntity {
|
|||||||
public static RecordEntity build(String id, String content) {
|
public static RecordEntity build(String id, String content) {
|
||||||
RecordEntity rec = new RecordEntity();
|
RecordEntity rec = new RecordEntity();
|
||||||
rec.setId(id);
|
rec.setId(id);
|
||||||
rec.setContent(content);
|
rec.content = content;
|
||||||
return rec;
|
return rec;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,8 +104,12 @@ public class RecordEntity extends AbstractEntity {
|
|||||||
throw new IllegalArgumentException("Invalid record type: " + type + ". Must be one of: "
|
throw new IllegalArgumentException("Invalid record type: " + type + ". Must be one of: "
|
||||||
+ java.util.Arrays.toString(RecordType.values()), e);
|
+ java.util.Arrays.toString(RecordType.values()), e);
|
||||||
}
|
}
|
||||||
RecordEntity rec = build(name, recordType, ttl, content);
|
RecordEntity rec = new RecordEntity();
|
||||||
rec.setId(id);
|
rec.setId(id);
|
||||||
|
rec.name = name;
|
||||||
|
rec.type = recordType.getType();
|
||||||
|
rec.ttl = ttl;
|
||||||
|
rec.content = content;
|
||||||
return rec;
|
return rec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -199,6 +199,6 @@ public enum RecordType {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getType();
|
return type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,15 +6,12 @@ package codes.thischwa.cf.model;
|
|||||||
* <p>This class contains information about the current page, page size, total pages, and result
|
* <p>This class contains information about the current page, page size, total pages, and result
|
||||||
* counts, which can be utilized in managing and navigating through paginated data.
|
* counts, which can be utilized in managing and navigating through paginated data.
|
||||||
*
|
*
|
||||||
* <ul>
|
* @param page The current page number.
|
||||||
* <li><b>page:</b> The current page number.
|
* @param perPage The number of results per page.
|
||||||
* <li><b>perPage:</b> The number of results per page.
|
* @param totalPages The total number of pages available.
|
||||||
* <li><b>totalPages:</b> The total number of pages available.
|
* @param count The number of results on the current page.
|
||||||
* <li><b>count:</b> The number of results on the current page.
|
* @param totalCount The total number of results across all pages.
|
||||||
* <li><b>totalCount:</b> The total number of results across all pages.
|
|
||||||
* </ul>
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public record ResultInfo(int page, int perPage, int totalPages, int count, int totalCount) {
|
public record ResultInfo(int page, int perPage, int totalPages, int count, int totalCount) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -22,24 +22,22 @@ public class CfClientPenTest {
|
|||||||
|
|
||||||
private static final String ZONE_STR = "mein-d-ns.de"; // existing baseline zone
|
private static final String ZONE_STR = "mein-d-ns.de"; // existing baseline zone
|
||||||
|
|
||||||
private static final String API_EMAIL = System.getenv("API_EMAIL");
|
private static final String API_TOKEN = System.getenv("API_TOKEN");
|
||||||
private static final String API_KEY = System.getenv("API_KEY");
|
|
||||||
|
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
static void checkEnv() {
|
static void checkEnv() {
|
||||||
assumeTrue(API_EMAIL != null && !API_EMAIL.isBlank(), "API_EMAIL not set; skipping pen tests");
|
assumeTrue(API_TOKEN != null && !API_TOKEN.isBlank(), "API_TOKEN not set; skipping pen tests");
|
||||||
assumeTrue(API_KEY != null && !API_KEY.isBlank(), "API_KEY not set; skipping pen tests");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private CfDnsClient newClient() {
|
private CfDnsClient newClient() {
|
||||||
return new CfDnsClient(true, API_EMAIL, API_KEY);
|
return new CfDnsClientBuilder().withEmptyResultThrowsException(true).withApiTokenAuth(API_TOKEN).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Invalid credentials should not authenticate and must throw CloudflareApiException")
|
@DisplayName("Invalid credentials should not authenticate and must throw CloudflareApiException")
|
||||||
void testInvalidCredentialsShouldFail() {
|
void testInvalidCredentialsShouldFail() {
|
||||||
// Use syntactically valid but wrong credentials
|
// Use syntactically valid but wrong credentials
|
||||||
CfDnsClient badClient = new CfDnsClient("invalid@example.com", UUID.randomUUID().toString());
|
CfDnsClient badClient = new CfDnsClientBuilder().withEmailKeyAuth("invalid@example.com", UUID.randomUUID().toString()).build();
|
||||||
assertThrows(CloudflareApiException.class, badClient::zoneList);
|
assertThrows(CloudflareApiException.class, badClient::zoneList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,15 +28,13 @@ public class CfClientTest {
|
|||||||
private static final String SLD_STR = "devsld";
|
private static final String SLD_STR = "devsld";
|
||||||
private static final int TTL = 60;
|
private static final int TTL = 60;
|
||||||
|
|
||||||
private static final String API_EMAIL = System.getenv("API_EMAIL");
|
private static final String API_TOKEN = System.getenv("API_TOKEN");
|
||||||
private static final String API_KEY = System.getenv("API_KEY");
|
|
||||||
|
|
||||||
private final CfDnsClient client = new CfDnsClient(true, API_EMAIL, API_KEY);
|
private final CfDnsClient client = new CfDnsClientBuilder().withEmptyResultThrowsException(true).withApiTokenAuth(API_TOKEN).build();
|
||||||
|
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
static void checkEnv() {
|
static void checkEnv() {
|
||||||
assumeTrue(API_EMAIL != null && !API_EMAIL.isBlank(), "API_EMAIL not set; skipping pen tests");
|
assumeTrue(API_TOKEN != null && !API_TOKEN.isBlank(), "API_TOKEN not set; skipping client tests");
|
||||||
assumeTrue(API_KEY != null && !API_KEY.isBlank(), "API_KEY not set; skipping pen tests");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -106,13 +104,13 @@ public class CfClientTest {
|
|||||||
void testDns() throws Exception {
|
void testDns() throws Exception {
|
||||||
// starting point: already existing zone 'mein-d-ns.de'
|
// starting point: already existing zone 'mein-d-ns.de'
|
||||||
ZoneEntity z = client.zoneGet(ZONE_STR);
|
ZoneEntity z = client.zoneGet(ZONE_STR);
|
||||||
assertEquals("0a83dd6e7f8c46039f2517bbded8115e", z.getId());
|
assertEquals("cf9d8b12f61423f280e0a3ea2a96d921", z.getId());
|
||||||
assertEquals("mein-d-ns.de", z.getName());
|
assertEquals("mein-d-ns.de", z.getName());
|
||||||
assertEquals("active", z.getStatus());
|
assertEquals("active", z.getStatus());
|
||||||
assertEquals(2, z.getNameServers().size());
|
assertEquals(2, z.getNameServers().size());
|
||||||
assertTrue(z.getNameServers().contains("sergi.ns.cloudflare.com"));
|
assertTrue(z.getNameServers().contains("rafe.ns.cloudflare.com"));
|
||||||
assertEquals(4, z.getOriginalNameServers().size());
|
assertTrue(z.getOriginalNameServers().size() >= 2);
|
||||||
assertTrue(z.getOriginalNameServers().contains("a.ns14.net"));
|
assertTrue(z.getOriginalNameServers().contains("blair.ns.cloudflare.com"));
|
||||||
assertNotNull(z.getActivatedOn());
|
assertNotNull(z.getActivatedOn());
|
||||||
assertNotNull(z.getModifiedOn());
|
assertNotNull(z.getModifiedOn());
|
||||||
assertNotNull(z.getCreatedOn());
|
assertNotNull(z.getCreatedOn());
|
||||||
@@ -224,14 +222,6 @@ public class CfClientTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
void testException() {
|
|
||||||
assertThrows(IllegalArgumentException.class, () -> new CfDnsClient(null, "key"));
|
|
||||||
assertThrows(IllegalArgumentException.class, () -> new CfDnsClient("email", null));
|
|
||||||
assertThrows(IllegalArgumentException.class, () -> new CfDnsClient("email", ""));
|
|
||||||
assertThrows(IllegalArgumentException.class, () -> new CfDnsClient("", "key"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testRecordEntityInvalidType() {
|
void testRecordEntityInvalidType() {
|
||||||
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class,
|
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class,
|
||||||
|
|||||||
Reference in New Issue
Block a user