diff --git a/.gitignore b/.gitignore
index 210b2e2..a410fbd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,3 +31,6 @@ out
# ci config for local ci build
.circleci/local-config.yml
venv*
+/.metadata/
+**/bin
+**/target
diff --git a/README.md b/README.md
index 0025752..39cda33 100644
--- a/README.md
+++ b/README.md
@@ -56,6 +56,7 @@ The table below outlines what version of Nexus Repository the plugin was built a
| v0.2.1 | 3.31.0-01 |
| v0.2.2 | 3.38.0-01 / 3.39.0.01 |
| v0.3.0 | \>= 3.41.0 |
+| v0.3.1 | \>= 3.41.0 |
If a new version of Nexus Repository is released and the plugin needs changes, a new release will be made, and this
table will be updated to indicate which version of Nexus Repository it will function against. This is done on a time
diff --git a/nexus-repository-ansiblegalaxy-it/pom.xml b/nexus-repository-ansiblegalaxy-it/pom.xml
index d7fd5bd..b1667f5 100644
--- a/nexus-repository-ansiblegalaxy-it/pom.xml
+++ b/nexus-repository-ansiblegalaxy-it/pom.xml
@@ -19,7 +19,7 @@
org.sonatype.nexus.plugins
nexus-repository-ansiblegalaxy-parent
- 0.3.0
+ 0.3.2
nexus-repository-ansiblegalaxy-it
diff --git a/nexus-repository-ansiblegalaxy/pom.xml b/nexus-repository-ansiblegalaxy/pom.xml
index 6b7e16f..ec75ef0 100644
--- a/nexus-repository-ansiblegalaxy/pom.xml
+++ b/nexus-repository-ansiblegalaxy/pom.xml
@@ -19,7 +19,7 @@
org.sonatype.nexus.plugins
nexus-repository-ansiblegalaxy-parent
- 0.3.0
+ 0.3.2
nexus-repository-ansiblegalaxy
diff --git a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/AnsibleGalaxyApiRepositoryAdapter.java b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/AnsibleGalaxyApiRepositoryAdapter.java
new file mode 100644
index 0000000..dbc59b2
--- /dev/null
+++ b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/AnsibleGalaxyApiRepositoryAdapter.java
@@ -0,0 +1,83 @@
+/*
+ * Sonatype Nexus (TM) Open Source Version
+ * Copyright (c) 2020-present Sonatype, Inc.
+ * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
+ *
+ * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
+ * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
+ * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
+ * Eclipse Foundation. All other trademarks are the property of their respective owners.
+ */
+package org.sonatype.nexus.plugins.ansiblegalaxy.api;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.sonatype.nexus.common.collect.NestedAttributesMap;
+import org.sonatype.nexus.common.text.Strings2;
+import org.sonatype.nexus.repository.Repository;
+import org.sonatype.nexus.repository.rest.api.SimpleApiRepositoryAdapter;
+import org.sonatype.nexus.repository.rest.api.model.AbstractApiRepository;
+import org.sonatype.nexus.repository.routing.RoutingRuleStore;
+import org.sonatype.nexus.repository.types.HostedType;
+import org.sonatype.nexus.repository.types.ProxyType;
+
+import org.sonatype.nexus.plugins.ansiblegalaxy.AnsibleGalaxyFormat;
+import org.sonatype.nexus.plugins.ansiblegalaxy.AnsibleGalaxyAttributes;
+import org.sonatype.nexus.plugins.ansiblegalaxy.AnsibleGalaxyHostedApiRepository;
+import org.sonatype.nexus.plugins.ansiblegalaxy.AnsibleGalaxyProxyApiRepository;
+
+@Named(AnsibleGalaxyFormat.NAME)
+public class AnsibleGalaxyApiRepositoryAdapter
+ extends SimpleApiRepositoryAdapter
+{
+ private static final String ANSIBLEGALAXY = "ansiblegalaxy";
+
+ @Inject
+ public AnsibleGalaxyApiRepositoryAdapter(final RoutingRuleStore routingRuleStore) {
+ super(routingRuleStore);
+ }
+
+ @Override
+ public AbstractApiRepository adapt(final Repository repository) {
+ boolean online = repository.getConfiguration().isOnline();
+ String name = repository.getName();
+ String url = repository.getUrl();
+
+ switch( repository.getType().toString()) {
+ case HostedType.NAME:
+ return new AnsibleGalaxyHostedApiRepository(
+ repository.getName(),
+ repository.getUrl(),
+ repository.getConfiguration().isOnline(),
+ getHostedStorageAttributes(repository),
+ getCleanupPolicyAttributes(repository),
+ getComponentAttributes(repository),
+ createAnsibleGalaxyAttributes(repository)
+ );
+ case ProxyType.NAME:
+ return new AnsibleGalaxyProxyApiRepository(
+ repository.getName(),
+ repository.getUrl(),
+ repository.getConfiguration().isOnline(),
+ getHostedStorageAttributes(repository),
+ getCleanupPolicyAttributes(repository),
+ getProxyAttributes(repository),
+ getNegativeCacheAttributes(repository),
+ getHttpClientAttributes(repository),
+ getRoutingRuleName(repository),
+ getReplicationAttributes(repository),
+ createAnsibleGalaxyAttributes(repository)
+ );
+ default:
+ return super.adapt(repository);
+ }
+ }
+
+ private AnsibleGalaxyAttributes createAnsibleGalaxyAttributes(final Repository repository) {
+ String disposition = repository.getConfiguration().attributes(ANSIBLEGALAXY).get("contentDisposition", String.class);
+ return new AnsibleGalaxyAttributes(disposition);
+ }
+}
diff --git a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/AnsibleGalaxyAttributes.java b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/AnsibleGalaxyAttributes.java
new file mode 100644
index 0000000..07065eb
--- /dev/null
+++ b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/AnsibleGalaxyAttributes.java
@@ -0,0 +1,37 @@
+/*
+ * Sonatype Nexus (TM) Open Source Version
+ * Copyright (c) 2020-present Sonatype, Inc.
+ * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
+ *
+ * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
+ * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
+ * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
+ * Eclipse Foundation. All other trademarks are the property of their respective owners.
+ */
+package org.sonatype.nexus.plugins.ansiblegalaxy;
+
+import javax.validation.constraints.NotEmpty;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.annotations.ApiModelProperty;
+
+public class AnsibleGalaxyAttributes
+{
+ @ApiModelProperty(value = "Content Disposition",
+ allowableValues = "INLINE,ATTACHMENT", example = "ATTACHMENT")
+ @NotEmpty
+ private final String contentDisposition;
+
+ @JsonCreator
+ public AnsibleGalaxyAttributes(
+ @JsonProperty("contentDisposition") final String contentDisposition) {
+ this.contentDisposition = contentDisposition;
+ }
+
+ public String getContentDisposition() {
+ return contentDisposition;
+ }
+}
diff --git a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/AnsibleGalaxyHostedApiRepository.java b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/AnsibleGalaxyHostedApiRepository.java
new file mode 100644
index 0000000..dc2264f
--- /dev/null
+++ b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/AnsibleGalaxyHostedApiRepository.java
@@ -0,0 +1,54 @@
+/*
+ * Sonatype Nexus (TM) Open Source Version
+ * Copyright (c) 2020-present Sonatype, Inc.
+ * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
+ *
+ * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
+ * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
+ * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
+ * Eclipse Foundation. All other trademarks are the property of their respective owners.
+ */
+package org.sonatype.nexus.plugins.ansiblegalaxy;
+
+import javax.validation.constraints.NotNull;
+
+import org.sonatype.nexus.plugins.ansiblegalaxy.AnsibleGalaxyFormat;
+import org.sonatype.nexus.repository.rest.api.model.CleanupPolicyAttributes;
+import org.sonatype.nexus.repository.rest.api.model.ComponentAttributes;
+import org.sonatype.nexus.repository.rest.api.model.HostedStorageAttributes;
+import org.sonatype.nexus.repository.rest.api.model.SimpleApiHostedRepository;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import org.sonatype.nexus.plugins.ansiblegalaxy.AnsibleGalaxyAttributes;
+
+/**
+ * @since 3.41
+ */
+public class AnsibleGalaxyHostedApiRepository
+ extends SimpleApiHostedRepository
+{
+ @NotNull
+ private final AnsibleGalaxyAttributes ansiblegalaxy;
+
+ @JsonCreator
+ public AnsibleGalaxyHostedApiRepository(
+ @JsonProperty("name") final String name,
+ @JsonProperty("url") final String url,
+ @JsonProperty("online") final Boolean online,
+ @JsonProperty("storage") final HostedStorageAttributes storage,
+ @JsonProperty("cleanup") final CleanupPolicyAttributes cleanup,
+ @JsonProperty("component") final ComponentAttributes component,
+ @JsonProperty("ansiblegalaxy") final AnsibleGalaxyAttributes ansiblegalaxy)
+ {
+ super(name, AnsibleGalaxyFormat.NAME, url, online, storage, cleanup, component);
+ this.ansiblegalaxy = ansiblegalaxy;
+ }
+
+ public AnsibleGalaxyAttributes getAnsibleGalaxy() {
+ return ansiblegalaxy;
+ }
+}
diff --git a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/AnsibleGalaxyProxyApiRepository.java b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/AnsibleGalaxyProxyApiRepository.java
new file mode 100644
index 0000000..c61346d
--- /dev/null
+++ b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/AnsibleGalaxyProxyApiRepository.java
@@ -0,0 +1,63 @@
+/*
+ * Sonatype Nexus (TM) Open Source Version
+ * Copyright (c) 2020-present Sonatype, Inc.
+ * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
+ *
+ * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
+ * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
+ * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
+ * Eclipse Foundation. All other trademarks are the property of their respective owners.
+ */
+package org.sonatype.nexus.plugins.ansiblegalaxy;
+
+import javax.validation.constraints.NotNull;
+
+import org.sonatype.nexus.plugins.ansiblegalaxy.AnsibleGalaxyFormat;
+import org.sonatype.nexus.repository.rest.api.model.CleanupPolicyAttributes;
+import org.sonatype.nexus.repository.rest.api.model.HttpClientAttributes;
+import org.sonatype.nexus.repository.rest.api.model.NegativeCacheAttributes;
+import org.sonatype.nexus.repository.rest.api.model.ProxyAttributes;
+import org.sonatype.nexus.repository.rest.api.model.ReplicationAttributes;
+import org.sonatype.nexus.repository.rest.api.model.SimpleApiProxyRepository;
+import org.sonatype.nexus.repository.rest.api.model.StorageAttributes;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import org.sonatype.nexus.plugins.ansiblegalaxy.AnsibleGalaxyAttributes;
+
+/**
+ * @since 3.41
+ */
+public class AnsibleGalaxyProxyApiRepository
+ extends SimpleApiProxyRepository
+{
+
+ @NotNull
+ private final AnsibleGalaxyAttributes ansiblegalaxy;
+
+ public AnsibleGalaxyProxyApiRepository(
+ @JsonProperty("name") final String name,
+ @JsonProperty("url") final String url,
+ @JsonProperty("online") final Boolean online,
+ @JsonProperty("storage") final StorageAttributes storage,
+ @JsonProperty("cleanup") final CleanupPolicyAttributes cleanup,
+ @JsonProperty("proxy") final ProxyAttributes proxy,
+ @JsonProperty("negativeCache") final NegativeCacheAttributes negativeCache,
+ @JsonProperty("httpClient") final HttpClientAttributes httpClient,
+ @JsonProperty("routingRuleName") final String routingRuleName,
+ @JsonProperty("replication") @JsonInclude(value= Include.NON_EMPTY, content=Include.NON_NULL)
+ final ReplicationAttributes replication,
+ @JsonProperty("ansiblegalaxy") final AnsibleGalaxyAttributes ansiblegalaxy)
+ {
+ super(name, AnsibleGalaxyFormat.NAME, url, online, storage, cleanup, proxy, negativeCache, httpClient, routingRuleName, replication);
+ this.ansiblegalaxy = ansiblegalaxy;
+ }
+
+ public AnsibleGalaxyAttributes getAnsibleGalaxy() {
+ return ansiblegalaxy;
+ }
+}
\ No newline at end of file
diff --git a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/AssetKind.java b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/AssetKind.java
index 78a5e89..e5f31e5 100644
--- a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/AssetKind.java
+++ b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/AssetKind.java
@@ -26,6 +26,7 @@ public enum AssetKind {
API_METADATA(METADATA),
COLLECTION_DETAIL(METADATA),
COLLECTION_VERSION_LIST(METADATA),
+ COLLECTION_VERSION_LIST_LIMIT(METADATA),
COLLECTION_VERSION_DETAIL(METADATA),
COLLECTION_ARTIFACT(CONTENT),
ROLE_SEARCH(METADATA),
diff --git a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/ContentDisposition.java b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/ContentDisposition.java
new file mode 100644
index 0000000..693e567
--- /dev/null
+++ b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/ContentDisposition.java
@@ -0,0 +1,28 @@
+/*
+ * Sonatype Nexus (TM) Open Source Version
+ * Copyright (c) 2020-present Sonatype, Inc.
+ * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
+ *
+ * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
+ * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
+ * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
+ * Eclipse Foundation. All other trademarks are the property of their respective owners.
+ */
+package org.sonatype.nexus.plugins.ansiblegalaxy;
+
+public enum ContentDisposition {
+ INLINE("inline"),
+ ATTACHMENT("attachment");
+
+ private final String value;
+
+ ContentDisposition(final String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/ContentDispositionHandler.java b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/ContentDispositionHandler.java
new file mode 100644
index 0000000..0fa17e4
--- /dev/null
+++ b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/ContentDispositionHandler.java
@@ -0,0 +1,44 @@
+/*
+ * Sonatype Nexus (TM) Open Source Version
+ * Copyright (c) 2020-present Sonatype, Inc.
+ * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
+ *
+ * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
+ * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
+ * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
+ * Eclipse Foundation. All other trademarks are the property of their respective owners.
+ */
+package org.sonatype.nexus.plugins.ansiblegalaxy;
+
+import javax.annotation.Nonnull;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.sonatype.nexus.repository.view.Context;
+import org.sonatype.nexus.repository.view.Handler;
+import org.sonatype.nexus.repository.view.Response;
+
+import static org.sonatype.nexus.repository.http.HttpMethods.GET;
+
+
+public class ContentDispositionHandler
+ implements Handler
+{
+ public static final String CONTENT_DISPOSITION_CONFIG_KEY = "contentDisposition";
+
+ @Nonnull
+ @Override
+ public Response handle(@Nonnull final Context context) throws Exception {
+ Response response = context.proceed();
+ String action = context.getRequest().getAction();
+ if (GET.equals(action)) {
+ String contentDisposition = context.getRepository().getConfiguration().attributes("ansiblegalaxy")
+ .get(CONTENT_DISPOSITION_CONFIG_KEY, String.class, ContentDisposition.INLINE.name());
+
+ response.getHeaders().replace("Content-Disposition", ContentDisposition.valueOf(contentDisposition).getValue());
+ }
+ return response;
+ }
+}
diff --git a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/AnsibleGalaxyRecipeSupport.groovy b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/AnsibleGalaxyRecipeSupport.groovy
index 7f56d86..797e87b 100644
--- a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/AnsibleGalaxyRecipeSupport.groovy
+++ b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/AnsibleGalaxyRecipeSupport.groovy
@@ -151,6 +151,14 @@ abstract class AnsibleGalaxyRecipeSupport
setAssetKind(AssetKind.COLLECTION_VERSION_LIST)
)
}
+ // /api/v3/plugin/ansible/content/published/collections/index/ansible/netcommon/versions/
+ static Matcher collectionVersionListMatcherPages() {
+ LogicMatchers.and(
+ new ActionMatcher(GET, HEAD),
+ new QueryTokenMatcher("/api/{apiversion}/plugin/ansible/content/published/collections/index/{author}/{module}/versions/", [limit: "limit", offset: "offset"]),
+ setAssetKind(AssetKind.COLLECTION_VERSION_LIST_LIMIT)
+ )
+ }
static Matcher collectionVersionDetailMatcher() {
LogicMatchers.and(
@@ -161,6 +169,14 @@ abstract class AnsibleGalaxyRecipeSupport
}
static Matcher collectionArtifactMatcher() {
+ LogicMatchers.and(
+ new ActionMatcher(GET, HEAD),
+ new TokenMatcher("/api/{apiversion}/plugin/ansible/content/published/collections/artifacts/{author}-{module}-{version}.tar.gz"),
+ setAssetKind(AssetKind.COLLECTION_ARTIFACT)
+ )
+ }
+
+ static Matcher collectionArtifactV2Matcher() {
LogicMatchers.and(
new ActionMatcher(GET, HEAD),
new TokenMatcher("/download/{author}-{module}-{version}.tar.gz"),
@@ -168,10 +184,12 @@ abstract class AnsibleGalaxyRecipeSupport
)
}
+ // https://repo.angeloxx.lan/repository/galaxy/api/v3/plugin/ansible/content/published/collections/artifacts/telekom_mms-icinga_director-1.34.1.tar.gz
+ // /api/v3/plugin/ansible/content/published/collections/artifacts/telekom_mms-icinga_director-1.34.1.tar.gz
static Matcher collectionArtifactIhmMatcher() {
LogicMatchers.and(
new ActionMatcher(GET, HEAD),
- new TokenMatcher("/collection/{author}/{module}/{version}/{author}-{module}-{version}.tar.gz"),
+ new TokenMatcher("/api/{apiversion}/plugin/ansible/content/published/collections/artifacts/{author}-{module}-{version}.tar.gz"),
setAssetKind(AssetKind.COLLECTION_ARTIFACT)
)
}
diff --git a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/hosted/AnsibleGalaxyHostedFacetImpl.java b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/hosted/AnsibleGalaxyHostedFacetImpl.java
index 307ed7a..d507c8e 100644
--- a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/hosted/AnsibleGalaxyHostedFacetImpl.java
+++ b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/hosted/AnsibleGalaxyHostedFacetImpl.java
@@ -43,6 +43,7 @@
import static org.sonatype.nexus.plugins.ansiblegalaxy.internal.util.AnsibleGalaxyDataAccess.HASH_ALGORITHMS;
import static org.sonatype.nexus.repository.storage.AssetEntityAdapter.P_ASSET_KIND;
import static org.sonatype.nexus.repository.storage.MetadataNodeEntityAdapter.P_NAME;
+import static org.sonatype.nexus.repository.storage.ComponentEntityAdapter.P_VERSION;
@Named
@@ -85,7 +86,7 @@ public AnsibleGalaxyHostedFacetImpl(AnsibleGalaxyDataAccess ansibleGalaxyDataAcc
this.sorting = new ArrayList<>();
this.sorting.add(SortBuilders.fieldSort(P_NAME).order(SortOrder.ASC));
- this.sorting.add(SortBuilders.fieldSort(ComponentEntityAdapter.P_VERSION).order(SortOrder.ASC));
+ this.sorting.add(SortBuilders.fieldSort(P_VERSION).order(SortOrder.ASC));
}
@TransactionalTouchBlob
@@ -171,8 +172,8 @@ private AnsibleGalaxyModules getModuleReleasesFromSearchResponse(
list.add(getRepository());
String baseUrlRepo = getRepository().getUrl();
Iterable assets;
- assets = tx.findAssets(Query.builder().where(P_NAME).like(String.format("%%%s/%s%%", user, module)).build(), list);
- long count = tx.countAssets(Query.builder().where(P_NAME).like(String.format("%%%s/%s%%", user, module)).build(), list);
+ assets = tx.findAssets(Query.builder().where(P_NAME).like(String.format("%%%s-%s%%", user, module)).build(), list);
+ long count = tx.countAssets(Query.builder().where(P_NAME).like(String.format("%%%s-%s%%", user, module)).build(), list);
AnsibleGalaxyModules releases = moduleBuilder.parse(count, count, 0, context);
for (Asset asset : assets) {
@@ -194,14 +195,20 @@ public Content moduleByNameAndVersion(Context context, String user, String modul
list.add(getRepository());
String baseUrlRepo = getRepository().getUrl();
Asset asset = null;
+ String asset_version = null;
Iterable assets;
- assets = tx.findAssets(Query.builder().where(P_NAME).like(String.format("%%%s/%s%%", user, module)).build(), list);
+ assets = tx.findAssets(Query
+ .builder()
+ .where(P_NAME).like(String.format("%%%s-%s%%", user, module, version))
+ .build(), list);
for (Asset assetX : assets) {
asset = assetX;
- break;
+ asset_version = (String) asset.formatAttributes().get("version");
+ if ( asset_version.equals(version) ) { break; }
}
+
AnsibleGalaxyModule result = new AnsibleGalaxyModule();
- result.setVersion(version)
+ result.setVersion(asset_version)
.setHref(ansibleGalaxyPathUtils.parseHref(baseUrlRepo, asset.attributes().child("ansiblegalaxy").get("name").toString(), asset.attributes().child("ansiblegalaxy").get("version").toString()))
.setDownload_url(ansibleGalaxyPathUtils.download(baseUrlRepo, user, module, version))
.setNamespace(new AnsibleGalaxyModule.AnsibleGalaxyModuleNamespace().setName(user))
@@ -273,5 +280,4 @@ private Component findOrCreateComponent(final StorageTx tx,
}
return component;
}
-}
-
+}
\ No newline at end of file
diff --git a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/hosted/AnsibleGalaxyHostedRecipe.groovy b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/hosted/AnsibleGalaxyHostedRecipe.groovy
index 99045be..597e1f5 100644
--- a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/hosted/AnsibleGalaxyHostedRecipe.groovy
+++ b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/hosted/AnsibleGalaxyHostedRecipe.groovy
@@ -112,7 +112,6 @@ class AnsibleGalaxyHostedRecipe
.handler(hostedHandlers.collectionVersionDetail)
.create())
-
builder.route(new Route.Builder().matcher(collectionArtifactMatcher())
.handler(timingHandler)
.handler(securityHandler)
diff --git a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/proxy/AnsibleGalaxyProxyFacetImpl.java b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/proxy/AnsibleGalaxyProxyFacetImpl.java
index fbfbbc2..af4576a 100644
--- a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/proxy/AnsibleGalaxyProxyFacetImpl.java
+++ b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/proxy/AnsibleGalaxyProxyFacetImpl.java
@@ -14,6 +14,9 @@
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.HttpRequestBase;
+import org.eclipse.aether.util.version.GenericVersionScheme;
+import org.eclipse.aether.version.InvalidVersionSpecificationException;
+import org.eclipse.aether.version.Version;
import org.slf4j.Logger;
import org.sonatype.goodies.common.Loggers;
import org.sonatype.nexus.plugins.ansiblegalaxy.AssetKind;
@@ -112,6 +115,8 @@ protected Content getCachedContent(final Context context) {
return getAsset(ansiblegalaxyPathUtils.collectionDetailPath(matcherState));
case COLLECTION_VERSION_LIST:
return getAsset(ansiblegalaxyPathUtils.collectionVersionPagedPath(matcherState));
+ case COLLECTION_VERSION_LIST_LIMIT:
+ return getAsset(ansiblegalaxyPathUtils.collectionVersionLimitPath(matcherState));
case COLLECTION_VERSION_DETAIL:
return getAsset(ansiblegalaxyPathUtils.collectionVersionDetailPath(matcherState));
case COLLECTION_ARTIFACT:
@@ -152,6 +157,8 @@ protected Content store(final Context context, final Content content) throws IOE
return putAsset(context, content, ansiblegalaxyPathUtils.collectionDetailPath(matcherState), assetKind);
case COLLECTION_VERSION_LIST:
return putAsset(context, content, ansiblegalaxyPathUtils.collectionVersionPagedPath(matcherState), assetKind);
+ case COLLECTION_VERSION_LIST_LIMIT:
+ return putAsset(context, content, ansiblegalaxyPathUtils.collectionVersionLimitPath(matcherState), assetKind);
case COLLECTION_VERSION_DETAIL:
return putComponent(context, ansiblegalaxyPathUtils.getCollectionAttributes(matcherState), content,
ansiblegalaxyPathUtils.collectionVersionDetailPath(matcherState), assetKind);
@@ -222,6 +229,26 @@ private InputStream getUpdatedContent(Context context, AssetKind assetKind, Inpu
replacers.add(new JsonPostpendReplacer(downloadUrlFieldName, queryString));
}
+ return new ReplacerStream(replacers).getReplacedContent(in);
+ } else if (assetKind == AssetKind.COLLECTION_VERSION_LIST || assetKind == AssetKind.COLLECTION_VERSION_LIST_LIMIT) {
+
+ List replacers = new ArrayList<>();
+
+ /* API Bug IMHO - https://github.com/ansible/awx/issues/14495 */
+ replacers.add(new JsonPrependReplacer("first", "/repository/" + getRepository().getName()));
+ replacers.add(new JsonPrependReplacer("previous", "/repository/" + getRepository().getName()));
+ replacers.add(new JsonPrependReplacer("last", "/repository/" + getRepository().getName()));
+ replacers.add(new JsonPrependReplacer("next", "/repository/" + getRepository().getName()));
+
+ // If client version < 2.13.9 remove "next" (backward compatibility, reduce options)
+ String userAgent = context.getRequest().getHeaders().get("User-Agent");
+ if (userAgent != null && userAgent.startsWith("ansible-galaxy/")) {
+ if (isUserAgentVersionLowerOrEqual(userAgent, "2.13.9")) {
+ log.info("Backward compatibility layer in action, mind some versions will be omitted");
+ replacers.add(new JsonSearchReplacer("next", ""));
+ }
+ }
+
return new ReplacerStream(replacers).getReplacedContent(in);
}
@@ -230,6 +257,20 @@ private InputStream getUpdatedContent(Context context, AssetKind assetKind, Inpu
return new ReplacerStream(urlReplacer).getReplacedContent(in);
}
+ private boolean isUserAgentVersionLowerOrEqual(String userAgent, String targetVersionString) {
+ try {
+ String version = userAgent.split("/")[1];
+ GenericVersionScheme versionScheme = new GenericVersionScheme();
+ Version userAgentVersion = versionScheme.parseVersion(version);
+ Version targetVersion = versionScheme.parseVersion(targetVersionString);
+
+ return userAgentVersion.compareTo(targetVersion) <= 0;
+ } catch (InvalidVersionSpecificationException e) {
+ log.info("isUserAgentVersionLowerOrEqual returns an error ({} vs {}), assuming false", userAgent, targetVersionString);
+ return false;
+ }
+ }
+
private String getModuleName(Context context) {
String path = context.getRequest().getPath().replaceFirst(ROLE_VERSION_URI_SUFFIX, "");
Request roleDetailRequest = new Request.Builder().copy(context.getRequest()).action(HttpMethods.GET).path(path)
diff --git a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/proxy/AnsibleGalaxyProxyRecipe.groovy b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/proxy/AnsibleGalaxyProxyRecipe.groovy
index f75b3d9..90d107b 100644
--- a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/proxy/AnsibleGalaxyProxyRecipe.groovy
+++ b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/proxy/AnsibleGalaxyProxyRecipe.groovy
@@ -77,8 +77,10 @@ class AnsibleGalaxyProxyRecipe
apiInternalsMatcher(),
collectionDetailMatcher(),
collectionVersionListMatcher(),
+ collectionVersionListMatcherPages(),
collectionVersionDetailMatcher(),
collectionArtifactMatcher(),
+ collectionArtifactV2Matcher(),
collectionArtifactIhmMatcher(),
roleSearchMatcher(),
roleDetailMatcher(),
diff --git a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/proxy/replacer/JsonSearchReplacer.java b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/proxy/replacer/JsonSearchReplacer.java
index 168a466..d63462a 100644
--- a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/proxy/replacer/JsonSearchReplacer.java
+++ b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/proxy/replacer/JsonSearchReplacer.java
@@ -32,8 +32,17 @@ public JsonSearchReplacer(String jsonFieldName, String search, String replace) {
this.replace = checkNotNull(replace);
}
+ public JsonSearchReplacer(String jsonFieldName, String replace) {
+ super(jsonFieldName);
+ this.search = null;
+ this.replace = checkNotNull(replace);
+ }
+
@Override
protected String getUpdatedContent(JsonNode field) {
+ if (search == null) {
+ return replace;
+ }
return field.asText().replaceAll(search, replace);
}
diff --git a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/util/AnsibleGalaxyPathUtils.java b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/util/AnsibleGalaxyPathUtils.java
index 92580a9..383fc96 100644
--- a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/util/AnsibleGalaxyPathUtils.java
+++ b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/util/AnsibleGalaxyPathUtils.java
@@ -77,6 +77,13 @@ public String page_size(final TokenMatcher.State state) {
return StringUtils.defaultIfBlank(state.getTokens().get("page_size"), "20");
}
+ public String offset(final TokenMatcher.State state) {
+ return StringUtils.defaultIfBlank(state.getTokens().get("offset"), "0");
+ }
+ public String limit(final TokenMatcher.State state) {
+ return StringUtils.defaultIfBlank(state.getTokens().get("limit"), "100");
+ }
+
public TokenMatcher.State matcherState(final Context context) {
State state = context.getAttributes().require(TokenMatcher.State.class);
log.debug("matched state tokens: {}", state.getTokens());
@@ -112,6 +119,15 @@ public String collectionVersionPagedPath(final State matcherState) {
return String.format("%s/%s/%s/versions%s.json", COLLECTION_PATH, author, module, page);
}
+ public String collectionVersionLimitPath(final State matcherState) {
+ String author = author(matcherState);
+ String module = module(matcherState);
+ String offset = offset(matcherState);
+ String limit = limit(matcherState);
+
+ return String.format("%s/%s/%s/versions-offset-%s-%s.json", COLLECTION_PATH, author, module, offset, limit);
+ }
+
public String roleSearchPath(final State matcherState) {
String author = author(matcherState);
String module = module(matcherState);
@@ -156,11 +172,15 @@ public String artifactPath(final String author, final String module, final Strin
public String download(String baseUrlRepo, final String author, final String module, final String version) {
- return String.format("%s/download/%s.tar.gz", baseUrlRepo, author + "-" + module + "-" + version);
+ return String.format("%s/api/v3/plugin/ansible/content/published/collections/artifacts/%s.tar.gz", baseUrlRepo, author + "-" + module + "-" + version);
}
public String collectionArtifactPath(final State matcherState) {
- return String.format("%s/%s", COLLECTION_PATH, artifactPath(matcherState));
+ String author = author(matcherState);
+ String module = module(matcherState);
+ String version = version(matcherState);
+ //return String.format("%s/%s", COLLECTION_PATH, artifactPath(matcherState));
+ return String.format("api/v3/plugin/ansible/content/published/collections/artifacts/%s-%s-%s.tar.gz", author, module, version);
}
public String parseHref(String baseUrlRepo, final String name, final String version) {
@@ -169,7 +189,8 @@ public String parseHref(String baseUrlRepo, final String name, final String vers
}
public String collectionArtifactPath(final String author, final String module, final String version) {
- return String.format("%s/%s", COLLECTION_PATH, artifactPath(author, module, version));
+ // return String.format("%s/%s", COLLECTION_PATH, artifactPath(author, module, version));
+ return String.format("api/v3/plugin/ansible/content/published/collections/artifacts/%s-%s-%s.tar.gz", author, module, version);
}
public String collectionNamePath(final String author, final String module) {
diff --git a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/rest/AnsibleGalaxyAttributes.java b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/rest/AnsibleGalaxyAttributes.java
new file mode 100644
index 0000000..f050a21
--- /dev/null
+++ b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/rest/AnsibleGalaxyAttributes.java
@@ -0,0 +1,45 @@
+/*
+ * Sonatype Nexus (TM) Open Source Version
+ * Copyright (c) 2020-present Sonatype, Inc.
+ * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
+ *
+ * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
+ * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
+ * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
+ * Eclipse Foundation. All other trademarks are the property of their respective owners.
+ */
+package org.sonatype.nexus.plugins.ansiblegalaxy.rest;
+
+import org.sonatype.nexus.plugins.ansiblegalaxy.ContentDisposition;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * REST API model of ansiblegalaxy attributes for repositories API
+ *
+ * @since 3.25
+ */
+public class AnsibleGalaxyAttributes
+{
+
+ public static final String CONTENT_DISPOSITION = "contentDisposition";
+
+ @ApiModelProperty(value = "Content Disposition",
+ allowableValues = "INLINE,ATTACHMENT", example = "ATTACHMENT")
+ private final ContentDisposition contentDisposition;
+
+ @JsonCreator
+ public AnsibleGalaxyAttributes(
+ @JsonProperty(CONTENT_DISPOSITION) final ContentDisposition contentDisposition)
+ {
+ this.contentDisposition = contentDisposition;
+ }
+
+ public ContentDisposition getContentDisposition() {
+ return contentDisposition;
+ }
+}
diff --git a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/rest/AnsibleGalaxyHostedRepositoriesApiResource.java b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/rest/AnsibleGalaxyHostedRepositoriesApiResource.java
new file mode 100644
index 0000000..b313738
--- /dev/null
+++ b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/rest/AnsibleGalaxyHostedRepositoriesApiResource.java
@@ -0,0 +1,75 @@
+/*
+ * Sonatype Nexus (TM) Open Source Version
+ * Copyright (c) 2020-present Sonatype, Inc.
+ * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
+ *
+ * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
+ * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
+ * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
+ * Eclipse Foundation. All other trademarks are the property of their respective owners.
+ */
+package org.sonatype.nexus.plugins.ansiblegalaxy.rest;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.Response;
+
+import org.sonatype.nexus.repository.rest.api.AbstractHostedRepositoriesApiResource;
+import org.sonatype.nexus.validation.Validate;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import org.apache.shiro.authz.annotation.RequiresAuthentication;
+
+import static org.sonatype.nexus.rest.ApiDocConstants.API_REPOSITORY_MANAGEMENT;
+import static org.sonatype.nexus.rest.ApiDocConstants.AUTHENTICATION_REQUIRED;
+import static org.sonatype.nexus.rest.ApiDocConstants.INSUFFICIENT_PERMISSIONS;
+import static org.sonatype.nexus.rest.ApiDocConstants.REPOSITORY_CREATED;
+import static org.sonatype.nexus.rest.ApiDocConstants.REPOSITORY_UPDATED;
+
+/**
+ * @since 3.24
+ */
+@Api(value = API_REPOSITORY_MANAGEMENT)
+public abstract class AnsibleGalaxyHostedRepositoriesApiResource
+ extends AbstractHostedRepositoriesApiResource
+{
+ @ApiOperation("Create ansiblegalaxy hosted repository")
+ @ApiResponses(value = {
+ @ApiResponse(code = 201, message = REPOSITORY_CREATED),
+ @ApiResponse(code = 401, message = AUTHENTICATION_REQUIRED),
+ @ApiResponse(code = 403, message = INSUFFICIENT_PERMISSIONS)
+ })
+ @POST
+ @RequiresAuthentication
+ @Validate
+ @Override
+ public Response createRepository(AnsibleGalaxyHostedRepositoryApiRequest request) {
+ return super.createRepository(request);
+ }
+
+ @ApiOperation("Update ansiblegalaxy hosted repository")
+ @ApiResponses(value = {
+ @ApiResponse(code = 204, message = REPOSITORY_UPDATED),
+ @ApiResponse(code = 401, message = AUTHENTICATION_REQUIRED),
+ @ApiResponse(code = 403, message = INSUFFICIENT_PERMISSIONS)
+ })
+ @PUT
+ @Path("/{repositoryName}")
+ @RequiresAuthentication
+ @Validate
+ @Override
+ public Response updateRepository(
+ final AnsibleGalaxyHostedRepositoryApiRequest request,
+ @ApiParam(value = "Name of the repository to update") @PathParam("repositoryName") final String repositoryName)
+ {
+ return super.updateRepository(request, repositoryName);
+ }
+}
\ No newline at end of file
diff --git a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/rest/AnsibleGalaxyHostedRepositoriesApiResourceV1.java b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/rest/AnsibleGalaxyHostedRepositoriesApiResourceV1.java
new file mode 100644
index 0000000..5b2dd02
--- /dev/null
+++ b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/rest/AnsibleGalaxyHostedRepositoriesApiResourceV1.java
@@ -0,0 +1,33 @@
+/*
+ * Sonatype Nexus (TM) Open Source Version
+ * Copyright (c) 2020-present Sonatype, Inc.
+ * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
+ *
+ * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
+ * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
+ * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
+ * Eclipse Foundation. All other trademarks are the property of their respective owners.
+ */
+package org.sonatype.nexus.plugins.ansiblegalaxy.rest;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+import javax.ws.rs.Path;
+
+import org.sonatype.nexus.repository.rest.api.RepositoriesApiResourceV1;
+
+import static org.sonatype.nexus.plugins.ansiblegalaxy.rest.AnsibleGalaxyHostedRepositoriesApiResourceV1.RESOURCE_URI;
+
+/**
+ * @since 3.26
+ */
+@Named
+@Singleton
+@Path(RESOURCE_URI)
+public class AnsibleGalaxyHostedRepositoriesApiResourceV1
+ extends AnsibleGalaxyHostedRepositoriesApiResource
+{
+ static final String RESOURCE_URI = RepositoriesApiResourceV1.RESOURCE_URI + "/ansiblegalaxy/hosted";
+}
diff --git a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/rest/AnsibleGalaxyHostedRepositoryApiRequest.java b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/rest/AnsibleGalaxyHostedRepositoryApiRequest.java
new file mode 100644
index 0000000..ddae95a
--- /dev/null
+++ b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/rest/AnsibleGalaxyHostedRepositoryApiRequest.java
@@ -0,0 +1,53 @@
+/*
+ * Sonatype Nexus (TM) Open Source Version
+ * Copyright (c) 2020-present Sonatype, Inc.
+ * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
+ *
+ * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
+ * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
+ * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
+ * Eclipse Foundation. All other trademarks are the property of their respective owners.
+ */
+package org.sonatype.nexus.plugins.ansiblegalaxy.rest;
+
+import org.sonatype.nexus.repository.rest.api.model.CleanupPolicyAttributes;
+import org.sonatype.nexus.repository.rest.api.model.ComponentAttributes;
+import org.sonatype.nexus.repository.rest.api.model.HostedRepositoryApiRequest;
+import org.sonatype.nexus.repository.rest.api.model.HostedStorageAttributes;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import org.sonatype.nexus.plugins.ansiblegalaxy.AnsibleGalaxyFormat;
+import org.sonatype.nexus.plugins.ansiblegalaxy.rest.AnsibleGalaxyAttributes;
+import static org.sonatype.nexus.plugins.ansiblegalaxy.ContentDisposition.ATTACHMENT;
+
+/**
+ * @since 3.24
+ */
+@JsonIgnoreProperties({"format", "type"})
+public class AnsibleGalaxyHostedRepositoryApiRequest
+ extends HostedRepositoryApiRequest
+{
+ private final AnsibleGalaxyAttributes ansiblegalaxy;
+
+ @JsonCreator
+ public AnsibleGalaxyHostedRepositoryApiRequest(
+ @JsonProperty("name") final String name,
+ @JsonProperty("online") final Boolean online,
+ @JsonProperty("storage") final HostedStorageAttributes storage,
+ @JsonProperty("cleanup") final CleanupPolicyAttributes cleanup,
+ @JsonProperty("ansiblegalaxy") final AnsibleGalaxyAttributes ansiblegalaxy,
+ @JsonProperty("component") final ComponentAttributes componentAttributes)
+ {
+ super(name, AnsibleGalaxyFormat.NAME, online, storage, cleanup, componentAttributes);
+ this.ansiblegalaxy = ansiblegalaxy != null ? ansiblegalaxy : new AnsibleGalaxyAttributes(ATTACHMENT);
+ }
+
+ public AnsibleGalaxyAttributes getAnsibleGalaxy() {
+ return ansiblegalaxy;
+ }
+}
\ No newline at end of file
diff --git a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/rest/AnsibleGalaxyHostedRepositoryApiRequestToConfigurationConverter.java b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/rest/AnsibleGalaxyHostedRepositoryApiRequestToConfigurationConverter.java
new file mode 100644
index 0000000..42271e5
--- /dev/null
+++ b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/rest/AnsibleGalaxyHostedRepositoryApiRequestToConfigurationConverter.java
@@ -0,0 +1,35 @@
+/*
+ * Sonatype Nexus (TM) Open Source Version
+ * Copyright (c) 2020-present Sonatype, Inc.
+ * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
+ *
+ * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
+ * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
+ * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
+ * Eclipse Foundation. All other trademarks are the property of their respective owners.
+ */
+package org.sonatype.nexus.plugins.ansiblegalaxy.rest;
+
+import javax.inject.Named;
+
+import org.sonatype.nexus.repository.config.Configuration;
+import org.sonatype.nexus.repository.rest.api.HostedRepositoryApiRequestToConfigurationConverter;
+
+import static org.sonatype.nexus.plugins.ansiblegalaxy.rest.AnsibleGalaxyAttributes.CONTENT_DISPOSITION;
+
+/**
+ * @since 3.25
+ */
+@Named
+public class AnsibleGalaxyHostedRepositoryApiRequestToConfigurationConverter
+ extends HostedRepositoryApiRequestToConfigurationConverter
+{
+ @Override
+ public Configuration convert(final AnsibleGalaxyHostedRepositoryApiRequest request) {
+ Configuration configuration = super.convert(request);
+ configuration.attributes("ansiblegalaxy").set(CONTENT_DISPOSITION, request.getAnsibleGalaxy().getContentDisposition().name());
+ return configuration;
+ }
+}
\ No newline at end of file
diff --git a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/rest/AnsibleGalaxyProxyRepositoriesApiResource.java b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/rest/AnsibleGalaxyProxyRepositoriesApiResource.java
new file mode 100644
index 0000000..8e80d7f
--- /dev/null
+++ b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/rest/AnsibleGalaxyProxyRepositoriesApiResource.java
@@ -0,0 +1,75 @@
+/*
+ * Sonatype Nexus (TM) Open Source Version
+ * Copyright (c) 2020-present Sonatype, Inc.
+ * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
+ *
+ * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
+ * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
+ * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
+ * Eclipse Foundation. All other trademarks are the property of their respective owners.
+ */
+package org.sonatype.nexus.plugins.ansiblegalaxy.rest;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.Response;
+
+import org.sonatype.nexus.repository.rest.api.AbstractProxyRepositoriesApiResource;
+import org.sonatype.nexus.validation.Validate;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import org.apache.shiro.authz.annotation.RequiresAuthentication;
+
+import static org.sonatype.nexus.rest.ApiDocConstants.API_REPOSITORY_MANAGEMENT;
+import static org.sonatype.nexus.rest.ApiDocConstants.AUTHENTICATION_REQUIRED;
+import static org.sonatype.nexus.rest.ApiDocConstants.INSUFFICIENT_PERMISSIONS;
+import static org.sonatype.nexus.rest.ApiDocConstants.REPOSITORY_CREATED;
+import static org.sonatype.nexus.rest.ApiDocConstants.REPOSITORY_UPDATED;
+
+/**
+ * @since 3.24
+ */
+@Api(value = API_REPOSITORY_MANAGEMENT)
+public abstract class AnsibleGalaxyProxyRepositoriesApiResource
+ extends AbstractProxyRepositoriesApiResource
+{
+ @ApiOperation("Create ansiblegalaxy proxy repository")
+ @ApiResponses(value = {
+ @ApiResponse(code = 201, message = REPOSITORY_CREATED),
+ @ApiResponse(code = 401, message = AUTHENTICATION_REQUIRED),
+ @ApiResponse(code = 403, message = INSUFFICIENT_PERMISSIONS)
+ })
+ @POST
+ @RequiresAuthentication
+ @Validate
+ @Override
+ public Response createRepository(final AnsibleGalaxyProxyRepositoryApiRequest request) {
+ return super.createRepository(request);
+ }
+
+ @ApiOperation("Update ansiblegalaxy proxy repository")
+ @ApiResponses(value = {
+ @ApiResponse(code = 204, message = REPOSITORY_UPDATED),
+ @ApiResponse(code = 401, message = AUTHENTICATION_REQUIRED),
+ @ApiResponse(code = 403, message = INSUFFICIENT_PERMISSIONS)
+ })
+ @PUT
+ @Path("/{repositoryName}")
+ @RequiresAuthentication
+ @Validate
+ @Override
+ public Response updateRepository(
+ final AnsibleGalaxyProxyRepositoryApiRequest request,
+ @ApiParam(value = "Name of the repository to update") @PathParam("repositoryName") final String repositoryName)
+ {
+ return super.updateRepository(request, repositoryName);
+ }
+}
\ No newline at end of file
diff --git a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/rest/AnsibleGalaxyProxyRepositoriesApiResourceV1.java b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/rest/AnsibleGalaxyProxyRepositoriesApiResourceV1.java
new file mode 100644
index 0000000..34bb995
--- /dev/null
+++ b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/rest/AnsibleGalaxyProxyRepositoriesApiResourceV1.java
@@ -0,0 +1,33 @@
+/*
+ * Sonatype Nexus (TM) Open Source Version
+ * Copyright (c) 2020-present Sonatype, Inc.
+ * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
+ *
+ * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
+ * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
+ * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
+ * Eclipse Foundation. All other trademarks are the property of their respective owners.
+ */
+package org.sonatype.nexus.plugins.ansiblegalaxy.rest;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+import javax.ws.rs.Path;
+
+import org.sonatype.nexus.repository.rest.api.RepositoriesApiResourceV1;
+
+import static org.sonatype.nexus.plugins.ansiblegalaxy.rest.AnsibleGalaxyProxyRepositoriesApiResourceV1.RESOURCE_URI;
+
+/**
+ * @since 3.26
+ */
+@Named
+@Singleton
+@Path(RESOURCE_URI)
+public class AnsibleGalaxyProxyRepositoriesApiResourceV1
+ extends AnsibleGalaxyProxyRepositoriesApiResource
+{
+ static final String RESOURCE_URI = RepositoriesApiResourceV1.RESOURCE_URI + "/ansiblegalaxy/proxy";
+}
diff --git a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/rest/AnsibleGalaxyProxyRepositoryApiRequest.java b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/rest/AnsibleGalaxyProxyRepositoryApiRequest.java
new file mode 100644
index 0000000..2ccd158
--- /dev/null
+++ b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/rest/AnsibleGalaxyProxyRepositoryApiRequest.java
@@ -0,0 +1,64 @@
+/*
+ * Sonatype Nexus (TM) Open Source Version
+ * Copyright (c) 2020-present Sonatype, Inc.
+ * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
+ *
+ * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
+ * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
+ * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
+ * Eclipse Foundation. All other trademarks are the property of their respective owners.
+ */
+package org.sonatype.nexus.plugins.ansiblegalaxy.rest;
+
+import org.sonatype.nexus.plugins.ansiblegalaxy.AnsibleGalaxyFormat;
+import org.sonatype.nexus.plugins.ansiblegalaxy.rest.AnsibleGalaxyAttributes;
+import org.sonatype.nexus.repository.rest.api.model.CleanupPolicyAttributes;
+import org.sonatype.nexus.repository.rest.api.model.HttpClientAttributes;
+import org.sonatype.nexus.repository.rest.api.model.NegativeCacheAttributes;
+import org.sonatype.nexus.repository.rest.api.model.ProxyAttributes;
+import org.sonatype.nexus.repository.rest.api.model.ProxyRepositoryApiRequest;
+import org.sonatype.nexus.repository.rest.api.model.ReplicationAttributes;
+import org.sonatype.nexus.repository.rest.api.model.StorageAttributes;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import static org.sonatype.nexus.plugins.ansiblegalaxy.ContentDisposition.ATTACHMENT;
+
+/**
+ * @since 3.24
+ */
+@JsonIgnoreProperties({"format", "type"})
+public class AnsibleGalaxyProxyRepositoryApiRequest
+ extends ProxyRepositoryApiRequest
+{
+ private final AnsibleGalaxyAttributes ansiblegalaxy;
+
+ @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
+ @SuppressWarnings("squid:S00107") // suppress constructor parameter count
+ public AnsibleGalaxyProxyRepositoryApiRequest(
+ @JsonProperty("name") final String name,
+ @JsonProperty("online") final Boolean online,
+ @JsonProperty("storage") final StorageAttributes storage,
+ @JsonProperty("cleanup") final CleanupPolicyAttributes cleanup,
+ @JsonProperty("proxy") final ProxyAttributes proxy,
+ @JsonProperty("negativeCache") final NegativeCacheAttributes negativeCache,
+ @JsonProperty("httpClient") final HttpClientAttributes httpClient,
+ @JsonProperty("routingRule") final String routingRule,
+ @JsonProperty("ansiblegalaxy") final AnsibleGalaxyAttributes ansiblegalaxy,
+ @JsonProperty("replication") @JsonInclude(value= Include.NON_EMPTY, content=Include.NON_NULL)
+ final ReplicationAttributes replication)
+ {
+ super(name, AnsibleGalaxyFormat.NAME, online, storage, cleanup, proxy, negativeCache, httpClient, routingRule, replication);
+ this.ansiblegalaxy = ansiblegalaxy != null ? ansiblegalaxy : new AnsibleGalaxyAttributes(ATTACHMENT);
+ }
+
+ public AnsibleGalaxyAttributes getAnsibleGalaxy() {
+ return ansiblegalaxy;
+ }
+}
\ No newline at end of file
diff --git a/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/rest/AnsibleGalaxyProxyRepositoryApiRequestToConfigurationConverter.java b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/rest/AnsibleGalaxyProxyRepositoryApiRequestToConfigurationConverter.java
new file mode 100644
index 0000000..2dd3aa9
--- /dev/null
+++ b/nexus-repository-ansiblegalaxy/src/main/java/org/sonatype/nexus/plugins/ansiblegalaxy/rest/AnsibleGalaxyProxyRepositoryApiRequestToConfigurationConverter.java
@@ -0,0 +1,42 @@
+/*
+ * Sonatype Nexus (TM) Open Source Version
+ * Copyright (c) 2020-present Sonatype, Inc.
+ * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
+ *
+ * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
+ * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
+ * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
+ * Eclipse Foundation. All other trademarks are the property of their respective owners.
+ */
+package org.sonatype.nexus.plugins.ansiblegalaxy.rest;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.sonatype.nexus.repository.config.Configuration;
+import org.sonatype.nexus.repository.rest.api.ProxyRepositoryApiRequestToConfigurationConverter;
+import org.sonatype.nexus.repository.routing.RoutingRuleStore;
+
+import static org.sonatype.nexus.plugins.ansiblegalaxy.rest.AnsibleGalaxyAttributes.CONTENT_DISPOSITION;
+
+/**
+ * @since 3.25
+ */
+@Named
+public class AnsibleGalaxyProxyRepositoryApiRequestToConfigurationConverter
+ extends ProxyRepositoryApiRequestToConfigurationConverter
+{
+ @Inject
+ public AnsibleGalaxyProxyRepositoryApiRequestToConfigurationConverter(final RoutingRuleStore routingRuleStore) {
+ super(routingRuleStore);
+ }
+
+ @Override
+ public Configuration convert(final AnsibleGalaxyProxyRepositoryApiRequest request) {
+ Configuration configuration = super.convert(request);
+ configuration.attributes("ansiblegalaxy").set(CONTENT_DISPOSITION, request.getAnsibleGalaxy().getContentDisposition().name());
+ return configuration;
+ }
+}
\ No newline at end of file
diff --git a/nexus-repository-ansiblegalaxy/src/test/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/AnsibleGalaxyRecipeSupportTest.java b/nexus-repository-ansiblegalaxy/src/test/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/AnsibleGalaxyRecipeSupportTest.java
index 8102960..9c0b553 100644
--- a/nexus-repository-ansiblegalaxy/src/test/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/AnsibleGalaxyRecipeSupportTest.java
+++ b/nexus-repository-ansiblegalaxy/src/test/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/AnsibleGalaxyRecipeSupportTest.java
@@ -60,7 +60,7 @@ public void setUp() {
@Test
public void testCollectionArtifactTar() {
- when(request.getPath()).thenReturn("/download/azure-azcollection-1.3.1.tar.gz");
+ when(request.getPath()).thenReturn("/api/v3/plugin/ansible/content/published/collections/artifacts/azure-azcollection-1.3.1.tar.gz");
Matcher matcher = collectionArtifactMatcher();
boolean matches = matcher.matches(context);
assertTrue(matches);
@@ -76,7 +76,7 @@ public void testCollectionArtifactTar() {
@Test
public void testCollectionBranchArtifactTar() {
- when(request.getPath()).thenReturn("/download/azure-azcollection-master.tar.gz");
+ when(request.getPath()).thenReturn("/api/v3/plugin/ansible/content/published/collections/artifacts/azure-azcollection-master.tar.gz");
Matcher matcher = collectionArtifactMatcher();
boolean matches = matcher.matches(context);
assertTrue(matches);
diff --git a/nexus-repository-ansiblegalaxy/src/test/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/util/AnsibleGalaxyPathUtilsTest.java b/nexus-repository-ansiblegalaxy/src/test/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/util/AnsibleGalaxyPathUtilsTest.java
index c99bdf2..5716892 100644
--- a/nexus-repository-ansiblegalaxy/src/test/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/util/AnsibleGalaxyPathUtilsTest.java
+++ b/nexus-repository-ansiblegalaxy/src/test/java/org/sonatype/nexus/plugins/ansiblegalaxy/internal/util/AnsibleGalaxyPathUtilsTest.java
@@ -126,7 +126,7 @@ public void roleMetadataPagedPath() {
public void collectionArtifactPath() {
String result = underTest.collectionArtifactPath(state);
- assertThat(result, is(equalTo("collection/azure/azcollection/1.2.0/azure-azcollection-1.2.0.tar.gz")));
+ assertThat(result, is(equalTo("api/v3/plugin/ansible/content/published/collections/artifacts/azure-azcollection-1.2.0.tar.gz")));
}
@Test
diff --git a/pom.xml b/pom.xml
index f2bd637..204d598 100644
--- a/pom.xml
+++ b/pom.xml
@@ -24,7 +24,7 @@
nexus-repository-ansiblegalaxy-parent
- 0.3.0
+ 0.3.2
pom
2020