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

Throw an error if Devfile from unsupported ssh repository is not reso… #770

Merged
merged 1 commit into from
Feb 26, 2025
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
4 changes: 2 additions & 2 deletions .ci/openshift-ci/test-gitea-no-pat-oauth-flow.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ trap "catchFinish" EXIT SIGINT
setupTestEnvironment ${OCP_NON_ADMIN_USER_NAME}
setupSSHKeyPairs "${GITEA_PRIVATE_KEY}" "${GITEA_PUBLIC_KEY}"

testFactoryResolverResponse ${PUBLIC_REPO_SSH_URL} 200
testFactoryResolverResponse ${PRIVATE_REPO_SSH_URL} 200
testFactoryResolverResponse ${PUBLIC_REPO_SSH_URL} 500
testFactoryResolverResponse ${PRIVATE_REPO_SSH_URL} 500
testFactoryResolverResponse ${PUBLIC_REPO_RAW_PATH_URL} 200

testCloneGitRepoProjectShouldExists ${PUBLIC_REPO_WORKSPACE_NAME} ${PUBLIC_PROJECT_NAME} ${PUBLIC_REPO_SSH_URL} ${USER_CHE_NAMESPACE}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# Copyright (c) 2012-2024 Red Hat, Inc.
# Copyright (c) 2012-2025 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 Down
4 changes: 4 additions & 0 deletions wsmaster/che-core-api-factory-git-ssh/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
<findbugs.failonerror>true</findbugs.failonerror>
</properties>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>jakarta.inject</groupId>
<artifactId>jakarta.inject-api</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2024 Red Hat, Inc.
* Copyright (c) 2012-2025 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 @@ -12,7 +12,6 @@
package org.eclipse.che.api.factory.server.git.ssh;

import static org.eclipse.che.api.factory.server.FactoryResolverPriority.LOWEST;
import static org.eclipse.che.api.factory.shared.Constants.CURRENT_VERSION;
import static org.eclipse.che.api.factory.shared.Constants.URL_PARAMETER_NAME;
import static org.eclipse.che.dto.server.DtoFactory.newDto;

Expand All @@ -35,7 +34,7 @@
import org.eclipse.che.api.workspace.server.devfile.URLFetcher;

/**
* Provides Factory Parameters resolver for Git Ssh repositories.
* Provides Factory Parameters resolver for SSH urls of unsupported Git providers.
*
* @author Anatolii Bazko
*/
Expand Down Expand Up @@ -90,15 +89,11 @@ public FactoryMetaDto createFactory(@NotNull final Map<String, String> factoryPa
gitSshUrl, urlFetcher, personalAccessTokenManager),
extractOverrideParams(factoryParameters),
true)
.orElseGet(
() -> newDto(FactoryDevfileV2Dto.class).withV(CURRENT_VERSION).withSource("repo"))
.orElseThrow(() -> new ApiException("Failed to fetch devfile"))
.acceptVisitor(new GitSshFactoryVisitor(gitSshUrl));
}

/**
* Visitor that puts the default devfile or updates devfile projects into the Git Ssh Factory, if
* needed.
*/
/** Visitor that updates factory dto with git ssh information. */
private class GitSshFactoryVisitor implements FactoryVisitor {

private final GitSshUrl gitSshUrl;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2023 Red Hat, Inc.
* Copyright (c) 2012-2025 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 Down Expand Up @@ -73,6 +73,9 @@ public Optional<String> filename() {

@Override
public String location() {
// Since we do not know the location from an SSH URL, we return the filename instead. The
// devfile content fetcher will always fail to fetch the devfile in this case.
// TODO: throw an error in order to avoid http request to fetch the devfile content.
return devfileFilename;
}
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*
* Copyright (c) 2012-2025 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.git.ssh;

import static java.util.Collections.singletonMap;
import static org.eclipse.che.api.factory.shared.Constants.CURRENT_VERSION;
import static org.eclipse.che.api.factory.shared.Constants.URL_PARAMETER_NAME;
import static org.eclipse.che.dto.server.DtoFactory.newDto;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;

import com.google.common.collect.ImmutableMap;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import org.eclipse.che.api.core.ApiException;
import org.eclipse.che.api.factory.server.scm.AuthorisationRequestManager;
import org.eclipse.che.api.factory.server.scm.PersonalAccessTokenManager;
import org.eclipse.che.api.factory.server.urlfactory.DevfileFilenamesProvider;
import org.eclipse.che.api.factory.server.urlfactory.URLFactoryBuilder;
import org.eclipse.che.api.factory.shared.dto.FactoryDevfileV2Dto;
import org.eclipse.che.api.factory.shared.dto.ScmInfoDto;
import org.eclipse.che.api.workspace.server.devfile.FileContentProvider;
import org.eclipse.che.api.workspace.server.devfile.URLFetcher;
import org.mockito.Mock;
import org.mockito.testng.MockitoTestNGListener;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;

@Listeners(MockitoTestNGListener.class)
public class GitSshFactoryParametersResolverTest {

@Mock private DevfileFilenamesProvider devfileFilenamesProvider;
@Mock private URLFetcher urlFetcher;
@Mock private URLFactoryBuilder urlFactoryBuilder;
@Mock private PersonalAccessTokenManager personalAccessTokenManager;
@Mock private AuthorisationRequestManager authorisationRequestManager;
@Mock private GitSshURLParser gitSshURLParser;
@Mock private GitSshUrl gitSshUrl;
private GitSshFactoryParametersResolver gitSshFactoryParametersResolver;

@BeforeMethod
protected void init() {
gitSshFactoryParametersResolver =
new GitSshFactoryParametersResolver(
gitSshURLParser,
urlFetcher,
urlFactoryBuilder,
personalAccessTokenManager,
authorisationRequestManager);
}

@Test
public void ShouldNotAcceptMissingParameter() {
// given
Map<String, String> parameters = singletonMap("foo", "this is a foo bar");
// when
boolean accept = gitSshFactoryParametersResolver.accept(parameters);
// then
assertFalse(accept);
}

@Test
public void ShouldNotAcceptInvalidUrl() {
// given
String url = "https://provider.com/user/repo.git";
when(gitSshURLParser.isValid(eq(url))).thenReturn(false);
Map<String, String> parameters = singletonMap(URL_PARAMETER_NAME, url);
// when
boolean accept = gitSshFactoryParametersResolver.accept(parameters);
// then
assertFalse(accept);
}

@Test
public void shouldAcceptValidUrl() {
// given
String url = "[email protected]:user/repo.git";
when(gitSshURLParser.isValid(eq(url))).thenReturn(true);
Map<String, String> parameters = singletonMap(URL_PARAMETER_NAME, url);
// when
boolean accept = gitSshFactoryParametersResolver.accept(parameters);
// then
assertTrue(accept);
}

@Test
public void shouldCreateFactoryWithDevfile() throws Exception {
// given
String url = "[email protected]:user/repo.git";
when(gitSshUrl.getProviderName()).thenReturn("git-ssh");
when(gitSshUrl.getRepositoryLocation()).thenReturn("repository-location");
ImmutableMap<String, String> params = ImmutableMap.of(URL_PARAMETER_NAME, url);
when(gitSshURLParser.parse(eq(url))).thenReturn(gitSshUrl);
when(urlFactoryBuilder.createFactoryFromDevfile(
eq(gitSshUrl), any(FileContentProvider.class), eq(Collections.emptyMap()), eq(true)))
.thenReturn(Optional.of(generateDevfileV2Factory()));
// when
FactoryDevfileV2Dto factory =
(FactoryDevfileV2Dto) gitSshFactoryParametersResolver.createFactory(params);
// then
ScmInfoDto scmInfo = factory.getScmInfo();
assertEquals(scmInfo.getScmProviderName(), "git-ssh");
assertEquals(scmInfo.getRepositoryUrl(), "repository-location");
}

@Test(
expectedExceptions = ApiException.class,
expectedExceptionsMessageRegExp = "Failed to fetch devfile")
public void shouldThrowException() throws Exception {
// given
String url = "[email protected]:user/repo.git";
ImmutableMap<String, String> params = ImmutableMap.of(URL_PARAMETER_NAME, url);
when(gitSshURLParser.parse(eq(url))).thenReturn(gitSshUrl);
when(urlFactoryBuilder.createFactoryFromDevfile(
eq(gitSshUrl), any(FileContentProvider.class), eq(Collections.emptyMap()), eq(true)))
.thenReturn(Optional.empty());
// when
FactoryDevfileV2Dto factory =
(FactoryDevfileV2Dto) gitSshFactoryParametersResolver.createFactory(params);
}

private FactoryDevfileV2Dto generateDevfileV2Factory() {
return newDto(FactoryDevfileV2Dto.class)
.withV(CURRENT_VERSION)
.withSource("repo")
.withDevfile(Map.of("schemaVersion", "2.0.0"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2012-2025 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.git.ssh;

import static org.testng.Assert.assertEquals;

import java.util.Arrays;
import java.util.List;
import org.eclipse.che.api.factory.server.urlfactory.RemoteFactoryUrl.DevfileLocation;
import org.mockito.testng.MockitoTestNGListener;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;

@Listeners(MockitoTestNGListener.class)
public class GitSshUrlTest {

@Test
public void shouldReturnDevfileLocations() throws Exception {
String[] devfileNames = {"devfile.yaml", ".devfile.yaml"};
GitSshUrl sshUrl =
new GitSshUrl()
.withRepository("repository")
.withHostName("hostname")
.withDevfileFilenames(Arrays.asList(devfileNames));
List<DevfileLocation> devfileLocations = sshUrl.devfileFileLocations();
assertEquals(devfileLocations.size(), 2);
assertEquals(devfileLocations.get(0).location(), "devfile.yaml");
assertEquals(devfileLocations.get(1).location(), ".devfile.yaml");
}
}
Loading