ScmRepositoryPlugin extends AbstractEC2InstancePlugin { @Override protected void process(final EC2InstanceContext context) { final Optional<Map<String, String>> optionalScmSource = context.getScmSource(); if (!optionalScmSource.isPresent()) { log.warn("Missing Scm source for {}. Skip ScmRepositoryPlugin.", context); return; } final Map<String, String> scmSource = optionalScmSource.get(); final String scmSourceUrl = scmSource.get(URL); if (isBlank(scmSourceUrl)) { violationSink.put( context.violation() .withPluginFullyQualifiedClassName(ScmRepositoryPlugin.class) .withType(SCM_URL_IS_MISSING_IN_SCM_SOURCE_JSON) .withMetaInfo(ImmutableMap.of( "application_id", context.getApplicationId().orElse(""), "deployment_artifact", context.getSource().orElse(""), "scm_source", new Yaml().dump(scmSource))) .build()); return; } final Repository scmSourceRepository; try { scmSourceRepository = repositories.parse(scmSourceUrl); } catch (final UnknownScmUrlException e) { violationSink.put( context.violation() .withPluginFullyQualifiedClassName(ScmRepositoryPlugin.class) .withType(ILLEGAL_SCM_REPOSITORY) .withMetaInfo(ImmutableMap.of( "application_id", context.getApplicationId().orElse(""), "deployment_artifact", context.getSource().orElse(""), "error_message", e.getMessage())) .build() ); return; } final String allowedOwnerPattern = Optional.ofNullable(properties.getHosts()) .map(ownersByHost -> ownersByHost.get(scmSourceRepository.getHost())) .orElseThrow(() -> new IllegalStateException( format("Could not find allowedOwnerPattern for %s. Available properties: %s", scmSourceRepository, properties.getHosts()))); if (!scmSourceRepository.getOwner().matches(allowedOwnerPattern)) { violationSink.put( context.violation() .withPluginFullyQualifiedClassName(ScmRepositoryPlugin.class) .withType(ILLEGAL_SCM_REPOSITORY) .withMetaInfo(ImmutableMap.of( "application_id", context.getApplicationId().orElse(""), "deployment_artifact", context.getSource().orElse(""), "normalized_scm_source_url", scmSourceRepository.toString(), "allowed_owners", allowedOwnerPattern, "actual_owner", scmSourceRepository.getOwner())) .build() ); } final Optional<Application> optionalKioApp = context.getKioApplication(); if (!optionalKioApp.isPresent()) { log.warn("Missing Kio App for {}. Skip ScmRepositoryPlugin.", context); return; } final Application app = optionalKioApp.get(); final String kioScmUrl = app.getScmUrl(); if (isBlank(kioScmUrl)) { violationSink.put( context.violation() .withPluginFullyQualifiedClassName(ScmRepositoryPlugin.class) .withType(SCM_URL_IS_MISSING_IN_KIO) .withMetaInfo(singletonMap("application_id", app.getId())) .build()); return; } try { final Repository kioRepository = repositories.parse(kioScmUrl); if (!scmSourceRepository.equals(kioRepository)) { violationSink.put( context.violation() .withPluginFullyQualifiedClassName(ScmRepositoryPlugin.class) .withType(SCM_URL_NOT_MATCH_WITH_KIO) .withMetaInfo(ImmutableMap.of( "application_id", app.getId(), "deployment_artifact", context.getSource().orElse(""), "normalized_scm_source_url", scmSourceRepository.toString(), "normalized_kio_scm_url", kioRepository.toString())).build()); } } catch (UnknownScmUrlException e) { violationSink.put( context.violation() .withPluginFullyQualifiedClassName(ScmRepositoryPlugin.class) .withType(SCM_URL_NOT_MATCH_WITH_KIO) .withMetaInfo(ImmutableMap.of( "application_id", app.getId(), "deployment_artifact", context.getSource().orElse(""), "normalized_scm_source_url", scmSourceRepository.toString(), "kio_scm_url", kioScmUrl, "error_message", e.getMessage())).build()); } } ScmRepositoryPlugin(
            final EC2InstanceContextProvider contextProvider,
            final Repositories repositories,
            final ViolationSink violationSink,
            final ScmRepositoryPluginProperties properties);   }
@Test public void testProcessEventNoViolation() throws Exception { when(mockContext.getKioApplication()).thenReturn(Optional.of(kioApp)); when(mockContext.getScmSource()).thenReturn(Optional.of(singletonMap("url", "https: when(mockRepositories.parse(anyString())).thenReturn(validRepo); plugin.process(mockContext); verify(mockContext).getKioApplication(); verify(mockContext).getScmSource(); verify(mockRepositories).parse(eq("https: verify(mockRepositories).parse(eq("git@github.com:zalando-stups/hello-world.git")); }
@Test public void testProcessMissingScmSource() throws Exception { when(mockContext.getScmSource()).thenReturn(empty()); plugin.process(mockContext); verify(mockContext).getScmSource(); }
@Test public void testProcessBlankScmSourceUrl() throws Exception { when(mockContext.getScmSource()).thenReturn(Optional.of(ImmutableMap.of("url", " ", "user", "unittester", "revision", "1a2b3c4d"))); plugin.process(mockContext); verify(mockContext).getScmSource(); verify(mockContext).getSource(); verify(mockContext).getApplicationId(); verify(mockContext).violation(); verify(mockViolationSink).put(argThat(hasType(SCM_URL_IS_MISSING_IN_SCM_SOURCE_JSON))); }
@Test public void testUnparseableScmSourceUrl() throws Exception { final String badScmUrl = "https: when(mockContext.getScmSource()).thenReturn(Optional.of(singletonMap("url", badScmUrl))); when(mockRepositories.parse(eq(badScmUrl))).thenThrow(new UnknownScmUrlException(badScmUrl)); plugin.process(mockContext); verify(mockContext).getScmSource(); verify(mockContext).getSource(); verify(mockContext).getApplicationId(); verify(mockContext).violation(); verify(mockRepositories).parse(eq(badScmUrl)); verify(mockViolationSink).put(argThat(hasType(ILLEGAL_SCM_REPOSITORY))); }
@Test public void testUnallowedOwners() throws Exception { when(mockContext.getScmSource()).thenReturn(Optional.of(singletonMap("url", unallowedRepo.toString()))); when(mockContext.getKioApplication()).thenReturn(empty()); when(mockRepositories.parse(eq(unallowedRepo.toString()))).thenReturn(unallowedRepo); plugin.process(mockContext); verify(mockContext).getScmSource(); verify(mockContext).getApplicationId(); verify(mockContext).violation(); verify(mockContext).getKioApplication(); verify(mockContext).getSource(); verify(mockRepositories).parse(eq(unallowedRepo.toString())); verify(mockViolationSink).put(argThat(hasType(ILLEGAL_SCM_REPOSITORY))); }
@Test public void testProcessMissingApp() throws Exception { when(mockContext.getScmSource()).thenReturn(Optional.of(singletonMap("url", validRepo.toString()))); when(mockContext.getKioApplication()).thenReturn(empty()); when(mockRepositories.parse(eq(validRepo.toString()))).thenReturn(validRepo); plugin.process(mockContext); verify(mockContext).getScmSource(); verify(mockContext).getKioApplication(); verify(mockRepositories).parse(eq(validRepo.toString())); }
@Test public void testProcessBlankKioScmUrl() throws Exception { when(mockContext.getScmSource()).thenReturn(Optional.of(singletonMap("url", validRepo.toString()))); when(mockRepositories.parse(eq(validRepo.toString()))).thenReturn(validRepo); when(mockContext.getKioApplication()).thenReturn(Optional.of(kioApp)); kioApp.setScmUrl(" "); plugin.process(mockContext); verify(mockContext).getScmSource(); verify(mockRepositories).parse(eq(validRepo.toString())); verify(mockContext).getKioApplication(); verify(mockContext).violation(); verify(mockViolationSink).put(argThat(hasType(SCM_URL_IS_MISSING_IN_KIO))); }
@Test public void testProcessEventWithDifferentScmUrls() throws Exception { when(mockContext.getKioApplication()).thenReturn(Optional.of(kioApp)); when(mockContext.getScmSource()).thenReturn(Optional.of(singletonMap("url", validRepo.toString()))); when(mockRepositories.parse(eq(validRepo.toString()))).thenReturn(validRepo); when(mockRepositories.parse(eq(kioApp.getScmUrl()))).thenReturn(anotherRepo); plugin.process(mockContext); verify(mockContext).getKioApplication(); verify(mockContext).getScmSource(); verify(mockContext).getSource(); verify(mockRepositories).parse(eq(validRepo.toString())); verify(mockRepositories).parse(eq(kioApp.getScmUrl())); verify(mockContext).violation(); verify(mockViolationSink).put(argThat(hasType(SCM_URL_NOT_MATCH_WITH_KIO))); }
@Test public void testProcessEventWithUnparseableKioScmUrl() throws Exception { when(mockContext.getKioApplication()).thenReturn(Optional.of(kioApp)); when(mockContext.getScmSource()).thenReturn(Optional.of(singletonMap("url", validRepo.toString()))); when(mockRepositories.parse(eq(validRepo.toString()))).thenReturn(validRepo); when(mockRepositories.parse(eq(kioApp.getScmUrl()))).thenThrow(new UnknownScmUrlException(kioApp.getScmUrl())); plugin.process(mockContext); verify(mockContext).getKioApplication(); verify(mockContext).getScmSource(); verify(mockContext).getSource(); verify(mockRepositories).parse(eq(validRepo.toString())); verify(mockRepositories).parse(eq(kioApp.getScmUrl())); verify(mockContext).violation(); verify(mockViolationSink).put(argThat(hasType(SCM_URL_NOT_MATCH_WITH_KIO))); }