summaryrefslogtreecommitdiffstats
path: root/flags
diff options
context:
space:
mode:
authorMorten Tokle <mortent@vespa.ai>2024-04-08 08:44:24 +0200
committerMorten Tokle <mortent@vespa.ai>2024-04-08 10:53:35 +0200
commitfbdcc1a57406d869bac44ff80f666b0ced77e162 (patch)
tree325c5779a60dccde66011e1c7fff9c8153cb22e4 /flags
parent5b728f052f9cc03e20ef88ce2e713b262ac24a0b (diff)
Flag to support role definitions
Diffstat (limited to 'flags')
-rw-r--r--flags/src/main/java/com/yahoo/vespa/flags/Flags.java9
-rw-r--r--flags/src/main/java/com/yahoo/vespa/flags/custom/Role.java55
-rw-r--r--flags/src/main/java/com/yahoo/vespa/flags/custom/RoleList.java45
-rw-r--r--flags/src/test/java/com/yahoo/vespa/flags/custom/RoleTest.java56
4 files changed, 163 insertions, 2 deletions
diff --git a/flags/src/main/java/com/yahoo/vespa/flags/Flags.java b/flags/src/main/java/com/yahoo/vespa/flags/Flags.java
index e038c96bf99..03a713f37f5 100644
--- a/flags/src/main/java/com/yahoo/vespa/flags/Flags.java
+++ b/flags/src/main/java/com/yahoo/vespa/flags/Flags.java
@@ -3,6 +3,7 @@ package com.yahoo.vespa.flags;
import com.yahoo.component.Vtag;
import com.yahoo.vespa.defaults.Defaults;
+import com.yahoo.vespa.flags.custom.RoleList;
import java.time.Instant;
import java.time.LocalDate;
@@ -14,8 +15,6 @@ import java.util.TreeMap;
import java.util.function.Predicate;
import static com.yahoo.vespa.flags.Dimension.APPLICATION;
-import static com.yahoo.vespa.flags.Dimension.ARCHITECTURE;
-import static com.yahoo.vespa.flags.Dimension.CLAVE;
import static com.yahoo.vespa.flags.Dimension.CLOUD_ACCOUNT;
import static com.yahoo.vespa.flags.Dimension.CONSOLE_USER_EMAIL;
import static com.yahoo.vespa.flags.Dimension.HOSTNAME;
@@ -417,6 +416,12 @@ public class Flags {
"Whether to use athenz as node identity provider",
"Takes effect on next identity refresh", HOSTNAME);
+ public static UnboundJacksonFlag<RoleList> ROLE_DEFINITIONS = defineJacksonFlag(
+ "role-definitions", RoleList.empty(), RoleList.class,
+ List.of("mortent"), "2024-04-05", "2024-10-01",
+ "Role definitions for the system",
+ "Takes effect immediately");
+
/** WARNING: public for testing: All flags should be defined in {@link Flags}. */
public static UnboundBooleanFlag defineFeatureFlag(String flagId, boolean defaultValue, List<String> owners,
String createdAt, String expiresAt, String description,
diff --git a/flags/src/main/java/com/yahoo/vespa/flags/custom/Role.java b/flags/src/main/java/com/yahoo/vespa/flags/custom/Role.java
new file mode 100644
index 00000000000..93845b6f59d
--- /dev/null
+++ b/flags/src/main/java/com/yahoo/vespa/flags/custom/Role.java
@@ -0,0 +1,55 @@
+// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+package com.yahoo.vespa.flags.custom;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.util.List;
+import java.util.Objects;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonInclude(value = JsonInclude.Include.NON_NULL)
+public class Role {
+ @JsonProperty("name")
+ private final String name;
+ @JsonProperty("members")
+ private final List<String> members;
+
+ @JsonCreator
+ public Role(@JsonProperty("name") String name, @JsonProperty("members") List<String> members) {
+ this.name = name;
+ this.members = members;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public List<String> getMembers() {
+ return members;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Role that = (Role) o;
+ return Objects.equals(name, that.name) && Objects.equals(members, that.members);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, members);
+ }
+
+ @Override
+ public String toString() {
+ return "RoleDefinition{" +
+ "name='" + name + '\'' +
+ ", members=" + members +
+ '}';
+ }
+}
diff --git a/flags/src/main/java/com/yahoo/vespa/flags/custom/RoleList.java b/flags/src/main/java/com/yahoo/vespa/flags/custom/RoleList.java
new file mode 100644
index 00000000000..4e3d14bf076
--- /dev/null
+++ b/flags/src/main/java/com/yahoo/vespa/flags/custom/RoleList.java
@@ -0,0 +1,45 @@
+// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+package com.yahoo.vespa.flags.custom;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.util.List;
+import java.util.Objects;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonInclude(value = JsonInclude.Include.NON_NULL)
+public class RoleList {
+
+ @JsonProperty("roles")
+ List<Role> roles;
+
+ @JsonCreator
+ public RoleList(@JsonProperty("roles") List<Role> roles) {
+ this.roles = roles;
+ }
+
+ public List<Role> roles() {
+ return roles;
+ }
+
+ public static RoleList empty() {
+ return new RoleList(List.of());
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ RoleList roleList = (RoleList) o;
+ return Objects.equals(roles, roleList.roles);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(roles);
+ }
+}
diff --git a/flags/src/test/java/com/yahoo/vespa/flags/custom/RoleTest.java b/flags/src/test/java/com/yahoo/vespa/flags/custom/RoleTest.java
new file mode 100644
index 00000000000..2b1290f5222
--- /dev/null
+++ b/flags/src/test/java/com/yahoo/vespa/flags/custom/RoleTest.java
@@ -0,0 +1,56 @@
+// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+package com.yahoo.vespa.flags.custom;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.yahoo.test.json.Jackson;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class RoleTest {
+
+ @Test
+ void deSerializesCorrectly() throws JsonProcessingException {
+ String json = """
+ {
+ "roles": [
+ {
+ "name": "role1",
+ "members": ["u1@example.com", "u2@example.com"]
+ },
+ {
+ "name": "role2",
+ "members": [ "u1@example.com" ]
+ }
+ ]
+ }
+ """;
+ var mapper = Jackson.mapper();
+ RoleList roleList = mapper.readValue(json, RoleList.class);
+ assertEquals(2, roleList.roles().size());
+ Optional<Role> role1 = roleList.roles().stream()
+ .filter(r -> r.getName().equals("role1"))
+ .findFirst();
+ assertEquals(2, role1.get().getMembers().size());
+
+ Optional<Role> role2 = roleList.roles().stream()
+ .filter(r -> r.getName().equals("role2"))
+ .findFirst();
+ assertEquals(1, role2.get().getMembers().size());
+ }
+
+ @Test
+ void serializeCorrectly() throws JsonProcessingException {
+ Role role1 = new Role("role1", List.of("u1", "u2"));
+ Role role2 = new Role("role2", List.of("u1"));
+ RoleList roleList = new RoleList(List.of(role1, role2));
+ var mapper = Jackson.mapper();
+ String serialized = mapper.writeValueAsString(roleList);
+ RoleList deserialized = mapper.readValue(serialized, RoleList.class);
+ assertEquals(roleList, deserialized);
+ }
+} \ No newline at end of file