Skip to content

Commit 9b77c37

Browse files
committed
Tested following flow:
1. Add dns server 2. create zone 3. add records 4. verify in powerdns 5. verify using dig
1 parent f29b8be commit 9b77c37

15 files changed

Lines changed: 428 additions & 82 deletions

File tree

api/src/main/java/org/apache/cloudstack/api/ApiConstants.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1336,6 +1336,8 @@ public class ApiConstants {
13361336
// DNS provider related
13371337
public static final String NAME_SERVERS = "nameservers";
13381338
public static final String CREDENTIALS = "credentials";
1339+
public static final String DNS_ZONE_ID = "dnszoneid";
1340+
public static final String CONTENTS = "contents";
13391341
public static final String PUBLIC_DOMAIN_SUFFIX = "publicdomainsuffix";
13401342

13411343
public static final String PARAMETER_DESCRIPTION_ACTIVATION_RULE = "Quota tariff's activation rule. It can receive a JS script that results in either " +

api/src/main/java/org/apache/cloudstack/api/command/user/dns/AddDnsServerCmd.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
package org.apache.cloudstack.api.command.user.dns;
1919

20+
import java.util.List;
21+
2022
import javax.inject.Inject;
2123

2224
import org.apache.cloudstack.api.APICommand;
@@ -51,7 +53,7 @@ public class AddDnsServerCmd extends BaseCmd {
5153
@Parameter(name = ApiConstants.PROVIDER, type = CommandType.STRING, required = true, description = "Provider type (e.g., PowerDNS)")
5254
private String provider;
5355

54-
@Parameter(name = ApiConstants.CREDENTIALS, type = CommandType.STRING, required = false, description = "API Key or Credentials for the external provider")
56+
@Parameter(name = ApiConstants.CREDENTIALS, type = CommandType.STRING, description = "API Key or Credentials for the external provider")
5557
private String credentials;
5658

5759
@Parameter(name = ApiConstants.PORT, type = CommandType.INTEGER, description = "Port number of the external DNS server")
@@ -63,8 +65,9 @@ public class AddDnsServerCmd extends BaseCmd {
6365
@Parameter(name = ApiConstants.PUBLIC_DOMAIN_SUFFIX, type = CommandType.STRING, description = "The domain suffix used for public access (e.g. public.example.com)")
6466
private String publicDomainSuffix;
6567

66-
@Parameter(name = ApiConstants.NAME_SERVERS, type = CommandType.STRING, description = "Comma separated list of name servers")
67-
private String nameServers;
68+
@Parameter(name = ApiConstants.NAME_SERVERS, type = CommandType.LIST, collectionType = CommandType.STRING,
69+
required = true, description = "Comma separated list of name servers")
70+
private List<String> nameServers;
6871

6972
/////////////////////////////////////////////////////
7073
/////////////////// Accessors ///////////////////////
@@ -89,7 +92,7 @@ public String getPublicDomainSuffix() {
8992
return publicDomainSuffix;
9093
}
9194

92-
public String getNameServers() {
95+
public List<String> getNameServers() {
9396
return nameServers;
9497
}
9598

api/src/main/java/org/apache/cloudstack/api/command/user/dns/CreateDnsRecordCmd.java

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.apache.cloudstack.api.command.user.dns;
22

3+
import java.util.List;
4+
35
import org.apache.cloudstack.api.APICommand;
46
import org.apache.cloudstack.api.ApiConstants;
57
import org.apache.cloudstack.api.ApiErrorCode;
@@ -9,35 +11,48 @@
911
import org.apache.cloudstack.api.response.DnsRecordResponse;
1012
import org.apache.cloudstack.api.response.DnsZoneResponse;
1113
import org.apache.cloudstack.context.CallContext;
14+
import org.apache.cloudstack.dns.DnsRecord;
1215

1316
import com.cloud.event.EventTypes;
17+
import com.cloud.exception.InvalidParameterValueException;
18+
import com.cloud.utils.EnumUtils;
1419

1520
@APICommand(name = "createDnsRecord", description = "Creates a DNS record directly on the provider",
1621
responseObject = DnsRecordResponse.class)
1722
public class CreateDnsRecordCmd extends BaseAsyncCmd {
1823

19-
@Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = DnsZoneResponse.class, required = true)
20-
private Long zoneId;
24+
@Parameter(name = ApiConstants.DNS_ZONE_ID, type = CommandType.UUID, entityType = DnsZoneResponse.class, required = true,
25+
description = "ID of the DNS zone")
26+
private Long dnsZoneId;
2127

2228
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "Record name")
2329
private String name;
2430

2531
@Parameter(name = ApiConstants.TYPE, type = CommandType.STRING, required = true, description = "Record type (A, CNAME)")
2632
private String type;
2733

28-
@Parameter(name = "content", type = CommandType.STRING, required = true, description = "IP or target")
29-
private String content;
34+
@Parameter(name = ApiConstants.CONTENTS, type = CommandType.LIST, collectionType = CommandType.STRING, required = true,
35+
description = "The content of the record (IP address for A/AAAA, FQDN for CNAME/NS, quoted string for TXT, etc.)")
36+
private List<String> contents;
3037

3138
@Parameter(name = "ttl", type = CommandType.INTEGER, description = "Time to live")
3239
private Integer ttl;
3340

3441
// Getters
35-
public Long getZoneId() { return zoneId; }
42+
public Long getDnsZoneId() { return dnsZoneId; }
3643
public String getName() { return name; }
37-
public String getType() { return type; }
38-
public String getContent() { return content; }
44+
45+
public List<String> getContents() { return contents; }
3946
public Integer getTtl() { return (ttl == null) ? 3600 : ttl; }
4047

48+
public DnsRecord.RecordType getType() {
49+
DnsRecord.RecordType dnsRecordType = EnumUtils.getEnumIgnoreCase(DnsRecord.RecordType.class, type);
50+
if (dnsRecordType == null) {
51+
throw new InvalidParameterValueException("Invalid value passed for record type, valid values are: " + EnumUtils.listValues(DnsRecord.RecordType.values()));
52+
}
53+
return dnsRecordType;
54+
}
55+
4156
@Override
4257
public void execute() {
4358
try {

api/src/main/java/org/apache/cloudstack/api/command/user/dns/DeleteDnsRecordCmd.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,19 @@
99
import org.apache.cloudstack.api.response.DnsZoneResponse;
1010
import org.apache.cloudstack.api.response.SuccessResponse;
1111
import org.apache.cloudstack.context.CallContext;
12+
import org.apache.cloudstack.dns.DnsRecord;
1213

1314
import com.cloud.event.EventTypes;
15+
import com.cloud.exception.InvalidParameterValueException;
16+
import com.cloud.utils.EnumUtils;
1417

1518
@APICommand(name = "deleteDnsRecord", description = "Deletes a DNS record from the external provider",
1619
responseObject = SuccessResponse.class)
1720
public class DeleteDnsRecordCmd extends BaseAsyncCmd {
1821

19-
@Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = DnsZoneResponse.class,
22+
@Parameter(name = ApiConstants.DNS_ZONE_ID, type = CommandType.UUID, entityType = DnsZoneResponse.class,
2023
required = true, description = "The ID of the DNS zone")
21-
private Long zoneId;
24+
private Long dnsZoneId;
2225

2326
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true)
2427
private String name;
@@ -27,9 +30,15 @@ public class DeleteDnsRecordCmd extends BaseAsyncCmd {
2730
private String type;
2831

2932
// Getters
30-
public Long getZoneId() { return zoneId; }
33+
public DnsRecord.RecordType getType() {
34+
DnsRecord.RecordType dnsRecordType = EnumUtils.getEnumIgnoreCase(DnsRecord.RecordType.class, type);
35+
if (dnsRecordType == null) {
36+
throw new InvalidParameterValueException("Invalid value passed for record type, valid values are: " + EnumUtils.listValues(DnsRecord.RecordType.values()));
37+
}
38+
return dnsRecordType;
39+
}
40+
public Long getDnsZoneId() { return dnsZoneId; }
3141
public String getName() { return name; }
32-
public String getType() { return type; }
3342

3443
@Override
3544
public void execute() {

api/src/main/java/org/apache/cloudstack/api/command/user/dns/ListDnsRecordsCmd.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@
1212
responseObject = DnsRecordResponse.class,
1313
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
1414
public class ListDnsRecordsCmd extends BaseListCmd {
15-
@Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = DnsZoneResponse.class,
16-
required = true, description = "the ID of the DNS zone to list records from")
17-
private Long zoneId;
1815

19-
public Long getZoneId() {
20-
return zoneId;
16+
@Parameter(name = ApiConstants.DNS_ZONE_ID, type = CommandType.UUID, entityType = DnsZoneResponse.class, required = true,
17+
description = "ID of the DNS zone to list records from")
18+
private Long dnsZoneId;
19+
20+
public Long getDnsZoneId() {
21+
return dnsZoneId;
2122
}
2223

2324
@Override

api/src/main/java/org/apache/cloudstack/api/command/user/dns/UpdateDnsServerCmd.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030
import org.apache.cloudstack.dns.DnsProviderManager;
3131
import org.apache.cloudstack.dns.DnsServer;
3232
import org.apache.commons.lang3.BooleanUtils;
33+
import org.apache.commons.lang3.StringUtils;
34+
35+
import com.cloud.utils.EnumUtils;
3336

3437
@APICommand(name = "updateDnsServer", description = "Update DNS server",
3538
responseObject = DnsServerResponse.class, requestHasSensitiveInfo = true)
@@ -67,6 +70,9 @@ public class UpdateDnsServerCmd extends BaseCmd {
6770
@Parameter(name = ApiConstants.NAME_SERVERS, type = CommandType.STRING, description = "Comma separated list of name servers")
6871
private String nameServers;
6972

73+
@Parameter(name = ApiConstants.STATE, type = CommandType.STRING, description = "Update state for the DNS server (Enabled, Disabled)")
74+
private String state;
75+
7076
/////////////////////////////////////////////////////
7177
/////////////////// Accessors ///////////////////////
7278
/////////////////////////////////////////////////////
@@ -109,4 +115,15 @@ public void execute() {
109115
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage());
110116
}
111117
}
118+
119+
public DnsServer.State getState() {
120+
if (StringUtils.isBlank(state)) {
121+
return null;
122+
}
123+
DnsServer.State dnsState = EnumUtils.getEnumIgnoreCase(DnsServer.State.class, state);
124+
if (dnsState == null) {
125+
throw new IllegalArgumentException("Invalid state value: " + state);
126+
}
127+
return dnsState;
128+
}
112129
}

api/src/main/java/org/apache/cloudstack/api/response/DnsRecordResponse.java

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
package org.apache.cloudstack.api.response;
1919

20+
import java.util.List;
21+
2022
import org.apache.cloudstack.api.ApiConstants;
2123
import org.apache.cloudstack.api.BaseResponse;
2224
import org.apache.cloudstack.dns.DnsRecord;
@@ -27,45 +29,29 @@
2729
public class DnsRecordResponse extends BaseResponse {
2830

2931
@SerializedName(ApiConstants.NAME)
30-
@Param(description = "the name of the DNS record")
32+
@Param(description = "The record name (e.g., www.example.com.)")
3133
private String name;
3234

3335
@SerializedName(ApiConstants.TYPE)
34-
@Param(description = "the type of the DNS record (A, CNAME, etc)")
35-
private String type;
36+
@Param(description = "The record type (e.g., A, CNAME, TXT)")
37+
private DnsRecord.RecordType type;
3638

37-
@SerializedName("content")
38-
@Param(description = "the content of the record (IP address or target)")
39-
private String content;
39+
@SerializedName("contents")
40+
@Param(description = "The contents of the record (IP address or target)")
41+
private List<String> contents;
4042

4143
@SerializedName("ttl")
42-
@Param(description = "the time to live (TTL) in seconds")
44+
@Param(description = "Time to live (TTL) in seconds")
4345
private Integer ttl;
4446

45-
@SerializedName(ApiConstants.ZONE_ID)
46-
@Param(description = "the ID of the zone this record belongs to")
47-
private String zoneId;
48-
49-
@SerializedName("sourceid")
50-
@Param(description = "the external ID of the record on the provider")
51-
private String sourceId;
52-
5347
public DnsRecordResponse() {
5448
super();
5549
setObjectName("dnsrecord");
5650
}
5751

5852
// Setters
5953
public void setName(String name) { this.name = name; }
60-
61-
// Accepts String or Enum.toString()
62-
public void setType(String type) { this.type = type; }
63-
public void setType(DnsRecord.RecordType type) {
64-
this.type = (type != null) ? type.name() : null;
65-
}
66-
67-
public void setContent(String content) { this.content = content; }
54+
public void setType(DnsRecord.RecordType type) { this.type = type; }
55+
public void setContent(List<String> contents) { this.contents = contents; }
6856
public void setTtl(Integer ttl) { this.ttl = ttl; }
69-
public void setZoneId(String zoneId) { this.zoneId = zoneId; }
70-
public void setSourceId(String sourceId) { this.sourceId = sourceId; }
7157
}

api/src/main/java/org/apache/cloudstack/dns/DnsProvider.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,8 @@ public interface DnsProvider extends Adapter {
3131
void provisionZone(DnsServer server, DnsZone zone);
3232
void deleteZone(DnsServer server, DnsZone zone) ;
3333

34-
DnsRecord createRecord(DnsServer server, DnsZone zone, DnsRecord record);
35-
boolean updateRecord(DnsServer server, DnsZone zone, DnsRecord record);
36-
boolean deleteRecord(DnsServer server, DnsZone zone, DnsRecord record);
37-
34+
void addRecord(DnsServer server, DnsZone zone, DnsRecord record);
3835
List<DnsRecord> listRecords(DnsServer server, DnsZone zone);
36+
void updateRecord(DnsServer server, DnsZone zone, DnsRecord record);
37+
void deleteRecord(DnsServer server, DnsZone zone, DnsRecord record);
3938
}

api/src/main/java/org/apache/cloudstack/dns/DnsProviderManager.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,17 +56,16 @@ public interface DnsProviderManager extends Manager, PluggableService {
5656
DnsZone updateDnsZone(UpdateDnsZoneCmd cmd);
5757
boolean deleteDnsZone(Long id);
5858
ListResponse<DnsZoneResponse> listDnsZones(ListDnsZonesCmd cmd);
59-
6059
DnsZone getDnsZone(long id);
6160

6261
DnsRecordResponse createDnsRecord(CreateDnsRecordCmd cmd);
6362
boolean deleteDnsRecord(DeleteDnsRecordCmd cmd);
64-
6563
ListResponse<DnsRecordResponse> listDnsRecords(ListDnsRecordsCmd cmd);
6664

6765
List<String> listProviderNames();
6866

6967

7068
// Helper to create the response object
7169
DnsZoneResponse createDnsZoneResponse(DnsZone zone);
70+
DnsRecordResponse createDnsRecordResponse(DnsRecord record);
7271
}

api/src/main/java/org/apache/cloudstack/dns/DnsRecord.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
package org.apache.cloudstack.dns;
1919

20+
import java.util.List;
21+
2022
import com.cloud.utils.exception.CloudRuntimeException;
2123

2224
public class DnsRecord {
@@ -36,16 +38,16 @@ public static RecordType fromString(String type) {
3638
}
3739

3840
private String name;
39-
private RecordType type; // Enforced Enum here
40-
private String content;
41+
private RecordType type;
42+
private List<String> contents;
4143
private int ttl;
4244

4345
public DnsRecord() {}
4446

45-
public DnsRecord(String name, RecordType type, String content, int ttl) {
47+
public DnsRecord(String name, RecordType type, List<String> contents, int ttl) {
4648
this.name = name;
4749
this.type = type;
48-
this.content = content;
50+
this.contents = contents;
4951
this.ttl = ttl;
5052
}
5153

@@ -56,8 +58,8 @@ public DnsRecord(String name, RecordType type, String content, int ttl) {
5658
public RecordType getType() { return type; }
5759
public void setType(RecordType type) { this.type = type; }
5860

59-
public String getContent() { return content; }
60-
public void setContent(String content) { this.content = content; }
61+
public List<String> getContents() { return contents; }
62+
public void setContents(List<String> contents) { this.contents = contents; }
6163

6264
public int getTtl() { return ttl; }
6365
public void setTtl(int ttl) { this.ttl = ttl; }

0 commit comments

Comments
 (0)