Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Improve error handling around loading recipes and add tests for Routes
- Avoid error internal server error when yaml in recipe is invalid (e.g. specifies "Route1") - Add validation for Routes in recipes (must refer to Service also in recipe) - Add test cases for OpenShiftEnvironmentFactory handling of Routes - Minor cleanup and simplification. Signed-off-by: Angel Misevski <amisevsk@redhat.com>
- Loading branch information
Showing
5 changed files
with
217 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
63 changes: 63 additions & 0 deletions
63
...pse/che/workspace/infrastructure/openshift/environment/OpenShiftEnvironmentValidator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
/* | ||
* Copyright (c) 2012-2018 Red Hat, Inc. | ||
* This program and the accompanying materials are made | ||
* available under the terms of the Eclipse Public License 2.0 | ||
* which is available at https://www.eclipse.org/legal/epl-2.0/ | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
* | ||
* Contributors: | ||
* Red Hat, Inc. - initial API and implementation | ||
*/ | ||
package org.eclipse.che.workspace.infrastructure.openshift.environment; | ||
|
||
import io.fabric8.openshift.api.model.Route; | ||
import java.util.Set; | ||
import java.util.stream.Collectors; | ||
import javax.inject.Inject; | ||
import org.eclipse.che.api.core.ValidationException; | ||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironmentPodsValidator; | ||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironmentValidator; | ||
|
||
/** | ||
* Adds additional OpenShift-specific validation to {@link KubernetesEnvironmentValidator} | ||
* | ||
* @author Angel Misevski | ||
*/ | ||
public class OpenShiftEnvironmentValidator extends KubernetesEnvironmentValidator { | ||
|
||
private static final String SERVICE_KIND = "Service"; | ||
|
||
@Inject | ||
public OpenShiftEnvironmentValidator(KubernetesEnvironmentPodsValidator podsValidator) { | ||
super(podsValidator); | ||
} | ||
|
||
public void validate(OpenShiftEnvironment env) throws ValidationException { | ||
super.validate(env); | ||
validateRoutesMatchServices(env); | ||
} | ||
|
||
private void validateRoutesMatchServices(OpenShiftEnvironment env) throws ValidationException { | ||
Set<String> recipeServices = | ||
env.getServices() | ||
.values() | ||
.stream() | ||
.map(s -> s.getMetadata().getName()) | ||
.collect(Collectors.toSet()); | ||
for (Route route : env.getRoutes().values()) { | ||
if (route.getSpec() == null | ||
|| route.getSpec().getTo() == null | ||
|| !route.getSpec().getTo().getKind().equals(SERVICE_KIND)) { | ||
continue; | ||
} | ||
String serviceName = route.getSpec().getTo().getName(); | ||
if (!recipeServices.contains(serviceName)) { | ||
throw new ValidationException( | ||
String.format( | ||
"Route '%s' refers to Service '%s'. Routes must refer to Services included in recipe", | ||
route.getMetadata().getName(), serviceName)); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
113 changes: 113 additions & 0 deletions
113
...che/workspace/infrastructure/openshift/environment/OpenShiftEnvironmentValidatorTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
/* | ||
* Copyright (c) 2012-2018 Red Hat, Inc. | ||
* This program and the accompanying materials are made | ||
* available under the terms of the Eclipse Public License 2.0 | ||
* which is available at https://www.eclipse.org/legal/epl-2.0/ | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
* | ||
* Contributors: | ||
* Red Hat, Inc. - initial API and implementation | ||
*/ | ||
package org.eclipse.che.workspace.infrastructure.openshift.environment; | ||
|
||
import static org.mockito.Mockito.when; | ||
|
||
import com.google.common.collect.ImmutableMap; | ||
import io.fabric8.kubernetes.api.model.Service; | ||
import io.fabric8.kubernetes.api.model.ServiceBuilder; | ||
import io.fabric8.openshift.api.model.Route; | ||
import io.fabric8.openshift.api.model.RouteBuilder; | ||
import java.util.Map; | ||
import org.eclipse.che.api.core.ValidationException; | ||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironmentPodsValidator; | ||
import org.mockito.InjectMocks; | ||
import org.mockito.Mock; | ||
import org.mockito.testng.MockitoTestNGListener; | ||
import org.testng.annotations.Listeners; | ||
import org.testng.annotations.Test; | ||
|
||
/** | ||
* Tests {@link OpenShiftEnvironmentValidator}. | ||
* | ||
* @author Angel Misevski | ||
*/ | ||
@Listeners(MockitoTestNGListener.class) | ||
public class OpenShiftEnvironmentValidatorTest { | ||
@Mock private KubernetesEnvironmentPodsValidator podsValidator; | ||
|
||
@Mock private OpenShiftEnvironment environment; | ||
|
||
@InjectMocks private OpenShiftEnvironmentValidator envValidator; | ||
|
||
@Test | ||
public void shouldDoNothingWhenRoutesMatchServices() throws Exception { | ||
// Given | ||
Map<String, Service> services = ImmutableMap.of("service1", makeService("service1")); | ||
Map<String, Route> routes = ImmutableMap.of("route1", makeRoute("route1", "service1")); | ||
when(environment.getRoutes()).thenReturn(routes); | ||
when(environment.getServices()).thenReturn(services); | ||
|
||
// When | ||
envValidator.validate(environment); | ||
|
||
// Then (nothing) | ||
} | ||
|
||
@Test | ||
public void shouldDoNothingWhenRoutesDoNotHaveToField() throws Exception { | ||
// Given | ||
Map<String, Route> routes = ImmutableMap.of("route1", makeRoute("route1", null)); | ||
when(environment.getRoutes()).thenReturn(routes); | ||
|
||
// When | ||
envValidator.validate(environment); | ||
|
||
// Then (nothing) | ||
} | ||
|
||
@Test(expectedExceptions = ValidationException.class) | ||
public void shouldThrowExceptionWhenRouteRefersToMissingService() throws Exception { | ||
// Given | ||
Map<String, Service> services = ImmutableMap.of("service1", makeService("service1")); | ||
Map<String, Route> routes = ImmutableMap.of("route1", makeRoute("route1", "notservice1")); | ||
when(environment.getRoutes()).thenReturn(routes); | ||
when(environment.getServices()).thenReturn(services); | ||
|
||
// When | ||
envValidator.validate(environment); | ||
|
||
// Then (ValidationException) | ||
} | ||
|
||
private Service makeService(String serviceName) { | ||
return new ServiceBuilder() | ||
.withNewMetadata() | ||
.withName(serviceName) | ||
.endMetadata() | ||
.withNewSpec() | ||
.endSpec() | ||
.build(); | ||
} | ||
|
||
/** | ||
* Make route for use in tests. If serviceName is null, return a route that does not refer to a | ||
* service. | ||
*/ | ||
private Route makeRoute(String routeName, String serviceName) { | ||
RouteBuilder routeBuilder = | ||
new RouteBuilder().withNewMetadata().withName(routeName).endMetadata(); | ||
if (serviceName != null) { | ||
routeBuilder | ||
.withNewSpec() | ||
.withNewTo() | ||
.withKind("Service") | ||
.withName(serviceName) | ||
.endTo() | ||
.endSpec(); | ||
} else { | ||
routeBuilder.withNewSpec().endSpec(); | ||
} | ||
return routeBuilder.build(); | ||
} | ||
} |