Skip to content

Commit 68b2961

Browse files
authored
feat: allow custom group.id and application.id (#25)
1 parent 04d35ff commit 68b2961

21 files changed

+1163
-26
lines changed

docs/confluent-cloud.md

-3
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,4 @@ Congrats! You're now using `kafka-gitops` to manage your Confluent Cloud cluster
109109

110110
Welcome to GitOps!
111111

112-
113-
114-
115112
[installation]: /installation.md

docs/permissions.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Permissions
22

3-
When running against a secure Kafka cluster, kafka-gitops needs to be authorized to perform actions against the cluster. This can be either a super user defined by the Kafka cluster or a custom user with specific permissions.
3+
When running against a secured Kafka cluster, `kafka-gitops` needs to be authorized to perform actions against the cluster. This can either be a super user defined by the Kafka cluster or a custom user with specific permissions.
44

55
## Example
66

docs/quick-start.md

+3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ For our quick start example, open a terminal where your `state.yaml` file is loc
3333
export KAFKA_BOOTSTRAP_SERVERS=localhost:9092
3434
```
3535

36+
!> **NOTE**: If running `kafka-gitops` against a secured Kafka cluster, it must be run with super user credentials or a user with special ACLs. [Read more on our permissions page][permissions].
37+
3638
## Validate
3739
We can validate the desired state file conforms to the [specification][specification]. To do this, run:
3840

@@ -141,5 +143,6 @@ org.apache.kafka.common.errors.PolicyViolationException: Topic replication facto
141143
Congrats! You've successfully started using GitOps strategies to manage your cluster. If you have security on your cluster, read the [services][services] page to start defining services.
142144

143145
[ccloud]: /confluent-cloud.md
146+
[permissions]: /permissions.md
144147
[specification]: /specification.md
145148
[services]: /services.md

docs/services.md

+56-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ A basic example shown below defines one topic, `test-topic`, and one service, `m
88

99
The service `my-application` both consumes from and produces to `test-topic`. This will generate the necessary ACLs for `my-application` to do this.
1010

11-
?> **Note**: If using Confluent Cloud, omit the principal field.
11+
?> **NOTE**: If using Confluent Cloud, omit the principal field.
1212

1313
```yaml
1414
topics:
@@ -32,7 +32,23 @@ Behind the scenes, this will generate three ACLs:
3232
- `WRITE` for topic `test-topic`
3333
- `READ` for consumer group `my-application`
3434

35-
!> Currently, consumer `group.id` must match the service name.
35+
#### Group ID
36+
37+
The `group.id` used for consumer ACLs defaults to the service name. You can override this by specifying the `group-id` property, as shown below:
38+
39+
```yaml
40+
services:
41+
my-application:
42+
type: application
43+
principal: User:myapp
44+
group-id: my-application-service
45+
consumes:
46+
- test-topic
47+
produces:
48+
- test-topic
49+
```
50+
51+
This would allow your consumer group to access kafka using `my-application-service` as the `group.id`.
3652

3753
## Kafka Streams Example
3854

@@ -63,6 +79,24 @@ Behind the scenes, this generates ACLs such as:
6379
- `READ` for consumer group `my-stream`
6480
- Various ACLs for Kafka streams internal topic management
6581

82+
#### Application ID
83+
84+
The `application.id` used for streams ACLs defaults to the service name. You can override this by specifying the `application-id` property, as shown below:
85+
86+
```yaml
87+
services:
88+
my-stream:
89+
type: kafka-streams
90+
principal: User:mystream
91+
application-id: my-stream-application
92+
consumes:
93+
- test-topic
94+
produces:
95+
- test-topic
96+
```
97+
98+
This would allow your streams application to access kafka using `my-stream-application` as the `application.id`.
99+
66100
## Kafka Connect Example
67101

68102
A basic example which defines one Kafka Connect cluster that has one connector running.
@@ -116,3 +150,23 @@ Behind the scenes, this generates ACLs such as:
116150
- `READ` for the consumer group `connect-rabbitmq-sink`
117151
- `READ` and `WRITE` for the internal kafka connect topics
118152
- `READ` for the consumer group `my-connect-cluster`
153+
154+
#### Group ID
155+
156+
The `group.id` used for the connect cluster ACLs defaults to the service name. You can override this by specifying the `group-id` property, as shown below:
157+
158+
```yaml
159+
services:
160+
my-connect-cluster:
161+
type: kafka-connect
162+
principal: User:myconnectcluster
163+
group-id: kafka-connect-cluster
164+
connectors:
165+
rabbitmq-sink:
166+
consumes:
167+
- rabbitmq-data
168+
```
169+
170+
This allows your connect cluster to access kafka using `kafka-connect-cluster` as the `group.id`.
171+
172+
!> **NOTE**: The `group-id` setting only affects the connect cluster `group.id`, and not any sink connector group IDs.

docs/specification.md

+9-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
This document describes the specification for how to write your Kafka cluster's desired state file. This currently must be a `YAML` file.
44

5-
?> Current version: `1`
5+
?> Current version: `1.0.1`
66

77
The desired state file consists of:
88

@@ -63,17 +63,18 @@ There are currently three service types:
6363
- `kafka-connect`
6464
- `kafka-streams`
6565

66-
?> **NOTE**: If using Confluent Cloud, omit the `principal` fields.
66+
!> **NOTE**: If using Confluent Cloud, omit the `principal` fields.
6767

6868
**Example application**:
6969

70-
!> **NOTE**: Currently, the service name must match the consumer `group.id`.
70+
?> **NOTE**: The `group-id` property is optional and defaults to the service name.
7171

7272
```yaml
7373
services:
7474
my-application-name:
7575
type: application
7676
principal: User:my-application-principal
77+
group-id: optional-group-id-override
7778
produces:
7879
- topic-name-one
7980
consumes:
@@ -83,13 +84,14 @@ services:
8384

8485
**Example kafka connect cluster**:
8586

86-
!> **NOTE**: Currently, the service name must match the connect cluster `group.id`.
87+
?> **NOTE**: The `group-id` property is optional and defaults to the service name.
8788

8889
```yaml
8990
services:
9091
my-kafka-connect-cluster-name:
9192
type: kafka-connect
9293
principal: User:my-connect-principal
94+
group-id: optional-group-id-override
9395
connectors:
9496
my-source-connector-name:
9597
produces:
@@ -101,20 +103,21 @@ services:
101103

102104
**Example kafka streams application**:
103105

104-
!> **NOTE**: Currently, the service name must match the streams `application.id`.
106+
?> **NOTE**: The `application-id` property is optional and defaults to the service name.
105107

106108
```yaml
107109
services:
108110
my-kafka-streams-name:
109111
type: kafka-streams
110112
principal: User:my-streams-principal
113+
application-id: optional-application-id-override
111114
produces:
112115
- topic-name-one
113116
consumes:
114117
- topic-name-two
115118
```
116119

117-
Under the cover, `kafka-gitops` generates ACLs based on these definitions.
120+
Behind the scenes, `kafka-gitops` generates ACLs based on these definitions.
118121

119122
## Users
120123

src/main/java/com/devshawn/kafka/gitops/domain/state/service/ApplicationService.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.devshawn.kafka.gitops.domain.state.AclDetails;
44
import com.devshawn.kafka.gitops.domain.state.ServiceDetails;
5+
import com.fasterxml.jackson.annotation.JsonProperty;
56
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
67
import org.inferred.freebuilder.FreeBuilder;
78

@@ -15,6 +16,9 @@ public abstract class ApplicationService extends ServiceDetails {
1516

1617
public abstract Optional<String> getPrincipal();
1718

19+
@JsonProperty("group-id")
20+
public abstract Optional<String> getGroupId();
21+
1822
public abstract List<String> getProduces();
1923

2024
public abstract List<String> getConsumes();
@@ -25,7 +29,8 @@ public List<AclDetails.Builder> getAcls(String serviceName) {
2529
getProduces().forEach(topic -> acls.add(generateWriteACL(topic, getPrincipal())));
2630
getConsumes().forEach(topic -> acls.add(generateReadAcl(topic, getPrincipal())));
2731
if (!getConsumes().isEmpty()) {
28-
acls.add(generateConsumerGroupAcl(serviceName, getPrincipal(), "READ"));
32+
String groupId = getGroupId().isPresent() ? getGroupId().get() : serviceName;
33+
acls.add(generateConsumerGroupAcl(groupId, getPrincipal(), "READ"));
2934
}
3035
return acls;
3136
}

src/main/java/com/devshawn/kafka/gitops/domain/state/service/KafkaConnectService.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import com.devshawn.kafka.gitops.domain.state.AclDetails;
55
import com.devshawn.kafka.gitops.domain.state.ServiceDetails;
6+
import com.fasterxml.jackson.annotation.JsonProperty;
67
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
78
import org.inferred.freebuilder.FreeBuilder;
89

@@ -15,6 +16,9 @@
1516
@JsonDeserialize(builder = KafkaConnectService.Builder.class)
1617
public abstract class KafkaConnectService extends ServiceDetails {
1718

19+
@JsonProperty("group-id")
20+
public abstract Optional<String> getGroupId();
21+
1822
public abstract Optional<String> getPrincipal();
1923

2024
public abstract List<String> getProduces();
@@ -30,14 +34,15 @@ public List<AclDetails.Builder> getAcls(String serviceName) {
3034
}
3135

3236
private List<AclDetails.Builder> getConnectWorkerAcls(String serviceName) {
37+
String groupId = getGroupId().isPresent() ? getGroupId().get() : serviceName;
3338
List<AclDetails.Builder> acls = new ArrayList<>();
3439
acls.add(generateReadAcl(String.format("connect-configs-%s", serviceName), getPrincipal()));
3540
acls.add(generateReadAcl(String.format("connect-offsets-%s", serviceName), getPrincipal()));
3641
acls.add(generateReadAcl(String.format("connect-status-%s", serviceName), getPrincipal()));
3742
acls.add(generateWriteACL(String.format("connect-configs-%s", serviceName), getPrincipal()));
3843
acls.add(generateWriteACL(String.format("connect-offsets-%s", serviceName), getPrincipal()));
3944
acls.add(generateWriteACL(String.format("connect-status-%s", serviceName), getPrincipal()));
40-
acls.add(generateConsumerGroupAcl(serviceName, getPrincipal(), "READ"));
45+
acls.add(generateConsumerGroupAcl(groupId, getPrincipal(), "READ"));
4146
getConnectors().forEach((connectorName, connector) -> acls.addAll(connector.getAcls(connectorName, getPrincipal())));
4247
return acls;
4348
}

src/main/java/com/devshawn/kafka/gitops/domain/state/service/KafkaStreamsService.java

+15-10
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.devshawn.kafka.gitops.domain.state.AclDetails;
44
import com.devshawn.kafka.gitops.domain.state.ServiceDetails;
5+
import com.fasterxml.jackson.annotation.JsonProperty;
56
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
67
import org.inferred.freebuilder.FreeBuilder;
78

@@ -15,6 +16,9 @@ public abstract class KafkaStreamsService extends ServiceDetails {
1516

1617
public abstract Optional<String> getPrincipal();
1718

19+
@JsonProperty("application-id")
20+
public abstract Optional<String> getApplicationId();
21+
1822
public abstract List<String> getProduces();
1923

2024
public abstract List<String> getConsumes();
@@ -29,17 +33,18 @@ public List<AclDetails.Builder> getAcls(String serviceName) {
2933
}
3034

3135
private List<AclDetails.Builder> getInternalAcls(String serviceName) {
36+
String applicationId = getApplicationId().isPresent() ? getApplicationId().get() : serviceName;
3237
List<AclDetails.Builder> acls = new ArrayList<>();
33-
acls.add(generatePrefixedTopicACL(serviceName, getPrincipal(), "READ"));
34-
acls.add(generatePrefixedTopicACL(serviceName, getPrincipal(), "WRITE"));
35-
acls.add(generatePrefixedTopicACL(serviceName, getPrincipal(), "DESCRIBE"));
36-
acls.add(generatePrefixedTopicACL(serviceName, getPrincipal(), "DELETE"));
37-
acls.add(generatePrefixedTopicACL(serviceName, getPrincipal(), "CREATE"));
38-
acls.add(generatePrefixedTopicACL(serviceName, getPrincipal(), "ALTER"));
39-
acls.add(generatePrefixedTopicACL(serviceName, getPrincipal(), "ALTER_CONFIGS"));
40-
acls.add(generatePrefixedTopicACL(serviceName, getPrincipal(), "DESCRIBE_CONFIGS"));
41-
acls.add(generateConsumerGroupAcl(serviceName, getPrincipal(), "READ"));
42-
acls.add(generateConsumerGroupAcl(serviceName, getPrincipal(), "DESCRIBE"));
38+
acls.add(generatePrefixedTopicACL(applicationId, getPrincipal(), "READ"));
39+
acls.add(generatePrefixedTopicACL(applicationId, getPrincipal(), "WRITE"));
40+
acls.add(generatePrefixedTopicACL(applicationId, getPrincipal(), "DESCRIBE"));
41+
acls.add(generatePrefixedTopicACL(applicationId, getPrincipal(), "DELETE"));
42+
acls.add(generatePrefixedTopicACL(applicationId, getPrincipal(), "CREATE"));
43+
acls.add(generatePrefixedTopicACL(applicationId, getPrincipal(), "ALTER"));
44+
acls.add(generatePrefixedTopicACL(applicationId, getPrincipal(), "ALTER_CONFIGS"));
45+
acls.add(generatePrefixedTopicACL(applicationId, getPrincipal(), "DESCRIBE_CONFIGS"));
46+
acls.add(generateConsumerGroupAcl(applicationId, getPrincipal(), "READ"));
47+
acls.add(generateConsumerGroupAcl(applicationId, getPrincipal(), "DESCRIBE"));
4348
return acls;
4449
}
4550

src/test/groovy/com/devshawn/kafka/gitops/ApplyCommandIntegrationSpec.groovy

+6-1
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,15 @@ class ApplyCommandIntegrationSpec extends Specification {
4848
planFile << [
4949
"simple",
5050
"application-service",
51+
"kafka-streams-service",
52+
"kafka-connect-service",
5153
"multi-file",
5254
"simple-users",
5355
"custom-service-acls",
54-
"custom-user-acls"
56+
"custom-user-acls",
57+
"custom-group-id-application",
58+
"custom-group-id-connect",
59+
"custom-application-id-streams"
5560
]
5661
}
5762

src/test/groovy/com/devshawn/kafka/gitops/PlanCommandIntegrationSpec.groovy

+4-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,10 @@ class PlanCommandIntegrationSpec extends Specification {
5858
"multi-file",
5959
"simple-users",
6060
"custom-service-acls",
61-
"custom-user-acls"
61+
"custom-user-acls",
62+
"custom-group-id-application",
63+
"custom-group-id-connect",
64+
"custom-application-id-streams"
6265
]
6366
}
6467

0 commit comments

Comments
 (0)