@Test public void importResources() { final DataManager dataManager = mock(DataManager.class); final SecurityContext securityContext = newMockSecurityContext(); final InputStream givenDataStream = new ByteArrayInputStream(new byte[0]); final IntegrationSupportHandler supportHandler = mock(IntegrationSupportHandler.class); final Connection testConnection = new Connection.Builder() .id("connection-id") .connectorId("connector-id") .name("test-connection").build(); final Integration integration = new Integration.Builder() .id("integration-id") .addConnection(testConnection) .build(); Map<String, List<WithResourceId>> resultMap = new HashMap<>(); resultMap.put("integration-id", Collections.singletonList(integration)); resultMap.put("connection-id", Collections.singletonList(testConnection)); when(supportHandler.importIntegration(securityContext, givenDataStream)) .thenReturn(resultMap); final Environment env = newEnvironment("env"); when(dataManager.fetchByPropertyValue(Environment.class, "name", "env")).thenReturn(Optional.of(env)); when(dataManager.fetch(Connector.class, "connector-id")).thenReturn( new Connector.Builder() .putProperty("prop", new ConfigurationProperty.Builder().build()) .build()); when(dataManager.fetchAll(eq(Integration.class), any())).then((Answer<ListResult<Integration>>) invocation -> { final Object[] arguments = invocation.getArguments(); ListResult<Integration> result = new ListResult.Builder<Integration>().addItem(integration).build(); for (int i = 1; i < arguments.length; i++) { @SuppressWarnings("unchecked") Function<ListResult<Integration>, ListResult<Integration>> operator = (Function<ListResult<Integration>, ListResult<Integration>>) arguments[i]; result = operator.apply(result); } return result; }); final EnvironmentHandler environmentHandler = new EnvironmentHandler(dataManager); final IntegrationDeploymentHandler deploymentHandler = mock(IntegrationDeploymentHandler.class); final EncryptionComponent encryptionComponent = mock(EncryptionComponent.class); when(encryptionComponent.encryptPropertyValues(any(), any())).thenReturn(Collections.singletonMap("prop", "value")); IntegrationHandler integrationHandler = mock(IntegrationHandler.class); when(integrationHandler.getOverview(any())).thenReturn( new IntegrationOverview.Builder().createFrom(integration) .connections(Collections.singletonList(testConnection.builder().putConfiguredProperty("prop", "value").build())) .build()); final PublicApiHandler handler = new PublicApiHandler(dataManager, encryptionComponent, deploymentHandler, null, null, environmentHandler, supportHandler, integrationHandler); final PublicApiHandler.ImportFormDataInput formInput = new PublicApiHandler.ImportFormDataInput(); formInput.setData(givenDataStream); formInput.setProperties(new ByteArrayInputStream("test-connection.prop=value".getBytes(StandardCharsets.UTF_8))); formInput.setRefreshIntegrations(Boolean.TRUE); formInput.setEnvironment("env"); formInput.setDeploy(Boolean.TRUE); final ContinuousDeliveryImportResults importResults = handler.importResources(securityContext, formInput); verify(deploymentHandler).update(securityContext, "integration-id"); assertThat(importResults.getLastImportedAt()).isNotNull(); assertThat(importResults.getResults().size()).isEqualTo(2); final Integration importedIntegration = (Integration) importResults.getResults().get(0); assertThat(importedIntegration.getConnections().get(0).getConfiguredProperties().get("prop")).isEqualTo("value"); }
@POST @Path("integrations") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.MULTIPART_FORM_DATA) @SuppressFBWarnings("RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE") public ContinuousDeliveryImportResults importResources(@Context SecurityContext sec, @NotNull @MultipartForm @Parameter(required = true) ImportFormDataInput formInput) { if (formInput == null) { throw new ClientErrorException("Multipart request is empty", Response.Status.BAD_REQUEST); } final String environment = formInput.getEnvironment(); EnvironmentHandler.validateEnvironment("environment", environment); final boolean deploy = Boolean.TRUE.equals(formInput.getDeploy()); final Environment env = environmentHandler.getEnvironment(environment); try (InputStream importFile = formInput.getData(); InputStream properties = formInput.getProperties()) { if (importFile == null) { throw new ClientErrorException("Missing file 'data' in multipart request", Response.Status.BAD_REQUEST); } @SuppressWarnings("JdkObsolete") final Date lastImportedAt = new Date(); final Map<String, List<WithResourceId>> resources = handler.importIntegration(sec, importFile); final List<WithResourceId> results = new ArrayList<>(); resources.values().forEach(results::addAll); final List<Integration> integrations = getResourcesOfType(results, Integration.class); environmentHandler.updateCDEnvironments(integrations, env.getId().get(), lastImportedAt, b -> b.lastImportedAt(lastImportedAt)); if (properties != null) { Map<String, Map<String, String>> params = getParams(properties); final List<Connection> connections = getResourcesOfType(results, Connection.class); connections.forEach(c -> { final Map<String, String> values = params.get(c.getName()); if (values != null) { updateConnection(c, values, formInput.getRefreshIntegrations(), lastImportedAt, results); } }); } if (deploy) { integrations.forEach(i -> publishIntegration(sec, i)); } return new ContinuousDeliveryImportResults.Builder() .lastImportedAt(lastImportedAt) .results(results) .build(); } catch (IOException e) { throw new ClientErrorException(String.format("Error processing multipart request: %s", e.getMessage()), Response.Status.BAD_REQUEST, e); } }
PublicApiHandler { @POST @Path("integrations") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.MULTIPART_FORM_DATA) @SuppressFBWarnings("RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE") public ContinuousDeliveryImportResults importResources(@Context SecurityContext sec, @NotNull @MultipartForm @Parameter(required = true) ImportFormDataInput formInput) { if (formInput == null) { throw new ClientErrorException("Multipart request is empty", Response.Status.BAD_REQUEST); } final String environment = formInput.getEnvironment(); EnvironmentHandler.validateEnvironment("environment", environment); final boolean deploy = Boolean.TRUE.equals(formInput.getDeploy()); final Environment env = environmentHandler.getEnvironment(environment); try (InputStream importFile = formInput.getData(); InputStream properties = formInput.getProperties()) { if (importFile == null) { throw new ClientErrorException("Missing file 'data' in multipart request", Response.Status.BAD_REQUEST); } @SuppressWarnings("JdkObsolete") final Date lastImportedAt = new Date(); final Map<String, List<WithResourceId>> resources = handler.importIntegration(sec, importFile); final List<WithResourceId> results = new ArrayList<>(); resources.values().forEach(results::addAll); final List<Integration> integrations = getResourcesOfType(results, Integration.class); environmentHandler.updateCDEnvironments(integrations, env.getId().get(), lastImportedAt, b -> b.lastImportedAt(lastImportedAt)); if (properties != null) { Map<String, Map<String, String>> params = getParams(properties); final List<Connection> connections = getResourcesOfType(results, Connection.class); connections.forEach(c -> { final Map<String, String> values = params.get(c.getName()); if (values != null) { updateConnection(c, values, formInput.getRefreshIntegrations(), lastImportedAt, results); } }); } if (deploy) { integrations.forEach(i -> publishIntegration(sec, i)); } return new ContinuousDeliveryImportResults.Builder() .lastImportedAt(lastImportedAt) .results(results) .build(); } catch (IOException e) { throw new ClientErrorException(String.format("Error processing multipart request: %s", e.getMessage()), Response.Status.BAD_REQUEST, e); } } }
PublicApiHandler { @POST @Path("integrations") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.MULTIPART_FORM_DATA) @SuppressFBWarnings("RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE") public ContinuousDeliveryImportResults importResources(@Context SecurityContext sec, @NotNull @MultipartForm @Parameter(required = true) ImportFormDataInput formInput) { if (formInput == null) { throw new ClientErrorException("Multipart request is empty", Response.Status.BAD_REQUEST); } final String environment = formInput.getEnvironment(); EnvironmentHandler.validateEnvironment("environment", environment); final boolean deploy = Boolean.TRUE.equals(formInput.getDeploy()); final Environment env = environmentHandler.getEnvironment(environment); try (InputStream importFile = formInput.getData(); InputStream properties = formInput.getProperties()) { if (importFile == null) { throw new ClientErrorException("Missing file 'data' in multipart request", Response.Status.BAD_REQUEST); } @SuppressWarnings("JdkObsolete") final Date lastImportedAt = new Date(); final Map<String, List<WithResourceId>> resources = handler.importIntegration(sec, importFile); final List<WithResourceId> results = new ArrayList<>(); resources.values().forEach(results::addAll); final List<Integration> integrations = getResourcesOfType(results, Integration.class); environmentHandler.updateCDEnvironments(integrations, env.getId().get(), lastImportedAt, b -> b.lastImportedAt(lastImportedAt)); if (properties != null) { Map<String, Map<String, String>> params = getParams(properties); final List<Connection> connections = getResourcesOfType(results, Connection.class); connections.forEach(c -> { final Map<String, String> values = params.get(c.getName()); if (values != null) { updateConnection(c, values, formInput.getRefreshIntegrations(), lastImportedAt, results); } }); } if (deploy) { integrations.forEach(i -> publishIntegration(sec, i)); } return new ContinuousDeliveryImportResults.Builder() .lastImportedAt(lastImportedAt) .results(results) .build(); } catch (IOException e) { throw new ClientErrorException(String.format("Error processing multipart request: %s", e.getMessage()), Response.Status.BAD_REQUEST, e); } } protected  PublicApiHandler(DataManager dataMgr, EncryptionComponent encryptionComponent,
        IntegrationDeploymentHandler deploymentHandler, ConnectionHandler connectionHandler,
        MonitoringProvider monitoringProvider, EnvironmentHandler environmentHandler,
        IntegrationSupportHandler handler, IntegrationHandler integrationHandler); }
PublicApiHandler { @POST @Path("integrations") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.MULTIPART_FORM_DATA) @SuppressFBWarnings("RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE") public ContinuousDeliveryImportResults importResources(@Context SecurityContext sec, @NotNull @MultipartForm @Parameter(required = true) ImportFormDataInput formInput) { if (formInput == null) { throw new ClientErrorException("Multipart request is empty", Response.Status.BAD_REQUEST); } final String environment = formInput.getEnvironment(); EnvironmentHandler.validateEnvironment("environment", environment); final boolean deploy = Boolean.TRUE.equals(formInput.getDeploy()); final Environment env = environmentHandler.getEnvironment(environment); try (InputStream importFile = formInput.getData(); InputStream properties = formInput.getProperties()) { if (importFile == null) { throw new ClientErrorException("Missing file 'data' in multipart request", Response.Status.BAD_REQUEST); } @SuppressWarnings("JdkObsolete") final Date lastImportedAt = new Date(); final Map<String, List<WithResourceId>> resources = handler.importIntegration(sec, importFile); final List<WithResourceId> results = new ArrayList<>(); resources.values().forEach(results::addAll); final List<Integration> integrations = getResourcesOfType(results, Integration.class); environmentHandler.updateCDEnvironments(integrations, env.getId().get(), lastImportedAt, b -> b.lastImportedAt(lastImportedAt)); if (properties != null) { Map<String, Map<String, String>> params = getParams(properties); final List<Connection> connections = getResourcesOfType(results, Connection.class); connections.forEach(c -> { final Map<String, String> values = params.get(c.getName()); if (values != null) { updateConnection(c, values, formInput.getRefreshIntegrations(), lastImportedAt, results); } }); } if (deploy) { integrations.forEach(i -> publishIntegration(sec, i)); } return new ContinuousDeliveryImportResults.Builder() .lastImportedAt(lastImportedAt) .results(results) .build(); } catch (IOException e) { throw new ClientErrorException(String.format("Error processing multipart request: %s", e.getMessage()), Response.Status.BAD_REQUEST, e); } } protected  PublicApiHandler(DataManager dataMgr, EncryptionComponent encryptionComponent,
        IntegrationDeploymentHandler deploymentHandler, ConnectionHandler connectionHandler,
        MonitoringProvider monitoringProvider, EnvironmentHandler environmentHandler,
        IntegrationSupportHandler handler, IntegrationHandler integrationHandler); List<String> getReleaseEnvironments(); @GET @Path("environments") @Produces(MediaType.APPLICATION_JSON) Response getReleaseEnvironments(@QueryParam("withUses") @Parameter boolean withUses); @POST @Path("environments/{env}") void addNewEnvironment(@NotNull @PathParam("env") @Parameter(required = true) String environment); @DELETE @Path("environments/{env}") void deleteEnvironment(@NotNull @PathParam("env") @Parameter(required = true) String environment); @PUT @Path("environments/{env}") @Consumes(MediaType.APPLICATION_JSON) void renameEnvironment(@NotNull @PathParam("env") @Parameter(required = true) String environment,
        @NotNull @Parameter(required = true) String newEnvironment); @GET @Path("integrations/{id}/tags") @Produces(MediaType.APPLICATION_JSON) Map<String, ContinuousDeliveryEnvironment> getReleaseTags(@NotNull @PathParam("id") @Parameter(required = true) String integrationId); @DELETE @Path("integrations/{id}/tags/{env}") void deleteReleaseTag(@NotNull @PathParam("id") @Parameter(required = true) String integrationId,
        @NotNull @PathParam("env") @Parameter(required = true) String environment); @PUT @Path("integrations/{id}/tags") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) Map<String, ContinuousDeliveryEnvironment> putTagsForRelease(@NotNull @PathParam("id") @Parameter(required = true) String integrationId,
        @NotNull @Parameter(required = true) List<String> environments); @PATCH @Path("integrations/{id}/tags") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) Map<String, ContinuousDeliveryEnvironment> patchTagsForRelease(@NotNull @PathParam("id") @Parameter(required = true) String integrationId,
        @NotNull @Parameter(required = true) List<String> environments); @GET @Path("integrations/{env}/export.zip") @Produces(MediaType.APPLICATION_OCTET_STREAM) @SuppressWarnings("JdkObsolete") Response exportResources(@NotNull @PathParam("env") @Parameter(required = true) String environment,
                                    @QueryParam("all") @Parameter boolean exportAll,
                                    @QueryParam("ignoreTimestamp") @Parameter boolean ignoreTimestamp); @POST @Path("integrations") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.MULTIPART_FORM_DATA) @SuppressFBWarnings("RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE") // https://github.com/spotbugs/spotbugs/issues/259 ContinuousDeliveryImportResults importResources(@Context SecurityContext sec,
        @NotNull @MultipartForm @Parameter(required = true) ImportFormDataInput formInput); @POST @Path("connections/{id}/properties") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) ConnectionOverview configureConnection(@Context SecurityContext sec,
                                                  @NotNull @PathParam("id") @Parameter(required = true) String connectionId,
                                                  @NotNull @QueryParam("refreshIntegrations") @Parameter Boolean refeshIntegrations,
                                                  @NotNull @Parameter(required = true) Map<String, String> properties); @GET @Path("integrations/{id}/state") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) IntegrationState getIntegrationState(@Context SecurityContext sec, @NotNull @PathParam("id") @Parameter(required = true) String integrationId); @POST @Path("integrations/{id}/deployments") @Produces(MediaType.APPLICATION_JSON) IntegrationDeployment publishIntegration(@Context final SecurityContext sec,
        @NotNull @PathParam("id") @Parameter(required = true) final String integrationId); @PUT @Path("integrations/{id}/deployments/stop") @Produces(MediaType.APPLICATION_JSON) void stopIntegration(@Context final SecurityContext sec, @NotNull @PathParam("id") @Parameter(required = true) final String integrationId); }
PublicApiHandler { @POST @Path("integrations") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.MULTIPART_FORM_DATA) @SuppressFBWarnings("RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE") public ContinuousDeliveryImportResults importResources(@Context SecurityContext sec, @NotNull @MultipartForm @Parameter(required = true) ImportFormDataInput formInput) { if (formInput == null) { throw new ClientErrorException("Multipart request is empty", Response.Status.BAD_REQUEST); } final String environment = formInput.getEnvironment(); EnvironmentHandler.validateEnvironment("environment", environment); final boolean deploy = Boolean.TRUE.equals(formInput.getDeploy()); final Environment env = environmentHandler.getEnvironment(environment); try (InputStream importFile = formInput.getData(); InputStream properties = formInput.getProperties()) { if (importFile == null) { throw new ClientErrorException("Missing file 'data' in multipart request", Response.Status.BAD_REQUEST); } @SuppressWarnings("JdkObsolete") final Date lastImportedAt = new Date(); final Map<String, List<WithResourceId>> resources = handler.importIntegration(sec, importFile); final List<WithResourceId> results = new ArrayList<>(); resources.values().forEach(results::addAll); final List<Integration> integrations = getResourcesOfType(results, Integration.class); environmentHandler.updateCDEnvironments(integrations, env.getId().get(), lastImportedAt, b -> b.lastImportedAt(lastImportedAt)); if (properties != null) { Map<String, Map<String, String>> params = getParams(properties); final List<Connection> connections = getResourcesOfType(results, Connection.class); connections.forEach(c -> { final Map<String, String> values = params.get(c.getName()); if (values != null) { updateConnection(c, values, formInput.getRefreshIntegrations(), lastImportedAt, results); } }); } if (deploy) { integrations.forEach(i -> publishIntegration(sec, i)); } return new ContinuousDeliveryImportResults.Builder() .lastImportedAt(lastImportedAt) .results(results) .build(); } catch (IOException e) { throw new ClientErrorException(String.format("Error processing multipart request: %s", e.getMessage()), Response.Status.BAD_REQUEST, e); } } protected  PublicApiHandler(DataManager dataMgr, EncryptionComponent encryptionComponent,
        IntegrationDeploymentHandler deploymentHandler, ConnectionHandler connectionHandler,
        MonitoringProvider monitoringProvider, EnvironmentHandler environmentHandler,
        IntegrationSupportHandler handler, IntegrationHandler integrationHandler); List<String> getReleaseEnvironments(); @GET @Path("environments") @Produces(MediaType.APPLICATION_JSON) Response getReleaseEnvironments(@QueryParam("withUses") @Parameter boolean withUses); @POST @Path("environments/{env}") void addNewEnvironment(@NotNull @PathParam("env") @Parameter(required = true) String environment); @DELETE @Path("environments/{env}") void deleteEnvironment(@NotNull @PathParam("env") @Parameter(required = true) String environment); @PUT @Path("environments/{env}") @Consumes(MediaType.APPLICATION_JSON) void renameEnvironment(@NotNull @PathParam("env") @Parameter(required = true) String environment,
        @NotNull @Parameter(required = true) String newEnvironment); @GET @Path("integrations/{id}/tags") @Produces(MediaType.APPLICATION_JSON) Map<String, ContinuousDeliveryEnvironment> getReleaseTags(@NotNull @PathParam("id") @Parameter(required = true) String integrationId); @DELETE @Path("integrations/{id}/tags/{env}") void deleteReleaseTag(@NotNull @PathParam("id") @Parameter(required = true) String integrationId,
        @NotNull @PathParam("env") @Parameter(required = true) String environment); @PUT @Path("integrations/{id}/tags") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) Map<String, ContinuousDeliveryEnvironment> putTagsForRelease(@NotNull @PathParam("id") @Parameter(required = true) String integrationId,
        @NotNull @Parameter(required = true) List<String> environments); @PATCH @Path("integrations/{id}/tags") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) Map<String, ContinuousDeliveryEnvironment> patchTagsForRelease(@NotNull @PathParam("id") @Parameter(required = true) String integrationId,
        @NotNull @Parameter(required = true) List<String> environments); @GET @Path("integrations/{env}/export.zip") @Produces(MediaType.APPLICATION_OCTET_STREAM) @SuppressWarnings("JdkObsolete") Response exportResources(@NotNull @PathParam("env") @Parameter(required = true) String environment,
                                    @QueryParam("all") @Parameter boolean exportAll,
                                    @QueryParam("ignoreTimestamp") @Parameter boolean ignoreTimestamp); @POST @Path("integrations") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.MULTIPART_FORM_DATA) @SuppressFBWarnings("RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE") // https://github.com/spotbugs/spotbugs/issues/259 ContinuousDeliveryImportResults importResources(@Context SecurityContext sec,
        @NotNull @MultipartForm @Parameter(required = true) ImportFormDataInput formInput); @POST @Path("connections/{id}/properties") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) ConnectionOverview configureConnection(@Context SecurityContext sec,
                                                  @NotNull @PathParam("id") @Parameter(required = true) String connectionId,
                                                  @NotNull @QueryParam("refreshIntegrations") @Parameter Boolean refeshIntegrations,
                                                  @NotNull @Parameter(required = true) Map<String, String> properties); @GET @Path("integrations/{id}/state") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) IntegrationState getIntegrationState(@Context SecurityContext sec, @NotNull @PathParam("id") @Parameter(required = true) String integrationId); @POST @Path("integrations/{id}/deployments") @Produces(MediaType.APPLICATION_JSON) IntegrationDeployment publishIntegration(@Context final SecurityContext sec,
        @NotNull @PathParam("id") @Parameter(required = true) final String integrationId); @PUT @Path("integrations/{id}/deployments/stop") @Produces(MediaType.APPLICATION_JSON) void stopIntegration(@Context final SecurityContext sec, @NotNull @PathParam("id") @Parameter(required = true) final String integrationId);  }