Skip to content

Commit

Permalink
feat: validate k8s groups that have a primary owner
Browse files Browse the repository at this point in the history
  • Loading branch information
a-cordier authored and kamiiiel committed Dec 4, 2024
1 parent 677bf1a commit df7e2ff
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@
import io.gravitee.apim.core.DomainService;
import io.gravitee.apim.core.group.model.Group;
import io.gravitee.apim.core.group.query_service.GroupQueryService;
import io.gravitee.apim.core.utils.StringUtils;
import io.gravitee.apim.core.validation.Validator;
import io.gravitee.definition.model.DefinitionVersion;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

Expand Down Expand Up @@ -66,12 +68,21 @@ public Result<Input> validateAndSanitize(Input input) {

var errors = new ArrayList<Error>();

var noPrimaryOwnerResultFromIds = validateAndSanitizeNoPrimaryOwners(groupsFromIds, Group::getId);
var noPrimaryOwnerResultFromNames = validateAndSanitizeNoPrimaryOwners(groupsFromNames, Group::getName);

noPrimaryOwnerResultFromIds.errors().ifPresent(errors::addAll);
noPrimaryOwnerResultFromNames.errors().ifPresent(errors::addAll);

var sanitizedFromIds = noPrimaryOwnerResultFromIds.value().orElse(List.of());
var sanitizedFromNames = noPrimaryOwnerResultFromNames.value().orElse(List.of());

if (DefinitionVersion.V2.getLabel().equals(input.definitionVersion)) {
sanitizedGroups.addAll(groupsFromIds.stream().map(Group::getName).toList());
sanitizedGroups.addAll(groupsFromNames.stream().map(Group::getName).toList());
sanitizedGroups.addAll(sanitizedFromIds.stream().map(Group::getName).toList());
sanitizedGroups.addAll(sanitizedFromNames.stream().map(Group::getName).toList());
} else {
sanitizedGroups.addAll(groupsFromIds.stream().map(Group::getId).toList());
sanitizedGroups.addAll(groupsFromNames.stream().map(Group::getId).toList());
sanitizedGroups.addAll(sanitizedFromIds.stream().map(Group::getId).toList());
sanitizedGroups.addAll(sanitizedFromNames.stream().map(Group::getId).toList());
}

givenGroups.removeAll(groupIds);
Expand All @@ -83,4 +94,25 @@ public Result<Input> validateAndSanitize(Input input) {

return Result.ofBoth(input.sanitized(sanitizedGroups), errors);
}

private Result<List<Group>> validateAndSanitizeNoPrimaryOwners(List<Group> groups, Function<Group, String> idMapper) {
var sanitized = new ArrayList<>(groups);
var groupsWithPrimaryOwner = sanitized.stream().filter(group -> StringUtils.isNotEmpty(group.getApiPrimaryOwner())).toList();
sanitized.removeAll(groupsWithPrimaryOwner);
var errors = buildPrimaryOwnerErrors(groupsWithPrimaryOwner, idMapper);
return Result.ofBoth(sanitized, errors);
}

private List<Error> buildPrimaryOwnerErrors(List<Group> groupsWithPrimaryOwner, Function<Group, String> idMapper) {
return groupsWithPrimaryOwner
.stream()
.map(idMapper)
.map(id ->
Error.warning(
"Group [%s] will be discarded because it contains an API Primary Owner member, which is not supported with by the operator.",
id
)
)
.toList();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* Copyright © 2015 The Gravitee team (http://gravitee.io)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.gravitee.apim.core.group.domain_service;

import inmemory.GroupQueryServiceInMemory;
import io.gravitee.apim.core.group.model.Group;
import io.gravitee.apim.core.validation.Validator;
import io.gravitee.definition.model.DefinitionVersion;
import java.util.List;
import java.util.Set;
import org.assertj.core.api.SoftAssertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.DisplayNameGenerator;
import org.junit.jupiter.api.Test;

/**
* @author Antoine CORDIER (antoine.cordier at graviteesource.com)
* @author GraviteeSource Team
*/
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
class ValidateGroupsDomainServiceTest {

private static final String ENVIRONMENT = "TEST";

private final GroupQueryServiceInMemory groupQueryService = new GroupQueryServiceInMemory();

private ValidateGroupsDomainService validateGroupsDomainService;

@BeforeEach
void setUp() {
groupQueryService.initWith(
List.of(
Group.builder().environmentId(ENVIRONMENT).id("group-with-po-id").name("group-with-po").apiPrimaryOwner("some-po").build(),
Group.builder().environmentId(ENVIRONMENT).id("group-without-po-id").name("group-without-po").build()
)
);
validateGroupsDomainService = new ValidateGroupsDomainService(groupQueryService);
}

@Test
void should_return_warnings_with_group_with_primary_owner_and_sanitize_v2() {
var givenGroups = Set.of("group-with-po-id", "group-without-po");

var input = new ValidateGroupsDomainService.Input(ENVIRONMENT, givenGroups, DefinitionVersion.V2.getLabel());

var result = validateGroupsDomainService.validateAndSanitize(input);

SoftAssertions.assertSoftly(soft -> {
soft.assertThat(result.value()).isNotEmpty();
soft.assertThat(result.value()).hasValue(input.sanitized(Set.of("group-without-po")));
soft.assertThat(result.errors()).isNotEmpty();
soft
.assertThat(result.errors())
.hasValue(
List.of(
Validator.Error.warning(
"Group [group-with-po-id] will be discarded because it contains an API Primary Owner member, which is not supported with by the operator."
)
)
);
});
}

@Test
void should_return_warnings_with_group_with_primary_owner_and_sanitize_v4() {
var givenGroups = Set.of("group-with-po", "group-without-po-id");

var input = new ValidateGroupsDomainService.Input(ENVIRONMENT, givenGroups, DefinitionVersion.V4.getLabel());

var result = validateGroupsDomainService.validateAndSanitize(input);

SoftAssertions.assertSoftly(soft -> {
soft.assertThat(result.value()).isNotEmpty();
soft.assertThat(result.value()).hasValue(input.sanitized(Set.of("group-without-po-id")));
soft.assertThat(result.errors()).isNotEmpty();
soft
.assertThat(result.errors())
.hasValue(
List.of(
Validator.Error.warning(
"Group [group-with-po] will be discarded because it contains an API Primary Owner member, which is not supported with by the operator."
)
)
);
});
}
}

0 comments on commit df7e2ff

Please sign in to comment.