Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support raw devfile urls without yaml extension #683

Merged
merged 5 commits into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2023 Red Hat, Inc.
* Copyright (c) 2012-2024 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/
Expand All @@ -16,7 +16,9 @@
import static org.eclipse.che.api.factory.server.FactoryResolverPriority.HIGHEST;
import static org.eclipse.che.api.factory.shared.Constants.URL_PARAMETER_NAME;

import com.fasterxml.jackson.databind.JsonNode;
import jakarta.validation.constraints.NotNull;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
Expand All @@ -30,8 +32,10 @@
import org.eclipse.che.api.factory.server.urlfactory.RemoteFactoryUrl;
import org.eclipse.che.api.factory.server.urlfactory.URLFactoryBuilder;
import org.eclipse.che.api.factory.shared.dto.FactoryMetaDto;
import org.eclipse.che.api.workspace.server.devfile.DevfileParser;
import org.eclipse.che.api.workspace.server.devfile.URLFetcher;
import org.eclipse.che.api.workspace.server.devfile.URLFileContentProvider;
import org.eclipse.che.api.workspace.server.devfile.exception.DevfileFormatException;

/**
* {@link FactoryParametersResolver} implementation to resolve factory based on url parameter as a
Expand All @@ -45,13 +49,15 @@ public class RawDevfileUrlFactoryParameterResolver extends BaseFactoryParameterR

protected final URLFactoryBuilder urlFactoryBuilder;
protected final URLFetcher urlFetcher;
private final DevfileParser devfileParser;

@Inject
public RawDevfileUrlFactoryParameterResolver(
URLFactoryBuilder urlFactoryBuilder, URLFetcher urlFetcher) {
URLFactoryBuilder urlFactoryBuilder, URLFetcher urlFetcher, DevfileParser devfileParser) {
super(null, urlFactoryBuilder, PROVIDER_NAME);
this.urlFactoryBuilder = urlFactoryBuilder;
this.urlFetcher = urlFetcher;
this.devfileParser = devfileParser;
}

/**
Expand All @@ -64,7 +70,17 @@ public RawDevfileUrlFactoryParameterResolver(
@Override
public boolean accept(Map<String, String> factoryParameters) {
String url = factoryParameters.get(URL_PARAMETER_NAME);
return !isNullOrEmpty(url) && PATTERN.matcher(url).matches();
return !isNullOrEmpty(url) && (PATTERN.matcher(url).matches() || containsYaml(url));
}

private boolean containsYaml(String requestURL) {
try {
String fetch = urlFetcher.fetch(requestURL);
JsonNode parsedYaml = devfileParser.parseYamlRaw(fetch);
return !parsedYaml.isEmpty();
} catch (IOException | DevfileFormatException e) {
return false;
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,14 @@
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.fail;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertTrue;

import com.fasterxml.jackson.databind.JsonNode;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.che.api.core.BadRequestException;
Expand Down Expand Up @@ -63,6 +66,7 @@ public class RawDevfileUrlFactoryParameterResolverTest {
+ " reference: ../localfile\n";

@Mock private URLFetcher urlFetcher;
@Mock private DevfileParser devfileParser;

@InjectMocks private RawDevfileUrlFactoryParameterResolver rawDevfileUrlFactoryParameterResolver;

Expand All @@ -84,7 +88,7 @@ public void shouldResolveRelativeFiles() throws Exception {
"editor", "plugin", false, devfileParser, new DevfileVersionDetector());

RawDevfileUrlFactoryParameterResolver res =
new RawDevfileUrlFactoryParameterResolver(factoryBuilder, urlFetcher);
new RawDevfileUrlFactoryParameterResolver(factoryBuilder, urlFetcher, devfileParser);

// set up our factory with the location of our devfile that is referencing our localfile
Map<String, String> factoryParameters = new HashMap<>();
Expand All @@ -106,7 +110,7 @@ public void shouldFilterAndProvideOverrideParameters() throws Exception {
URLFetcher urlFetcher = mock(URLFetcher.class);

RawDevfileUrlFactoryParameterResolver res =
new RawDevfileUrlFactoryParameterResolver(urlFactoryBuilder, urlFetcher);
new RawDevfileUrlFactoryParameterResolver(urlFactoryBuilder, urlFetcher, devfileParser);

Map<String, String> factoryParameters = new HashMap<>();
factoryParameters.put(URL_PARAMETER_NAME, "http://myloc/devfile");
Expand Down Expand Up @@ -137,7 +141,7 @@ public void shouldThrowExceptionOnInvalidURL(String url, String message) throws
URLFetcher urlFetcher = mock(URLFetcher.class);

RawDevfileUrlFactoryParameterResolver res =
new RawDevfileUrlFactoryParameterResolver(urlFactoryBuilder, urlFetcher);
new RawDevfileUrlFactoryParameterResolver(urlFactoryBuilder, urlFetcher, devfileParser);

Map<String, String> factoryParameters = new HashMap<>();
factoryParameters.put(URL_PARAMETER_NAME, url);
Expand Down Expand Up @@ -165,12 +169,67 @@ public void shouldAcceptRawDevfileUrl(String url) {
assertTrue(result);
}

@Test(dataProvider = "devfileUrlsWithoutExtension")
public void shouldAcceptRawDevfileUrlWithoutExtension(String url) throws Exception {
// given
JsonNode jsonNode = mock(JsonNode.class);
when(urlFetcher.fetch(eq(url))).thenReturn(DEVFILE);
when(devfileParser.parseYamlRaw(eq(DEVFILE))).thenReturn(jsonNode);
when(jsonNode.isEmpty()).thenReturn(false);

// when
boolean result =
rawDevfileUrlFactoryParameterResolver.accept(singletonMap(URL_PARAMETER_NAME, url));

// then
assertTrue(result);
}

@Test
public void shouldAcceptRawDevfileUrlWithYaml() throws Exception {
// given
JsonNode jsonNode = mock(JsonNode.class);
String url = "https://host/path/devfile";
when(urlFetcher.fetch(eq(url))).thenReturn(DEVFILE);
when(devfileParser.parseYamlRaw(eq(DEVFILE))).thenReturn(jsonNode);
when(jsonNode.isEmpty()).thenReturn(false);

// when
boolean result =
rawDevfileUrlFactoryParameterResolver.accept(singletonMap(URL_PARAMETER_NAME, url));

// then
assertTrue(result);
}

@Test
public void shouldNotAcceptPublicGitRepositoryUrl() throws Exception {
// given
JsonNode jsonNode = mock(JsonNode.class);
String gitRepositoryUrl = "https://host/user/repo.git";
when(urlFetcher.fetch(eq(gitRepositoryUrl))).thenReturn("unsupported content");
when(devfileParser.parseYamlRaw(eq("unsupported content"))).thenReturn(jsonNode);
when(jsonNode.isEmpty()).thenReturn(true);

// when
boolean result =
rawDevfileUrlFactoryParameterResolver.accept(
singletonMap(URL_PARAMETER_NAME, gitRepositoryUrl));

// then
assertFalse(result);
}

@Test
public void shouldNotAcceptRawDevfileUrl() {
public void shouldNotAcceptPrivateGitRepositoryUrl() throws Exception {
// given
String gitRepositoryUrl = "https://host/user/private-repo.git";
when(urlFetcher.fetch(eq(gitRepositoryUrl))).thenThrow(new FileNotFoundException());

// when
boolean result =
rawDevfileUrlFactoryParameterResolver.accept(
singletonMap(URL_PARAMETER_NAME, "https://host/user/repo.git"));
singletonMap(URL_PARAMETER_NAME, gitRepositoryUrl));

// then
assertFalse(result);
Expand Down Expand Up @@ -201,4 +260,9 @@ private Object[] devfileUrls() {
"https://host/path/any-name.yml?token=TOKEN123"
};
}

@DataProvider(name = "devfileUrlsWithoutExtension")
private Object[] devfileUrlsWithoutExtension() {
return new String[] {"https://host/path/any-name", "https://host/path/any-name?token=TOKEN123"};
}
}
Loading