Allow to use reference to content
Signed-off-by: Max Shaposhnik <mshaposh@redhat.com>7.20.x
parent
b96fa87296
commit
3704ffccec
|
|
@ -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']
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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\"}]}}]}"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
@ -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)))
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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\"]]"
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -17,4 +17,4 @@ components:
|
|||
- name: theia-ide
|
||||
type: cheEditor
|
||||
id: eclipse/theia:0.0.3
|
||||
local: petclinic.yaml
|
||||
reference: petclinic.yaml
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -16,8 +16,8 @@ name: petclinic-dev-environment
|
|||
components:
|
||||
- name: mysql
|
||||
type: kubernetes
|
||||
local: petclinic.yaml
|
||||
localContent: |
|
||||
reference: petclinic.yaml
|
||||
referenceContent: |
|
||||
kind: List
|
||||
items:
|
||||
-
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue