Skip to content

Commit eeeccda

Browse files
authored
KafkaTopicACLs: filter by valid/invalid workloads (#110)
* KafkaTopicACLs: filter by valid/invalid workloads Fixes #71 * Workloads include jobs ...
1 parent 111885b commit eeeccda

File tree

9 files changed

+305
-4
lines changed

9 files changed

+305
-4
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
apiVersion: nais.io/v1alpha1
2+
kind: Application
3+
metadata:
4+
name: app1
5+
spec:
6+
image: navikt/app-name:latest
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
apiVersion: kafka.nais.io/v1
2+
kind: Topic
3+
metadata:
4+
labels:
5+
team: devteam
6+
name: dokument
7+
namespace: devteam
8+
resourceVersion: "467599169"
9+
uid: 09047c15-c504-42d0-a636-286cd4a7c0ea
10+
spec:
11+
acl:
12+
- access: read
13+
application: "*"
14+
team: devteam
15+
- access: readwrite
16+
application: all
17+
team: "*"
18+
- access: readwrite
19+
application: app1
20+
team: devteam
21+
- access: readwrite
22+
application: app2
23+
team: otherteam
24+
- access: readwrite
25+
application: missing
26+
team: devteam
27+
- access: readwrite
28+
application: missing
29+
team: otherteam
30+
- access: readwrite
31+
application: jobname-1
32+
team: otherteam
33+
config:
34+
cleanupPolicy: delete
35+
localRetentionBytes: -2
36+
localRetentionHours: -2
37+
maxMessageBytes: 1048588
38+
minimumInSyncReplicas: 1
39+
partitions: 1
40+
replication: 3
41+
retentionBytes: -1
42+
retentionHours: 720
43+
segmentHours: 168
44+
pool: dev
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
apiVersion: nais.io/v1alpha1
2+
kind: Application
3+
metadata:
4+
name: app2
5+
spec:
6+
image: navikt/app-name:latest
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
apiVersion: nais.io/v1
2+
kind: Naisjob
3+
metadata:
4+
name: jobname-1
5+
spec:
6+
image: europe-north1-docker.pkg.dev/nais/navikt/app-name:latest
7+
schedule: "0 0 * * *"
+209
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
Helper.readK8sResources("k8s_resources/kafka_acl_filter")
2+
3+
local team = Team.new("devteam", "purpose", "#slack-channel")
4+
local user = User.new()
5+
6+
Test.gql("topic without filter", function(t)
7+
t.addHeader("x-user-email", user:email())
8+
9+
t.query([[
10+
{
11+
team(slug: "devteam") {
12+
environment(name: "dev") {
13+
kafkaTopic(name: "dokument") {
14+
acl {
15+
nodes {
16+
workloadName
17+
teamName
18+
access
19+
}
20+
}
21+
}
22+
}
23+
}
24+
}
25+
]])
26+
27+
t.check {
28+
data = {
29+
team = {
30+
environment = {
31+
kafkaTopic = {
32+
acl = {
33+
nodes = {
34+
{ workloadName = "*", teamName = "devteam", access = "read" },
35+
{ workloadName = "all", teamName = "*", access = "readwrite" },
36+
{ workloadName = "app1", teamName = "devteam", access = "readwrite" },
37+
{ workloadName = "app2", teamName = "otherteam", access = "readwrite" },
38+
{ workloadName = "jobname-1", teamName = "otherteam", access = "readwrite" },
39+
{ workloadName = "missing", teamName = "devteam", access = "readwrite" },
40+
{ workloadName = "missing", teamName = "otherteam", access = "readwrite" },
41+
},
42+
},
43+
},
44+
},
45+
},
46+
},
47+
}
48+
end)
49+
50+
Test.gql("topic filtering for workload", function(t)
51+
t.addHeader("x-user-email", user:email())
52+
53+
t.query([[
54+
{
55+
team(slug: "devteam") {
56+
environment(name: "dev") {
57+
kafkaTopic(name: "dokument") {
58+
acl(filter: { workload: "app1" }) {
59+
nodes {
60+
workloadName
61+
teamName
62+
access
63+
}
64+
}
65+
}
66+
}
67+
}
68+
}
69+
]])
70+
71+
t.check {
72+
data = {
73+
team = {
74+
environment = {
75+
kafkaTopic = {
76+
acl = {
77+
nodes = {
78+
{ workloadName = "*", teamName = "devteam", access = "read" },
79+
{ workloadName = "app1", teamName = "devteam", access = "readwrite" },
80+
},
81+
},
82+
},
83+
},
84+
},
85+
},
86+
}
87+
end)
88+
89+
Test.gql("topic filtering for team", function(t)
90+
t.addHeader("x-user-email", user:email())
91+
92+
t.query([[
93+
{
94+
team(slug: "devteam") {
95+
environment(name: "dev") {
96+
kafkaTopic(name: "dokument") {
97+
acl(filter: { team: "otherteam" }) {
98+
nodes {
99+
workloadName
100+
teamName
101+
access
102+
}
103+
}
104+
}
105+
}
106+
}
107+
}
108+
]])
109+
110+
t.check {
111+
data = {
112+
team = {
113+
environment = {
114+
kafkaTopic = {
115+
acl = {
116+
nodes = {
117+
{ workloadName = "all", teamName = "*", access = "readwrite" },
118+
{ workloadName = "app2", teamName = "otherteam", access = "readwrite" },
119+
{ workloadName = "jobname-1", teamName = "otherteam", access = "readwrite" },
120+
{ workloadName = "missing", teamName = "otherteam", access = "readwrite" },
121+
},
122+
},
123+
},
124+
},
125+
},
126+
},
127+
}
128+
end)
129+
130+
Test.gql("topic filtering for valid workloads", function(t)
131+
t.addHeader("x-user-email", user:email())
132+
133+
t.query([[
134+
{
135+
team(slug: "devteam") {
136+
environment(name: "dev") {
137+
kafkaTopic(name: "dokument") {
138+
acl(filter: { validWorkloads: true }) {
139+
nodes {
140+
workloadName
141+
teamName
142+
access
143+
}
144+
}
145+
}
146+
}
147+
}
148+
}
149+
]])
150+
151+
t.check {
152+
data = {
153+
team = {
154+
environment = {
155+
kafkaTopic = {
156+
acl = {
157+
nodes = {
158+
{ workloadName = "*", teamName = "devteam", access = "read" },
159+
{ workloadName = "all", teamName = "*", access = "readwrite" },
160+
{ workloadName = "app1", teamName = "devteam", access = "readwrite" },
161+
{ workloadName = "app2", teamName = "otherteam", access = "readwrite" },
162+
{ workloadName = "jobname-1", teamName = "otherteam", access = "readwrite" },
163+
},
164+
},
165+
},
166+
},
167+
},
168+
},
169+
}
170+
end)
171+
172+
Test.gql("topic filtering for invalid workloads", function(t)
173+
t.addHeader("x-user-email", user:email())
174+
175+
t.query([[
176+
{
177+
team(slug: "devteam") {
178+
environment(name: "dev") {
179+
kafkaTopic(name: "dokument") {
180+
acl(filter: { validWorkloads: false }) {
181+
nodes {
182+
workloadName
183+
teamName
184+
access
185+
}
186+
}
187+
}
188+
}
189+
}
190+
}
191+
]])
192+
193+
t.check {
194+
data = {
195+
team = {
196+
environment = {
197+
kafkaTopic = {
198+
acl = {
199+
nodes = {
200+
{ workloadName = "missing", teamName = "devteam", access = "readwrite" },
201+
{ workloadName = "missing", teamName = "otherteam", access = "readwrite" },
202+
},
203+
},
204+
},
205+
},
206+
},
207+
},
208+
}
209+
end)

internal/graph/gengql/generated.go

+9-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/graph/schema/kafka.graphqls

+1
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ type KafkaTopicAclEdge {
119119
input KafkaTopicAclFilter {
120120
team: Slug
121121
workload: String
122+
validWorkloads: Boolean
122123
}
123124

124125
input KafkaTopicOrder {

internal/persistence/kafkatopic/models.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,9 @@ func (e KafkaTopicACLOrderField) MarshalGQL(w io.Writer) {
140140
}
141141

142142
type KafkaTopicACLFilter struct {
143-
Team *slug.Slug `json:"team,omitempty"`
144-
Workload *string `json:"workload,omitempty"`
143+
Team *slug.Slug `json:"team,omitempty"`
144+
Workload *string `json:"workload,omitempty"`
145+
ValidWorkloads *bool `json:"validWorkloads,omitempty"`
145146
}
146147

147148
func toKafkaTopicConfiguration(cfg *kafka_nais_io_v1.Config) *KafkaTopicConfiguration {

internal/persistence/kafkatopic/sortfilter.go

+20-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ import (
55
"strings"
66

77
"github.com/nais/api/internal/graph/sortfilter"
8+
"github.com/nais/api/internal/slug"
9+
"github.com/nais/api/internal/workload/application"
10+
"github.com/nais/api/internal/workload/job"
811
)
912

1013
var (
@@ -22,7 +25,7 @@ func init() {
2225

2326
SortFilterTopicACL.RegisterSort("TOPIC_NAME", func(ctx context.Context, a, b *KafkaTopicACL) int {
2427
return strings.Compare(a.TopicName, b.TopicName)
25-
})
28+
}, "CONSUMER", "TEAM_SLUG", "ACCESS")
2629
SortFilterTopicACL.RegisterSort("TEAM_SLUG", func(ctx context.Context, a, b *KafkaTopicACL) int {
2730
return strings.Compare(a.TeamName, b.TeamName)
2831
})
@@ -42,6 +45,22 @@ func init() {
4245
return false
4346
}
4447

48+
if filter.ValidWorkloads != nil {
49+
if v.WorkloadName == "*" || v.WorkloadName == "" {
50+
return *filter.ValidWorkloads
51+
}
52+
if v.TeamName == "*" || v.TeamName == "" {
53+
return *filter.ValidWorkloads
54+
}
55+
56+
if _, err := application.Get(ctx, slug.Slug(v.TeamName), v.EnvironmentName, v.WorkloadName); err != nil {
57+
if _, err := job.Get(ctx, slug.Slug(v.TeamName), v.EnvironmentName, v.WorkloadName); err != nil {
58+
return !*filter.ValidWorkloads
59+
}
60+
}
61+
return *filter.ValidWorkloads
62+
}
63+
4564
return true
4665
})
4766
}

0 commit comments

Comments
 (0)