Allow to use reference to content

Signed-off-by: Max Shaposhnik <mshaposh@redhat.com>
7.20.x
Max Shaposhnik 2019-04-01 14:29:48 +03:00 committed by GitHub
parent b96fa87296
commit 3704ffccec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 290 additions and 463 deletions

View File

@ -109,28 +109,27 @@ List of available Che plugins and more information about registry can be found o
#### kubernetes/openshift
More complex component type, which allows to apply configuration from kubernetes/openshift lists. Content of the component may be provided either via `local` attribute which points to the file with component content.
More complex component type, which allows to apply configuration from kubernetes/openshift lists. Content of the component may be provided either via `reference` attribute which points to the file with component content.
```
...
components:
- name: mysql
type: kubernetes
local: petclinic.yaml
reference: petclinic.yaml
selector:
app.kubernetes.io/name: mysql
app.kubernetes.io/component: database
app.kubernetes.io/part-of: petclinic
```
Contents of the `local` file is currently read _ONLY_ if the devfile and local file both placed in the same public GitHub repository.
So, alternatively, if you need to post devfile with such components to REST API, contents of K8S/Openshift list can be embedded into devfile using `localContent` field:
Alternatively, if you need to post devfile with such components to REST API, contents of K8S/Openshift list can be embedded into devfile using `referenceContent` field:
```
...
components:
- name: mysql
type: kubernetes
local: petclinic.yaml
localContent: |
reference: petclinic.yaml
referenceContent: |
kind: List
items:
-
@ -157,7 +156,7 @@ The entrypoints can be defined for example like this:
components:
- name: appDeployment
type: kubernetes
local: app-deployment.yaml
reference: app-deployment.yaml
entrypoints:
- parentName: mysqlServer
command: ['sleep']

View File

@ -79,6 +79,10 @@
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-core</artifactId>
@ -115,6 +119,10 @@
<groupId>org.eclipse.che.infrastructure.docker</groupId>
<artifactId>docker-environment</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>

View File

@ -41,7 +41,6 @@ import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.ValidationException;
import org.eclipse.che.api.core.rest.Service;
import org.eclipse.che.api.devfile.model.Devfile;
import org.eclipse.che.api.devfile.server.FileContentProvider.FetchNotSupportedProvider;
import org.eclipse.che.api.devfile.server.exception.DevfileException;
import org.eclipse.che.api.devfile.server.schema.DevfileSchemaProvider;
import org.eclipse.che.api.workspace.server.WorkspaceLinksGenerator;
@ -56,16 +55,19 @@ public class DevfileService extends Service {
private DevfileSchemaProvider schemaCachedProvider;
private ObjectMapper objectMapper;
private DevfileManager devfileManager;
private URLFileContentProvider urlFileContentProvider;
@Inject
public DevfileService(
WorkspaceLinksGenerator linksGenerator,
DevfileSchemaProvider schemaCachedProvider,
DevfileManager devfileManager) {
DevfileManager devfileManager,
URLFetcher urlFetcher) {
this.linksGenerator = linksGenerator;
this.schemaCachedProvider = schemaCachedProvider;
this.devfileManager = devfileManager;
this.objectMapper = new ObjectMapper(new YAMLFactory());
this.urlFileContentProvider = new URLFileContentProvider(null, urlFetcher);
}
/**
@ -119,11 +121,7 @@ public class DevfileService extends Service {
WorkspaceImpl workspace;
try {
Devfile devfile = devfileManager.parse(data);
workspace =
devfileManager.createWorkspace(
devfile,
new FetchNotSupportedProvider(
"Devfile Service does not support fetching local file referenced in Devfile."));
workspace = devfileManager.createWorkspace(devfile, urlFileContentProvider);
} catch (DevfileException e) {
throw new BadRequestException(e.getMessage());
}

View File

@ -44,34 +44,13 @@ public interface FileContentProvider {
/**
* Fetches content of the specified file.
*
* @param fileName file name to fetch content. Only devfile-relative files are currently
* supported, so it means file should be localed at the same directory level as devfile (no
* matter in repository or PR or branch etc )
* @param fileURL absolute or devfile-relative file URL to fetch content
* @return content of the specified file
* @throws IOException when there is an error during content retrieval
* @throws DevfileException when implementation does not support fetching of additional files
* content
*/
String fetchContent(String fileName) throws IOException, DevfileException;
/** Default implementation of {@link FileContentProvider} that does not support fetching. */
class FetchNotSupportedProvider implements FileContentProvider {
private String message;
public FetchNotSupportedProvider() {
this.message = "File content fetching is not supported";
}
public FetchNotSupportedProvider(String message) {
this.message = message;
}
@Override
public String fetchContent(String fileName) throws DevfileException {
throw new DevfileException(message);
}
}
String fetchContent(String fileURL) throws IOException, DevfileException;
/**
* A file content provider that caches responses from the content provider it is wrapping. Useful
@ -89,13 +68,13 @@ public interface FileContentProvider {
}
@Override
public String fetchContent(String fileName) throws IOException, DevfileException {
SoftReference<String> ref = cache.get(fileName);
public String fetchContent(String fileURL) throws IOException, DevfileException {
SoftReference<String> ref = cache.get(fileURL);
String ret = ref == null ? null : ref.get();
if (ret == null) {
ret = provider.fetchContent(fileName);
cache.put(fileName, new SoftReference<>(ret));
ret = provider.fetchContent(fileURL);
cache.put(fileURL, new SoftReference<>(ret));
}
return ret;

View File

@ -9,7 +9,7 @@
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.api.factory.server.urlfactory;
package org.eclipse.che.api.devfile.server;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Objects.requireNonNull;

View File

@ -0,0 +1,73 @@
/*
* 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.api.devfile.server;
import static java.lang.String.format;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import org.eclipse.che.api.devfile.server.exception.DevfileException;
/**
* A simple implementation of the FileContentProvider that merely uses the function resolve relative
* paths and {@link URLFetcher} for retrieving the content, handling common error cases.
*/
public class URLFileContentProvider implements FileContentProvider {
private final URI devfileLocation;
private final URLFetcher urlFetcher;
public URLFileContentProvider(URI devfileLocation, URLFetcher urlFetcher) {
this.devfileLocation = devfileLocation;
this.urlFetcher = urlFetcher;
}
@Override
public String fetchContent(String fileURL) throws IOException, DevfileException {
URI fileURI;
String requestURL;
try {
fileURI = new URI(fileURL);
} catch (URISyntaxException e) {
throw new DevfileException(e.getMessage(), e);
}
if (fileURI.isAbsolute()) {
requestURL = fileURL;
} else {
if (devfileLocation == null) {
throw new DevfileException(
format(
"It is unable to fetch a file %s as relative to devfile, since devfile location"
+ " is unknown. Try specifying absolute URL.",
fileURL));
}
requestURL = devfileLocation.resolve(fileURI).toString();
}
try {
return urlFetcher.fetch(requestURL);
} catch (IOException e) {
throw new IOException(
format(
"Failed to fetch a file %s specified in devfile %s from URL %s. Make sure the URL"
+ " of the devfile points to the raw content of it (e.g. not to the webpage"
+ " showing it but really just its contents). Additionally, if you 're using "
+ " relative form, make sure the referenced files are actually stored"
+ " relative to the devfile on the same host,"
+ " or try to specify URL in absolute form. The current attempt to download"
+ " the file failed with the following error message: %s",
fileURL, devfileLocation, requestURL, e.getMessage()),
e);
}
}
}

View File

@ -110,19 +110,19 @@ public class KubernetesComponentToWorkspaceApplier implements ComponentToWorkspa
Component recipeComponent, @Nullable FileContentProvider fileContentProvider)
throws DevfileException {
checkArgument(fileContentProvider != null, "Content provider must not be null");
if (!isNullOrEmpty(recipeComponent.getLocalContent())) {
return recipeComponent.getLocalContent();
if (!isNullOrEmpty(recipeComponent.getReferenceContent())) {
return recipeComponent.getReferenceContent();
}
String recipeFileContent;
try {
recipeFileContent = fileContentProvider.fetchContent(recipeComponent.getLocal());
recipeFileContent = fileContentProvider.fetchContent(recipeComponent.getReference());
} catch (DevfileException e) {
throw new DevfileException(
format(
"Fetching content of file `%s` specified in `local` field of component `%s` is not supported. "
+ "Please provide its content in `localContent` field. Cause: %s",
recipeComponent.getLocal(), recipeComponent.getName(), e.getMessage()),
"Fetching content of file `%s` specified in `reference` field of component `%s` is not supported. "
+ "Please provide its content in `referenceContent` field. Cause: %s",
recipeComponent.getReference(), recipeComponent.getName(), e.getMessage()),
e);
} catch (IOException e) {
throw new DevfileException(
@ -134,8 +134,8 @@ public class KubernetesComponentToWorkspaceApplier implements ComponentToWorkspa
if (isNullOrEmpty(recipeFileContent)) {
throw new DevfileException(
format(
"The local file '%s' defined in component '%s' is empty.",
recipeComponent.getLocal(), recipeComponent.getName()));
"The reference file '%s' defined in component '%s' is empty.",
recipeComponent.getReference(), recipeComponent.getName()));
}
return recipeFileContent;
}
@ -193,14 +193,15 @@ public class KubernetesComponentToWorkspaceApplier implements ComponentToWorkspa
}
private List<HasMetadata> unmarshalComponentObjects(
Component k8sComponent, String componentLocalContent) throws DevfileRecipeFormatException {
Component k8sComponent, String componentreferenceContent)
throws DevfileRecipeFormatException {
try {
return unmarshal(componentLocalContent);
return unmarshal(componentreferenceContent);
} catch (DevfileRecipeFormatException e) {
throw new DevfileRecipeFormatException(
format(
"Error occurred during parsing list from file %s for component '%s': %s",
k8sComponent.getLocal(), k8sComponent.getName(), e.getMessage()),
k8sComponent.getReference(), k8sComponent.getName(), e.getMessage()),
e);
}
}

View File

@ -261,10 +261,10 @@ public class DevfileIntegrityValidator {
Component component, FileContentProvider contentProvider)
throws ValidationException, InfrastructureException, IOException, DevfileException {
List<HasMetadata> content;
if (component.getLocalContent() != null) {
content = kubernetesRecipeParser.parse(component.getLocalContent());
} else if (component.getLocal() != null) {
String data = contentProvider.fetchContent(component.getLocal());
if (component.getReferenceContent() != null) {
content = kubernetesRecipeParser.parse(component.getReferenceContent());
} else if (component.getReference() != null) {
String data = contentProvider.fetchContent(component.getReference());
content = kubernetesRecipeParser.parse(data);
} else {
content = Collections.emptyList();

View File

@ -113,8 +113,8 @@
"type"
],
"dependencies": {
"localContent": [
"local"
"referenceContent": [
"reference"
]
},
"additionalProperties": false,
@ -144,13 +144,13 @@
]
},
"name": {},
"local": {},
"localContent": {},
"reference": {},
"referenceContent": {},
"selector": {},
"entrypoints": {}
},
"required": [
"local"
"reference"
],
"additionalProperties": false
},
@ -205,15 +205,15 @@
"eclipse/maven-jdk8:1.0.0"
]
},
"local": {
"description": "Describes location of Kubernetes list yaml file. Applicable only for 'kubernetes' and 'openshift' type components",
"reference": {
"description": "Describes absolute or devfile-relative location of Kubernetes list yaml file. Applicable only for 'kubernetes' and 'openshift' type components",
"type": "string",
"examples": [
"petclinic-app.yaml"
]
},
"localContent": {
"description": "Inlined content of a file specified in field 'local'",
"referenceContent": {
"description": "Inlined content of a file specified in field 'reference'",
"type": "string",
"examples": [
"{\"kind\":\"List\",\"items\":[{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"name\":\"ws\"},\"spec\":{\"containers\":[{\"image\":\"eclipse/che-dev:nightly\"}]}}]}"

View File

@ -54,6 +54,7 @@ public class DevfileServiceTest {
@Mock private WorkspaceLinksGenerator linksGenerator;
@Mock private DevfileManager devfileManager;
@Mock private URLFetcher urlFetcher;
private DevfileSchemaProvider schemaProvider = new DevfileSchemaProvider();
private ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
@ -64,7 +65,8 @@ public class DevfileServiceTest {
@BeforeMethod
public void initService() {
this.devFileService = new DevfileService(linksGenerator, schemaProvider, devfileManager);
this.devFileService =
new DevfileService(linksGenerator, schemaProvider, devfileManager, urlFetcher);
}
@Test

View File

@ -9,10 +9,10 @@
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.api.factory.server.urlfactory;
package org.eclipse.che.api.devfile.server;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.eclipse.che.api.factory.server.urlfactory.URLFetcher.MAXIMUM_READ_BYTES;
import static org.eclipse.che.api.devfile.server.URLFetcher.MAXIMUM_READ_BYTES;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
@ -30,7 +30,7 @@ import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
/**
* Testing {@link URLFetcher}
* Testing {@link org.eclipse.che.api.devfile.server.URLFetcher}
*
* @author Florent Benoit
*/

View File

@ -0,0 +1,59 @@
/*
* 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.api.devfile.server;
import static org.mockito.Mockito.verify;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import org.eclipse.che.api.devfile.server.exception.DevfileException;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.testng.MockitoTestNGListener;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
@Listeners(MockitoTestNGListener.class)
public class URLFileContentProviderTest {
@Mock private URLFetcher urlFetcher;
@Test(
expectedExceptions = DevfileException.class,
expectedExceptionsMessageRegExp =
"It is unable to fetch a file /relative/dev.yaml as relative to devfile, since devfile location is unknown. Try specifying absolute URL.")
public void shouldThrowExceptionWhenNoDevfileLocationKnownAndURLIsRelative() throws Exception {
URLFileContentProvider provider = new URLFileContentProvider(null, urlFetcher);
provider.fetchContent("/relative/dev.yaml");
}
@Test
public void shouldFetchByAbsoluteURL() throws Exception {
String url = "http://myhost.com/relative/dev.yaml";
URLFileContentProvider provider = new URLFileContentProvider(null, urlFetcher);
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
provider.fetchContent(url);
verify(urlFetcher).fetch(captor.capture());
assertEquals(captor.getValue(), url);
}
@Test
public void shouldMergeDevfileLocationAndRelativeURL() throws Exception {
String devfileUrl = "http://myhost.com/relative/devile.yaml";
String relativeUrl = "relative.yaml";
URLFileContentProvider provider = new URLFileContentProvider(new URI(devfileUrl), urlFetcher);
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
provider.fetchContent(relativeUrl);
verify(urlFetcher).fetch(captor.capture());
assertEquals(captor.getValue(), "http://myhost.com/relative/relative.yaml");
}
}

View File

@ -42,7 +42,7 @@ import java.util.Map;
import org.eclipse.che.api.core.ValidationException;
import org.eclipse.che.api.devfile.model.Component;
import org.eclipse.che.api.devfile.model.Entrypoint;
import org.eclipse.che.api.devfile.server.FileContentProvider.FetchNotSupportedProvider;
import org.eclipse.che.api.devfile.server.URLFileContentProvider;
import org.eclipse.che.api.devfile.server.exception.DevfileException;
import org.eclipse.che.api.workspace.server.model.impl.CommandImpl;
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceConfigImpl;
@ -62,7 +62,7 @@ import org.testng.reporters.Files;
@Listeners(MockitoTestNGListener.class)
public class KubernetesComponentToWorkspaceApplierTest {
public static final String LOCAL_FILENAME = "local.yaml";
public static final String REFERENCE_FILENAME = "reference.yaml";
public static final String COMPONENT_NAME = "foo";
private WorkspaceConfigImpl workspaceConfig;
@ -83,8 +83,8 @@ public class KubernetesComponentToWorkspaceApplierTest {
@Test(
expectedExceptions = DevfileException.class,
expectedExceptionsMessageRegExp =
"Fetching content of file `local.yaml` specified in `local` field of component `foo` is not "
+ "supported. Please provide its content in `localContent` field. Cause: fetch is not supported")
"Fetching content of file `reference.yaml` specified in `reference` field of component `foo` is not "
+ "supported. Please provide its content in `referenceContent` field. Cause: fetch is not supported")
public void
shouldThrowExceptionWhenRecipeComponentIsPresentAndContentProviderDoesNotSupportFetching()
throws Exception {
@ -92,7 +92,7 @@ public class KubernetesComponentToWorkspaceApplierTest {
Component component =
new Component()
.withType(KUBERNETES_COMPONENT_TYPE)
.withLocal(LOCAL_FILENAME)
.withReference(REFERENCE_FILENAME)
.withName(COMPONENT_NAME);
// when
@ -108,7 +108,7 @@ public class KubernetesComponentToWorkspaceApplierTest {
expectedExceptions = DevfileException.class,
expectedExceptionsMessageRegExp =
"Error occurred during parsing list from file "
+ LOCAL_FILENAME
+ REFERENCE_FILENAME
+ " for component '"
+ COMPONENT_NAME
+ "': .*")
@ -118,7 +118,7 @@ public class KubernetesComponentToWorkspaceApplierTest {
Component component =
new Component()
.withType(KUBERNETES_COMPONENT_TYPE)
.withLocal(LOCAL_FILENAME)
.withReference(REFERENCE_FILENAME)
.withName(COMPONENT_NAME);
// when
@ -134,7 +134,7 @@ public class KubernetesComponentToWorkspaceApplierTest {
Component component =
new Component()
.withType(KUBERNETES_COMPONENT_TYPE)
.withLocal(LOCAL_FILENAME)
.withReference(REFERENCE_FILENAME)
.withName(COMPONENT_NAME);
// when
@ -155,7 +155,7 @@ public class KubernetesComponentToWorkspaceApplierTest {
Component component =
new Component()
.withType(KUBERNETES_COMPONENT_TYPE)
.withLocal(LOCAL_FILENAME)
.withReference(REFERENCE_FILENAME)
.withName(COMPONENT_NAME)
.withSelector(new HashMap<>());
@ -172,18 +172,18 @@ public class KubernetesComponentToWorkspaceApplierTest {
}
@Test
public void shouldUseLocalContentAsRecipeIfPresent() throws Exception {
public void shouldUseReferenceContentAsRecipeIfPresent() throws Exception {
String yamlRecipeContent = getResource("petclinic.yaml");
doReturn(toK8SList(yamlRecipeContent).getItems()).when(k8sRecipeParser).parse(anyString());
Component component =
new Component()
.withType(KUBERNETES_COMPONENT_TYPE)
.withLocal(LOCAL_FILENAME)
.withLocalContent(yamlRecipeContent)
.withReference(REFERENCE_FILENAME)
.withReferenceContent(yamlRecipeContent)
.withName(COMPONENT_NAME)
.withSelector(new HashMap<>());
applier.apply(workspaceConfig, component, new FetchNotSupportedProvider());
applier.apply(workspaceConfig, component, new URLFileContentProvider(null, null));
verify(k8sEnvProvisioner)
.provision(
@ -202,7 +202,7 @@ public class KubernetesComponentToWorkspaceApplierTest {
Component component =
new Component()
.withType(OPENSHIFT_COMPONENT_TYPE)
.withLocal(LOCAL_FILENAME)
.withReference(REFERENCE_FILENAME)
.withName(COMPONENT_NAME)
.withSelector(new HashMap<>());
@ -227,7 +227,7 @@ public class KubernetesComponentToWorkspaceApplierTest {
Component component =
new Component()
.withType(OPENSHIFT_COMPONENT_TYPE)
.withLocal(LOCAL_FILENAME)
.withReference(REFERENCE_FILENAME)
.withName(COMPONENT_NAME)
.withSelector(selector);
doReturn(toK8SList(yamlRecipeContent).getItems()).when(k8sRecipeParser).parse(anyString());
@ -260,7 +260,7 @@ public class KubernetesComponentToWorkspaceApplierTest {
Component component =
new Component()
.withType(OPENSHIFT_COMPONENT_TYPE)
.withLocal(LOCAL_FILENAME)
.withReference(REFERENCE_FILENAME)
.withName(COMPONENT_NAME)
.withSelector(selector);
CommandImpl command = new CommandImpl();
@ -286,7 +286,7 @@ public class KubernetesComponentToWorkspaceApplierTest {
Component component =
new Component()
.withType(OPENSHIFT_COMPONENT_TYPE)
.withLocal(LOCAL_FILENAME)
.withReference(REFERENCE_FILENAME)
.withName(COMPONENT_NAME)
.withSelector(new HashMap<>());
@ -312,7 +312,7 @@ public class KubernetesComponentToWorkspaceApplierTest {
Component component =
new Component()
.withType(OPENSHIFT_COMPONENT_TYPE)
.withLocal(LOCAL_FILENAME)
.withReference(REFERENCE_FILENAME)
.withName(COMPONENT_NAME)
.withEntrypoints(
singletonList(new Entrypoint().withParentName("petclinic").withCommand(command)))

View File

@ -179,7 +179,7 @@ public class DevfileIntegrityValidatorTest {
// this is the openshift component which is the only one sensitive to the selector in our
// example
// devfile
devfile.getComponents().get(3).setLocalContent("content");
devfile.getComponents().get(3).setReferenceContent("content");
devfile.getComponents().get(3).setSelector(selector);
// when
@ -203,7 +203,7 @@ public class DevfileIntegrityValidatorTest {
.build()));
Devfile devfile = copyOf(initialDevfile);
devfile.getComponents().get(0).setLocalContent("content");
devfile.getComponents().get(0).setReferenceContent("content");
devfile
.getComponents()
.get(0)

View File

@ -41,15 +41,16 @@ public class DevfileSchemaValidatorTest {
public Object[][] validDevfiles() {
return new Object[][] {
{"editor_plugin_component/devfile_editor_plugins.yaml"},
{"kubernetes_openshift_component/devfile_kubernetes_component_reference.yaml"},
{"kubernetes_openshift_component/devfile_kubernetes_component_absolute_reference.yaml"},
{"component/devfile_without_any_component.yaml"},
{"kubernetes_openshift_component/devfile_kubernetes_component_local.yaml"},
{
"kubernetes_openshift_component/devfile_kubernetes_component_local_and_content_as_block.yaml"
"kubernetes_openshift_component/devfile_kubernetes_component_reference_and_content_as_block.yaml"
},
{"kubernetes_openshift_component/devfile_openshift_component.yaml"},
{"kubernetes_openshift_component/devfile_openshift_component_local_and_content.yaml"},
{"kubernetes_openshift_component/devfile_openshift_component_reference_and_content.yaml"},
{
"kubernetes_openshift_component/devfile_openshift_component_local_and_content_as_block.yaml"
"kubernetes_openshift_component/devfile_openshift_component_reference_and_content_as_block.yaml"
},
{"dockerimage_component/devfile_dockerimage_component.yaml"},
{"dockerimage_component/devfile_dockerimage_component_without_entry_point.yaml"}
@ -102,7 +103,7 @@ public class DevfileSchemaValidatorTest {
+ "instance failed to match exactly one schema (matched 0 out of 3),"
+ "/devfile/components/0 object instance has properties which are not allowed by the schema: [\"unknown\"],"
+ "/devfile/components/0 object instance has properties which are not allowed by the schema: [\"id\",\"unknown\"],"
+ "/devfile/components/0 object has missing required properties ([\"local\"]),"
+ "/devfile/components/0 object has missing required properties ([\"reference\"]),"
+ "/devfile/components/0 object instance has properties which are not allowed by the schema: [\"id\",\"unknown\"],"
+ "/devfile/components/0 object has missing required properties ([\"image\",\"memoryLimit\"])]"
},
@ -124,15 +125,15 @@ public class DevfileSchemaValidatorTest {
"editor_plugin_component/devfile_editor_component_with_missing_id.yaml",
"Devfile schema validation failed. Errors: [instance failed to match exactly one schema (matched 0 out of 3),"
+ "/devfile/components/0 object has missing required properties ([\"id\"]),"
+ "/devfile/components/0 object has missing required properties ([\"local\"]),"
+ "/devfile/components/0 object has missing required properties ([\"reference\"]),"
+ "/devfile/components/0 object has missing required properties ([\"image\",\"memoryLimit\"])]"
},
{
"editor_plugin_component/devfile_editor_component_with_indistinctive_field_local.yaml",
"editor_plugin_component/devfile_editor_component_with_indistinctive_field_reference.yaml",
"Devfile schema validation failed. Errors: [instance failed to match exactly one schema (matched 0 out of 3),"
+ "/devfile/components/0 object instance has properties which are not allowed by the schema: [\"local\"],"
+ "/devfile/components/0 object instance has properties which are not allowed by the schema: [\"reference\"],"
+ "/devfile/components/0 object instance has properties which are not allowed by the schema: [\"id\"],"
+ "/devfile/components/0 object instance has properties which are not allowed by the schema: [\"id\",\"local\"],"
+ "/devfile/components/0 object instance has properties which are not allowed by the schema: [\"id\",\"reference\"],"
+ "/devfile/components/0 object has missing required properties ([\"image\",\"memoryLimit\"])]"
},
{
@ -147,38 +148,38 @@ public class DevfileSchemaValidatorTest {
},
// kubernetes/openshift component model testing
{
"kubernetes_openshift_component/devfile_openshift_component_with_missing_local.yaml",
"kubernetes_openshift_component/devfile_openshift_component_with_missing_reference.yaml",
"Devfile schema validation failed. Errors: [instance failed to match exactly one schema (matched 0 out of 3),"
+ "/devfile/components/0 object has missing required properties ([\"id\"]),"
+ "/devfile/components/0 object has missing required properties ([\"local\"]),"
+ "/devfile/components/0 object has missing required properties ([\"reference\"]),"
+ "/devfile/components/0 object has missing required properties ([\"image\",\"memoryLimit\"])]"
},
{
"kubernetes_openshift_component/devfile_openshift_component_content_without_local.yaml",
"Devfile schema validation failed. Errors: [/devfile/components/0 property \"localContent\" of object has missing property dependencies (schema requires [\"local\"]; missing: [\"local\"]),"
"kubernetes_openshift_component/devfile_openshift_component_content_without_reference.yaml",
"Devfile schema validation failed. Errors: [/devfile/components/0 property \"referenceContent\" of object has missing property dependencies (schema requires [\"reference\"]; missing: [\"reference\"]),"
+ "instance failed to match exactly one schema (matched 0 out of 3),"
+ "/devfile/components/0 object instance has properties which are not allowed by the schema: [\"localContent\",\"selector\"],"
+ "/devfile/components/0 object instance has properties which are not allowed by the schema: [\"referenceContent\",\"selector\"],"
+ "/devfile/components/0 object has missing required properties ([\"id\"]),"
+ "/devfile/components/0 object has missing required properties ([\"local\"]),"
+ "/devfile/components/0 object instance has properties which are not allowed by the schema: [\"localContent\",\"selector\"],"
+ "/devfile/components/0 object has missing required properties ([\"reference\"]),"
+ "/devfile/components/0 object instance has properties which are not allowed by the schema: [\"referenceContent\",\"selector\"],"
+ "/devfile/components/0 object has missing required properties ([\"image\",\"memoryLimit\"])]"
},
{
"kubernetes_openshift_component/devfile_kubernetes_component_content_without_local.yaml",
"Devfile schema validation failed. Errors: [/devfile/components/0 property \"localContent\" of object has missing property dependencies (schema requires [\"local\"]; missing: [\"local\"]),"
"kubernetes_openshift_component/devfile_kubernetes_component_content_without_reference.yaml",
"Devfile schema validation failed. Errors: [/devfile/components/0 property \"referenceContent\" of object has missing property dependencies (schema requires [\"reference\"]; missing: [\"reference\"]),"
+ "instance failed to match exactly one schema (matched 0 out of 3),"
+ "/devfile/components/0 object instance has properties which are not allowed by the schema: [\"localContent\",\"selector\"],"
+ "/devfile/components/0 object instance has properties which are not allowed by the schema: [\"referenceContent\",\"selector\"],"
+ "/devfile/components/0 object has missing required properties ([\"id\"]),"
+ "/devfile/components/0 object has missing required properties ([\"local\"]),"
+ "/devfile/components/0 object instance has properties which are not allowed by the schema: [\"localContent\",\"selector\"],"
+ "/devfile/components/0 object has missing required properties ([\"reference\"]),"
+ "/devfile/components/0 object instance has properties which are not allowed by the schema: [\"referenceContent\",\"selector\"],"
+ "/devfile/components/0 object has missing required properties ([\"image\",\"memoryLimit\"])]"
},
{
"kubernetes_openshift_component/devfile_openshift_component_with_indistinctive_field_id.yaml",
"Devfile schema validation failed. Errors: [instance failed to match exactly one schema (matched 0 out of 3)"
+ ",/devfile/components/0 object instance has properties which are not allowed by the schema: [\"local\",\"selector\"],"
+ ",/devfile/components/0 object instance has properties which are not allowed by the schema: [\"reference\",\"selector\"],"
+ "/devfile/components/0 object instance has properties which are not allowed by the schema: [\"id\"],"
+ "/devfile/components/0 object instance has properties which are not allowed by the schema: [\"id\",\"local\",\"selector\"],"
+ "/devfile/components/0 object instance has properties which are not allowed by the schema: [\"id\",\"reference\",\"selector\"],"
+ "/devfile/components/0 object has missing required properties ([\"image\",\"memoryLimit\"])]"
},
// Dockerimage component model testing
@ -188,7 +189,7 @@ public class DevfileSchemaValidatorTest {
+ "/devfile/components/0 object instance has properties which are not allowed by the schema: [\"memoryLimit\"],"
+ "/devfile/components/0 object has missing required properties ([\"id\"]),"
+ "/devfile/components/0 object instance has properties which are not allowed by the schema: [\"memoryLimit\"],"
+ "/devfile/components/0 object has missing required properties ([\"local\"]),"
+ "/devfile/components/0 object has missing required properties ([\"reference\"]),"
+ "/devfile/components/0 object has missing required properties ([\"image\"])]"
},
{
@ -196,7 +197,7 @@ public class DevfileSchemaValidatorTest {
"Devfile schema validation failed. Errors: [instance failed to match exactly one schema (matched 0 out of 3),"
+ "/devfile/components/0 object instance has properties which are not allowed by the schema: [\"image\"],"
+ "/devfile/components/0 object has missing required properties ([\"id\"]),"
+ "/devfile/components/0 object instance has properties which are not allowed by the schema: [\"image\"],/devfile/components/0 object has missing required properties ([\"local\"]),"
+ "/devfile/components/0 object instance has properties which are not allowed by the schema: [\"image\"],/devfile/components/0 object has missing required properties ([\"reference\"]),"
+ "/devfile/components/0 object has missing required properties ([\"memoryLimit\"])]"
},
{
@ -205,7 +206,7 @@ public class DevfileSchemaValidatorTest {
+ "/devfile/components/0 object instance has properties which are not allowed by the schema: [\"endpoints\",\"env\",\"image\",\"memoryLimit\",\"selector\",\"volumes\"],"
+ "/devfile/components/0 object has missing required properties ([\"id\"]),"
+ "/devfile/components/0 object instance has properties which are not allowed by the schema: [\"endpoints\",\"env\",\"image\",\"memoryLimit\",\"volumes\"],"
+ "/devfile/components/0 object has missing required properties ([\"local\"]),"
+ "/devfile/components/0 object has missing required properties ([\"reference\"]),"
+ "/devfile/components/0 object instance has properties which are not allowed by the schema: [\"selector\"]]"
},
};

View File

@ -30,7 +30,7 @@ components:
id: eclipse/theia-jdtls:0.0.3
- name: os-recipe
type: openshift
local: petclinic.yaml
reference: petclinic.yaml
selector:
app.kubernetes.io/name: mysql
app.kubernetes.io/component: database

View File

@ -16,7 +16,7 @@ name: petclinic-dev-environment
components:
- name: mysql
type: openshift
local: petclinic.yaml
reference: petclinic.yaml
selector:
app.kubernetes.io/name: mysql
app.kubernetes.io/component: database

View File

@ -0,0 +1,30 @@
#
# 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
#
---
specVersion: 0.0.1
name: petclinic-dev-environment
components:
- name: mysql
type: kubernetes
reference: https://github.com/redhat-developer/devfile/blob/master/samples/web-nodejs-with-db-sample/mongo-db.yaml
selector:
app.kubernetes.io/name: mysql
app.kubernetes.io/component: database
app.kubernetes.io/part-of: petclinic
commands:
- name: build
actions:
- type: exec
component: mysql
command: mvn clean
workdir: /projects/spring-petclinic

View File

@ -16,7 +16,7 @@ name: petclinic-dev-environment
components:
- name: mysql
type: kubernetes
localContent: petclinic.yaml
referenceContent: petclinic.yaml
selector:
app.kubernetes.io/name: mysql
app.kubernetes.io/component: database

View File

@ -16,7 +16,7 @@ name: petclinic-dev-environment
components:
- name: mysql
type: kubernetes
local: petclinic.yaml
reference: petclinic.yaml
selector:
app.kubernetes.io/name: mysql
app.kubernetes.io/component: database

View File

@ -16,8 +16,8 @@ name: petclinic-dev-environment
components:
- name: mysql
type: kubernetes
local: petclinic.yaml
localContent: |
reference: petclinic.yaml
referenceContent: |
kind: List
items:
-

View File

@ -16,7 +16,7 @@ name: petclinic-dev-environment
components:
- name: mysql
type: openshift
local: petclinic.yaml
reference: petclinic.yaml
selector:
app.kubernetes.io/name: mysql
app.kubernetes.io/component: database

View File

@ -16,7 +16,7 @@ name: petclinic-dev-environment
components:
- name: mysql
type: openshift
localContent: this is content of file that is supposed to be in local field but it is missing
referenceContent: this is content of file that is supposed to be in local field but it is missing
selector:
app.kubernetes.io/name: mysql
app.kubernetes.io/component: database

View File

@ -16,8 +16,8 @@ name: petclinic-dev-environment
components:
- name: mysql
type: openshift
localContent: it is supposed to be a content of the file specified in the local field
local: petclinic.yaml
referenceContent: it is supposed to be a content of the file specified in the local field
reference: petclinic.yaml
selector:
app.kubernetes.io/name: mysql
app.kubernetes.io/component: database

View File

@ -16,7 +16,7 @@ name: petclinic-dev-environment
components:
- name: mysql
type: openshift
localContent: |
referenceContent: |
kind: List
items:
-
@ -32,7 +32,7 @@ components:
resources:
limits:
memory: 512Mi
local: petclinic.yaml
reference: petclinic.yaml
selector:
app.kubernetes.io/name: mysql
app.kubernetes.io/component: database

View File

@ -16,7 +16,7 @@ name: petclinic-dev-environment
components:
- name: mysql
type: openshift
local: petclinic.yaml
reference: petclinic.yaml
selector:
app.kubernetes.io/name: mysql
app.kubernetes.io/component: database

View File

@ -21,10 +21,10 @@ import javax.inject.Singleton;
import javax.validation.constraints.NotNull;
import org.eclipse.che.api.core.BadRequestException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.devfile.server.URLFetcher;
import org.eclipse.che.api.factory.server.FactoryParametersResolver;
import org.eclipse.che.api.factory.server.urlfactory.ProjectConfigDtoMerger;
import org.eclipse.che.api.factory.server.urlfactory.URLFactoryBuilder;
import org.eclipse.che.api.factory.server.urlfactory.URLFetcher;
import org.eclipse.che.api.factory.shared.dto.FactoryDto;
import org.eclipse.che.api.workspace.shared.dto.ProjectConfigDto;

View File

@ -16,7 +16,7 @@ import java.util.regex.Pattern;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.validation.constraints.NotNull;
import org.eclipse.che.api.factory.server.urlfactory.URLFetcher;
import org.eclipse.che.api.devfile.server.URLFetcher;
/**
* Parser of String Github URLs and provide {@link GithubUrl} objects.

View File

@ -17,7 +17,7 @@ import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import org.eclipse.che.api.factory.server.urlfactory.URLFetcher;
import org.eclipse.che.api.devfile.server.URLFetcher;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.testng.MockitoTestNGListener;

View File

@ -20,10 +20,10 @@ import javax.inject.Singleton;
import javax.validation.constraints.NotNull;
import org.eclipse.che.api.core.BadRequestException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.devfile.server.URLFetcher;
import org.eclipse.che.api.devfile.server.URLFileContentProvider;
import org.eclipse.che.api.factory.server.urlfactory.DefaultFactoryUrl;
import org.eclipse.che.api.factory.server.urlfactory.URLFactoryBuilder;
import org.eclipse.che.api.factory.server.urlfactory.URLFetcher;
import org.eclipse.che.api.factory.server.urlfactory.URLFileContentProvider;
import org.eclipse.che.api.factory.shared.dto.FactoryDto;
/**

View File

@ -1,101 +0,0 @@
/*
* 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.api.factory.server.urlfactory;
import static java.util.Objects.requireNonNull;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.concurrent.TimeUnit;
import javax.inject.Singleton;
import javax.validation.constraints.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Manages checking if URL are there or not
*
* @author Florent Benoit
*/
@Singleton
public class URLChecker {
/** Logger. */
private static final Logger LOG = LoggerFactory.getLogger(URLChecker.class);
/** Connection timeout of 10seconds. */
private static final int CONNECTION_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(10);
/** Error message to log. */
private static final String UNABLE_TO_CHECK_MESSAGE =
"Unable to check if remote location {0} is available or not. {1}";
/**
* Check if given URL location exists remotely
*
* @param url the URL to test
* @return true if remote URL is existing directly (no redirect)
*/
public boolean exists(@NotNull final String url) {
requireNonNull(url, "URL parameter cannot be null");
try {
return exists(new URL(url));
} catch (MalformedURLException e) {
LOG.debug(UNABLE_TO_CHECK_MESSAGE, url, e);
return false;
}
}
/**
* Check if given URL location exists remotely
*
* @param url the URL to test
* @return true if remote URL is existing directly (no redirect)
*/
public boolean exists(@NotNull final URL url) {
requireNonNull(url, "URL parameter cannot be null");
try {
final URLConnection urlConnection = url.openConnection();
urlConnection.setConnectTimeout(CONNECTION_TIMEOUT);
if (urlConnection instanceof HttpURLConnection) {
return exists((HttpURLConnection) urlConnection);
} else {
urlConnection.connect();
return true;
}
} catch (IOException ioe) {
LOG.debug(UNABLE_TO_CHECK_MESSAGE, url, ioe);
return false;
}
}
/**
* Check if given URL location exists remotely
*
* @param httpURLConnection the http url connection to test
* @return true if remote URL is existing directly (no redirect)
*/
protected boolean exists(final HttpURLConnection httpURLConnection) {
try {
return httpURLConnection.getResponseCode() == HttpURLConnection.HTTP_OK;
} catch (IOException ioe) {
LOG.debug(UNABLE_TO_CHECK_MESSAGE, httpURLConnection, ioe);
return false;
} finally {
httpURLConnection.disconnect();
}
}
}

View File

@ -28,6 +28,7 @@ import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.devfile.model.Devfile;
import org.eclipse.che.api.devfile.server.DevfileManager;
import org.eclipse.che.api.devfile.server.FileContentProvider;
import org.eclipse.che.api.devfile.server.URLFetcher;
import org.eclipse.che.api.devfile.server.exception.DevfileException;
import org.eclipse.che.api.factory.shared.dto.FactoryDto;
import org.eclipse.che.api.workspace.server.DtoConverter;

View File

@ -1,55 +0,0 @@
/*
* 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.api.factory.server.urlfactory;
import static java.lang.String.format;
import java.io.IOException;
import java.net.URI;
import org.eclipse.che.api.devfile.server.FileContentProvider;
/**
* A simple implementation of the FileContentProvider that merely uses the function resolve relative
* paths and {@link URLFetcher} for retrieving the content, handling common error cases.
*/
public class URLFileContentProvider implements FileContentProvider {
private final URI devfileLocation;
private final URLFetcher urlFetcher;
public URLFileContentProvider(URI devfileLocation, URLFetcher urlFetcher) {
this.devfileLocation = devfileLocation;
this.urlFetcher = urlFetcher;
}
@Override
public String fetchContent(String fileName) throws IOException {
URI fileUrl = devfileLocation.resolve(fileName);
try {
return urlFetcher.fetch(fileUrl.toString());
} catch (IOException e) {
throw new IOException(
format(
"Failed to fetch a file %s as relative to devfile %s from URL %s. Make sure the URL"
+ " of the devfile points to the raw content of it (e.g. not to the webpage"
+ " showing it but really just its contents). Additionally, make sure the"
+ " referenced files are actually stored relative to the devfile on the same"
+ " host. If none of that is possible, try to host your devfile on some other"
+ " location together with the referenced files in such a way that resolving the"
+ " \"local\" name of a component as a relative path against the devfile location"
+ " gives a true downloadable URL for that file. The current attempt to download"
+ " the file failed with the following error message: %s",
fileName, devfileLocation, fileUrl, e.getMessage()),
e);
}
}
}

View File

@ -28,6 +28,7 @@ import java.util.Set;
import org.eclipse.che.api.devfile.model.Component;
import org.eclipse.che.api.devfile.server.DevfileManager;
import org.eclipse.che.api.devfile.server.FileContentProvider;
import org.eclipse.che.api.devfile.server.URLFetcher;
import org.eclipse.che.api.devfile.server.convert.CommandConverter;
import org.eclipse.che.api.devfile.server.convert.DefaultEditorProvisioner;
import org.eclipse.che.api.devfile.server.convert.DevfileConverter;
@ -38,7 +39,6 @@ import org.eclipse.che.api.devfile.server.schema.DevfileSchemaProvider;
import org.eclipse.che.api.devfile.server.validator.DevfileIntegrityValidator;
import org.eclipse.che.api.devfile.server.validator.DevfileSchemaValidator;
import org.eclipse.che.api.factory.server.urlfactory.URLFactoryBuilder;
import org.eclipse.che.api.factory.server.urlfactory.URLFetcher;
import org.eclipse.che.api.workspace.server.WorkspaceManager;
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesRecipeParser;
import org.mockito.Mock;
@ -56,7 +56,7 @@ public class DefaultFactoryParameterResolverTest {
+ "components:\n"
+ "- type: kubernetes\n"
+ " name: component\n"
+ " local: ../localfile\n";
+ " reference: ../localfile\n";
@Mock private URLFetcher urlFetcher;
@Mock private KubernetesRecipeParser kubernetesRecipeParser;
@ -80,7 +80,7 @@ public class DefaultFactoryParameterResolverTest {
// local file. That's all we need to happen
FileContentProvider p = i.getArgument(2);
Component component = i.getArgument(1);
p.fetchContent(component.getLocal());
p.fetchContent(component.getReference());
return null;
})
.when(applier)

View File

@ -1,169 +0,0 @@
/*
* 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.api.factory.server.urlfactory;
import static org.eclipse.jetty.http.HttpStatus.NOT_FOUND_404;
import static org.eclipse.jetty.http.HttpStatus.OK_200;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.mockito.InjectMocks;
import org.mockito.testng.MockitoTestNGListener;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
/**
* Testing {@link URLChecker}
*
* @author Florent Benoit
*/
@Listeners(MockitoTestNGListener.class)
public class URLCheckerTest {
/** Instance to test. */
@InjectMocks private URLChecker URLChecker;
/** Http jetty instance used in tests. */
private Server server;
/** Port number used. */
private int port;
/** Check that when url is null, NPE is thrown */
@Test(expectedExceptions = NullPointerException.class)
public void checkNullURL() {
URLChecker.exists((String) null);
}
/** Check that the url exists */
@Test
public void checkUrlFileExists() {
// test to check if this url exist
URL urlJson =
URLCheckerTest.class.getResource(
"/" + URLCheckerTest.class.getName().replace('.', '/') + ".class");
Assert.assertNotNull(urlJson);
boolean exists = URLChecker.exists(urlJson);
assertTrue(exists);
}
/** Check when url doesn't exist */
@Test
public void checkUrlFileNotExists() {
// test to check if this url exist
URL urlJson = getClass().getClassLoader().getResource(".che.json");
Assert.assertNotNull(urlJson);
boolean exists = URLChecker.exists(urlJson.toString() + "-notfound");
assertFalse(exists);
}
/** Check when url is invalid */
@Test
public void checkUrlFileIsInvalid() {
boolean exists = URLChecker.exists("hello world");
assertFalse(exists);
}
/** Check when url is invalid */
@Test
public void checkUrlIsInvalid() throws MalformedURLException {
// test to check if this url exist
URL urlJson = getClass().getClassLoader().getResource(".che.json");
Assert.assertNotNull(urlJson);
boolean exists = URLChecker.exists(new URL(urlJson.toString() + "-notfound"));
assertFalse(exists);
}
/** Check HTTP url. */
@Test
public void checkHTTPUrl() throws IOException {
HttpURLConnection httpURLConnection = mock(HttpURLConnection.class);
// if 200, it's ok
when(httpURLConnection.getResponseCode()).thenReturn(OK_200);
boolean exists = URLChecker.exists(httpURLConnection);
assertTrue(exists);
// if 404, it's ko
reset(httpURLConnection);
when(httpURLConnection.getResponseCode()).thenReturn(NOT_FOUND_404);
exists = URLChecker.exists(httpURLConnection);
assertFalse(exists);
// failure, it's ko
reset(httpURLConnection);
when(httpURLConnection.getResponseCode()).thenThrow(IOException.class);
exists = URLChecker.exists(httpURLConnection);
assertFalse(exists);
// check local server
exists = URLChecker.exists("http://localhost:" + port);
assertTrue(exists);
}
/**
* Start http server to really test a HTTP endpoint. as URL can't be mock
*
* @throws Exception if server is not started
*/
@BeforeClass
public void startJetty() throws Exception {
this.server = new Server(0);
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
context.addServlet(new ServletHolder(new MyServlet()), "/");
this.server.setHandler(context);
this.server.start();
this.port = ((ServerConnector) server.getConnectors()[0]).getLocalPort();
}
/**
* Stops the server at the end
*
* @throws Exception
*/
@AfterClass
public void stopJetty() throws Exception {
server.stop();
}
/** Dummy servlet class. */
static class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.getOutputStream().print("hello");
}
}
}

View File

@ -28,6 +28,7 @@ import java.util.HashMap;
import java.util.Map;
import org.eclipse.che.api.devfile.model.Devfile;
import org.eclipse.che.api.devfile.server.DevfileManager;
import org.eclipse.che.api.devfile.server.URLFetcher;
import org.eclipse.che.api.factory.shared.dto.FactoryDto;
import org.eclipse.che.api.workspace.server.model.impl.EnvironmentImpl;
import org.eclipse.che.api.workspace.server.model.impl.RecipeImpl;