diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 2704b68..cfac590 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -1,6 +1,13 @@
version: 2
+registries:
+ maven-github:
+ type: maven-repository
+ url: https://maven.pkg.github.com/homecentr
+ username: lholota
+ password: ${{ secrets.GH_PACKAGES_TOKEN }}
updates:
- package-ecosystem: gradle
+ registries: "*"
directory: "/tests"
schedule:
interval: daily
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ccd20ee..2a18b22 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -11,13 +11,11 @@ env:
jobs:
build:
runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ packages: read
steps:
- uses: actions/checkout@master
-
- - name: Set up java for tests execution
- uses: actions/setup-java@v1
- with:
- java-version: 11
- name: Set tag var
id: vars
@@ -30,10 +28,7 @@ jobs:
run: docker build . -t ${{ env.IMAGE_NAME }}:${{ steps.vars.outputs.docker_tag }}
- name: Test Docker image
- run: cd tests && sudo gradle test --info -Dimage_tag=${{ env.IMAGE_NAME }}:${{ steps.vars.outputs.docker_tag }}
-
- - name: Scan with Phonito Security
- uses: phonito/phonito-scanner-action@master
- with:
- image: ${{ env.IMAGE_NAME }}:${{ steps.vars.outputs.docker_tag }}
- phonito-token: '${{ secrets.PHONITO_TOKEN }}'
\ No newline at end of file
+ run: cd tests && sudo --preserve-env gradle test --info -Ddocker_image_tag=${{ env.IMAGE_NAME }}:${{ steps.vars.outputs.docker_tag }}
+ env: # To allow downloading packages
+ GITHUB_USERNAME: ${{ github.actor }}
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml
index 7fc99c5..d35dddf 100644
--- a/.github/workflows/ci_cd.yml
+++ b/.github/workflows/ci_cd.yml
@@ -10,16 +10,14 @@ env:
jobs:
build:
runs-on: ubuntu-latest
+ permissions:
+ contents: write # To add version tags
+ packages: write # To push docker image
steps:
- uses: actions/checkout@master
- - name: Set up java for tests execution
- uses: actions/setup-java@v1
- with:
- java-version: 11
-
- name: "Determine release version"
- uses: codfish/semantic-release-action@master
+ uses: docker://ghcr.io/codfish/semantic-release-action:v1.9.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -29,7 +27,11 @@ jobs:
- name: "Build Docker image"
if: env.RELEASE_VERSION != ''
run: |
- docker build . -t "$IMAGE_NAME:$RELEASE_VERSION" \
+ docker build . \
+ --tag "$IMAGE_NAME:$RELEASE_VERSION" \
+ --tag "$IMAGE_NAME:latest" \
+ --tag "ghcr.io/$IMAGE_NAME:$RELEASE_VERSION" \
+ --tag "ghcr.io/$IMAGE_NAME:latest" \
--label "org.label-schema.schema-version=1.0" \
--label "org.label-schema.vcs-ref=${GITHUB_SHA}" \
--label "org.label-schema.vcs-url=https://github.com/${GITHUB_REPOSITORY}" \
@@ -40,36 +42,33 @@ jobs:
- name: Test Docker image
if: env.RELEASE_VERSION != ''
- run: cd tests && sudo gradle test -Dimage_tag=${{ env.IMAGE_NAME }}:${{ env.RELEASE_VERSION }}
-
- - name: Scan with Phonito Security
- if: env.RELEASE_VERSION != ''
- uses: phonito/phonito-scanner-action@master
- with:
- image: ${{ env.IMAGE_NAME }}:${{ env.RELEASE_VERSION }}
- phonito-token: '${{ secrets.PHONITO_TOKEN }}'
-
- - name: "Tag image as latest"
- if: env.RELEASE_VERSION != ''
- run: "docker tag $IMAGE_NAME:$RELEASE_VERSION $IMAGE_NAME:latest"
+ run: cd tests && sudo --preserve-env gradle test -Ddocker_image_tag=${{ env.IMAGE_NAME }}:${{ env.RELEASE_VERSION }}
+ env: # To allow downloading packages
+ GITHUB_USERNAME: ${{ github.actor }}
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ # DockerHub
- name: "Log into Docker Hub"
if: env.RELEASE_VERSION != ''
run: "echo ${{ secrets.DOCKERHUB_PASSWORD }} | docker login --username ${{ secrets.DOCKERHUB_USERNAME }} --password-stdin"
- - name: "Push versioned image"
+ - name: "Push to DockerHub"
if: env.RELEASE_VERSION != ''
- run: "docker push $IMAGE_NAME:$RELEASE_VERSION"
-
- - name: "Push latest image"
- if: env.RELEASE_VERSION != ''
- run: "docker push $IMAGE_NAME:latest"
+ run: "docker push $IMAGE_NAME:$RELEASE_VERSION && docker push $IMAGE_NAME:latest"
- name: "Update Docker Hub description"
if: env.RELEASE_VERSION != ''
- uses: peter-evans/dockerhub-description@v2.4.2
+ uses: peter-evans/dockerhub-description@v2.4.3
env:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }}
DOCKERHUB_REPOSITORY: ${{ env.IMAGE_NAME }}
-
\ No newline at end of file
+
+ # GitHub Packages
+ - name: "Log into GitHub Packages"
+ if: env.RELEASE_VERSION != ''
+ run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
+
+ - name: "Push to GitHub Packages"
+ if: env.RELEASE_VERSION != ''
+ run: "docker push ghcr.io/$IMAGE_NAME:$RELEASE_VERSION && docker push ghcr.io/$IMAGE_NAME:latest"
\ No newline at end of file
diff --git a/.github/workflows/regular_scan.yml b/.github/workflows/regular_scan.yml
deleted file mode 100644
index 4cf0a1e..0000000
--- a/.github/workflows/regular_scan.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-name: Regular Docker image vulnerability scan
-on:
- schedule:
- - cron: '0 6 * * *'
-
-env:
- IMAGE_NAME: "homecentr/swarm-local-network-connector"
-
-jobs:
- build:
- runs-on: ubuntu-latest
- steps:
- - name: Pull Docker image
- run: docker pull ${{ env.IMAGE_NAME }}:latest
-
- - name: Scan image for vulnerabilities
- uses: phonito/phonito-scanner-action@master
- with:
- image: ${{ env.IMAGE_NAME }}:latest
- phonito-token: '${{ secrets.PHONITO_TOKEN }}'
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index 5bc0fca..9a625af 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,8 +1,8 @@
-FROM golang:1.16.0-alpine as build
+FROM golang:1.17.0-alpine3.14 as build
ENV GO111MODULE=auto
-RUN apk add --no-cache git=2.30.1-r0
+RUN apk add --no-cache git=2.32.0-r0
COPY ./src /go/src/github.com/homecentr/docker-swarm-local-network-connector
@@ -11,7 +11,7 @@ WORKDIR /go/src/github.com/homecentr/docker-swarm-local-network-connector
RUN go get ./... && \
go build
-FROM homecentr/base:2.4.3-alpine
+FROM homecentr/base:3.2.0-alpine
# Copy S6 overlay
COPY --from=build /go/src/github.com/homecentr/docker-swarm-local-network-connector/docker-swarm-local-network-connector /swarm-local-network-connector
diff --git a/README.md b/README.md
index ce21921..d6c7aee 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,6 @@
[![](https://badgen.net/docker/size/homecentr/swarm-local-network-connector)](https://hub.docker.com/repository/docker/homecentr/swarm-local-network-connector)
![CI/CD on master](https://github.com/homecentr/docker-swarm-local-network-connector/workflows/CI/CD%20on%20master/badge.svg)
-![Regular Docker image vulnerability scan](https://github.com/homecentr/docker-swarm-local-network-connector/workflows/Regular%20Docker%20image%20vulnerability%20scan/badge.svg)
# HomeCentr - swarm-local-network-connector
Connector process which monitors for newly created containers and connectes them to the network specified in the label. This is a workaround to solve the problem when Docker Swarm does not pass explicit IP address when connecting container to a macvlan network or other local scoped network drivers.
diff --git a/SECURITY.md b/SECURITY.md
index 432ecf9..4de4bc1 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -10,6 +10,6 @@ Known security issues will be published in GitHub repository's Security / Securi
## Automated processes
-The Docker image is scanned for vulnerabilities every 24 hours using [Phonito.io](https://phonito.io/?b=a). You can see the scan status under the actions tab / Regular Docker image vulnerability scan.
+The Docker image is regularly scanned for vulnerabilities with [Snyk.io](https://snyk.io/).
The dependencies are automatically scanned using [Dependabot](https://dependabot.com/). Dependencies are regularly updated. You can check for pending dependency updates by listing open Pull requests with the "dependencies" label.
\ No newline at end of file
diff --git a/fs/etc/services.d/connector/run b/fs/etc/services.d/connector/run
index d153499..9472a1f 100644
--- a/fs/etc/services.d/connector/run
+++ b/fs/etc/services.d/connector/run
@@ -1,5 +1,3 @@
#!/usr/bin/with-contenv sh
-s6-setuidgid "$PUID:$PGID"
-
-exec /swarm-local-network-connector
\ No newline at end of file
+exec runas /swarm-local-network-connector
\ No newline at end of file
diff --git a/tests/.idea/jarRepositories.xml b/tests/.idea/jarRepositories.xml
index fdc392f..760e86d 100644
--- a/tests/.idea/jarRepositories.xml
+++ b/tests/.idea/jarRepositories.xml
@@ -16,5 +16,10 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/build.gradle b/tests/build.gradle
index d259824..d5bce49 100644
--- a/tests/build.gradle
+++ b/tests/build.gradle
@@ -9,17 +9,27 @@ sourceCompatibility = 1.8
repositories {
mavenCentral()
+ maven {
+ name = "GitHubPackages"
+ url = uri("https://maven.pkg.github.com/homecentr/lib-testcontainers-extensions")
+ credentials {
+ username = System.getenv("GITHUB_USERNAME")
+ password = System.getenv("GITHUB_TOKEN")
+ }
+ }
}
dependencies {
testImplementation group: 'junit', name: 'junit', version: '4.13.2'
- testImplementation "org.testcontainers:testcontainers:1.15.2"
- testImplementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.30'
- testImplementation group: 'org.slf4j', name: 'slf4j-simple', version: '1.7.30'
+ testImplementation group: 'org.testcontainers', name: 'testcontainers', version: '1.16.0'
+ testImplementation group: 'io.homecentr', name: 'testcontainers-extensions', version: '1.6.0'
+ testImplementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.32'
+ testImplementation group: 'org.slf4j', name: 'slf4j-simple', version: '1.7.32'
}
test {
- systemProperty 'image_tag', System.getProperty('image_tag')
+ systemProperty 'docker_image_tag', System.getProperty('docker_image_tag')
+
afterTest { desc, result ->
logger.quiet "Executing test ${desc.name} [${desc.className}] with result: ${result.resultType}"
}
diff --git a/tests/src/test/java/ConnectorContainerShould.java b/tests/src/test/java/ConnectorContainerShould.java
index 8f05cfb..028d22c 100644
--- a/tests/src/test/java/ConnectorContainerShould.java
+++ b/tests/src/test/java/ConnectorContainerShould.java
@@ -1,4 +1,8 @@
-import PullPolicies.NeverPullImagePolicy;
+import helpers.DockerImageTagResolver;
+import io.homecentr.testcontainers.containers.GenericContainerEx;
+import io.homecentr.testcontainers.images.NeverPullImagePolicy;
+import org.junit.After;
+import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -6,109 +10,94 @@
import org.testcontainers.containers.output.Slf4jLogConsumer;
import org.testcontainers.containers.wait.strategy.Wait;
+import java.time.Duration;
import java.util.concurrent.TimeoutException;
+import static io.homecentr.testcontainers.WaitLoop.waitFor;
import static org.junit.Assert.assertEquals;
public class ConnectorContainerShould extends ContainerTestBase {
private static final Logger logger = LoggerFactory.getLogger(ContainerTestBase.class);
- @Test
- public void connectContainersCreatedBeforeStartOfConnector() throws InterruptedException, TimeoutException {
-
- GenericContainer targetContainer = new GenericContainer<>("nginx")
- .withLabel("io.homecentr.local-networks", "[{ \"Network\": \""+ getNetworkName() +"\" }]");
+ private GenericContainer _connectorContainer;
+ private GenericContainer _targetContainer;
- GenericContainer connectorContainer = createConnectorContainer();
-
- try {
- targetContainer.start();
+ @Before
+ public void before() {
+ _connectorContainer = new GenericContainerEx<>(new DockerImageTagResolver())
+ .withFileSystemBind("//var/run/docker.sock", "/var/run/docker.sock")
+ .withImagePullPolicy(new NeverPullImagePolicy())
+ .withEnv("LOG_LEVEL", "debug")
+ .withEnv("PUID", "0")
+ .withEnv("PGID", "0")
+ .waitingFor(Wait.forLogMessage(".*Started, waiting for signal.*", 1));
+ }
- connectorContainer.start();
- connectorContainer.followOutput(new Slf4jLogConsumer(logger));
+ @After
+ public void after() {
+ _connectorContainer.close();
- waitUntilContainerConnectedToNetwork(targetContainer, 5000);
- }
- finally {
- targetContainer.close();
- connectorContainer.close();
+ if(_targetContainer != null) {
+ _targetContainer.close();
}
}
@Test
- public void connectContainerCreatedAfterStartOfConnector() throws InterruptedException, TimeoutException {
- GenericContainer targetContainer = new GenericContainer<>("nginx")
+ public void connectContainersCreatedBeforeStartOfConnector() throws Exception {
+ _targetContainer = new GenericContainer<>("nginx")
.withLabel("io.homecentr.local-networks", "[{ \"Network\": \""+ getNetworkName() +"\" }]");
- GenericContainer connectorContainer = createConnectorContainer();
+ _targetContainer.start();
- try {
- connectorContainer.start();
- targetContainer.start();
+ _connectorContainer.start();
+ _connectorContainer.followOutput(new Slf4jLogConsumer(logger));
- connectorContainer.followOutput(new Slf4jLogConsumer(logger));
+ waitFor(Duration.ofSeconds(5), () -> isConnectedToNetwork(_targetContainer));
+ }
- waitUntilContainerConnectedToNetwork(targetContainer, 5000);
- }
- finally {
- targetContainer.close();
- connectorContainer.close();
- }
+ @Test
+ public void connectContainerCreatedAfterStartOfConnector() throws Exception {
+ _targetContainer = new GenericContainer<>("nginx")
+ .withLabel("io.homecentr.local-networks", "[{ \"Network\": \""+ getNetworkName() +"\" }]");
+
+ _connectorContainer.start();
+ _connectorContainer.followOutput(new Slf4jLogConsumer(logger));
+
+ _targetContainer.start();
+
+ waitFor(Duration.ofSeconds(5), () -> isConnectedToNetwork(_targetContainer));
}
@Test
public void connectContainerWithExplicitConfig() throws Exception {
- GenericContainer targetContainer = new GenericContainer<>("nginx")
+ _targetContainer = new GenericContainer<>("nginx")
.withLabel("io.homecentr.local-networks", "[{ \"Network\": \""+ getNetworkName() +"\", \"Config\": { \"IPAMConfig\": { \"IPV4Address\": \"192.168.99.100\" } } }]");
- GenericContainer connectorContainer = createConnectorContainer();
-
- try {
- connectorContainer.start();
- targetContainer.start();
+ _connectorContainer.start();
+ _connectorContainer.followOutput(new Slf4jLogConsumer(logger));
- connectorContainer.followOutput(new Slf4jLogConsumer(logger));
+ _targetContainer.start();
- waitUntilContainerConnectedToNetwork(targetContainer, 5000);
+ waitFor(Duration.ofSeconds(5), () -> isConnectedToNetwork(_targetContainer));
- assertEquals("192.168.99.100", getContainerIpAddress(targetContainer));
- }
- finally {
- targetContainer.close();
- connectorContainer.close();
- }
+ assertEquals("192.168.99.100", getContainerIpAddress(_targetContainer));
}
@Test
public void ignoreContainerWithInvalidLabel() throws Exception {
- GenericContainer targetContainer = new GenericContainer<>("nginx")
+ _targetContainer = new GenericContainer<>("nginx")
.withLabel("io.homecentr.local-networks", "[{ \"Network\": \""+ getNetworkName() +"\" }]");
- GenericContainer connectorContainer = createConnectorContainer();
-
- try {
- connectorContainer.start();
- targetContainer.start();
+ _connectorContainer.start();
+ _connectorContainer.followOutput(new Slf4jLogConsumer(logger));
- connectorContainer.followOutput(new Slf4jLogConsumer(logger));
+ _targetContainer.start();
- try {
- waitUntilContainerConnectedToNetwork(targetContainer, 5000);
- }
- catch (TimeoutException ex) { }
- }
- finally {
- targetContainer.close();
- connectorContainer.close();
+ try {
+ // Wait to make sure the container is not connected to the network
+ waitFor(Duration.ofSeconds(5), () -> isConnectedToNetwork(_targetContainer));
}
- }
-
- private GenericContainer createConnectorContainer() {
- return new GenericContainer<>(getConnectorImageTag())
- .withFileSystemBind("//var/run/docker.sock", "/var/run/docker.sock")
- .withImagePullPolicy(new NeverPullImagePolicy())
- .withEnv("LOG_LEVEL", "debug")
- .waitingFor(Wait.forLogMessage(".*Started, waiting for signal.*", 1));
+ catch (TimeoutException ex) { }
}
}
diff --git a/tests/src/test/java/ContainerTestBase.java b/tests/src/test/java/ContainerTestBase.java
index 5ea05f3..1dda0ce 100644
--- a/tests/src/test/java/ContainerTestBase.java
+++ b/tests/src/test/java/ContainerTestBase.java
@@ -7,8 +7,6 @@
import org.testcontainers.DockerClientFactory;
import org.testcontainers.containers.GenericContainer;
-import java.util.concurrent.TimeoutException;
-
public abstract class ContainerTestBase {
private static final String networkName = "target-network";
@@ -27,24 +25,6 @@ public static void cleanUp() {
deleteNetwork(_networkId);
}
- protected String getConnectorImageTag() {
- return System.getProperty("image_tag");
- }
-
- protected void waitUntilContainerConnectedToNetwork(GenericContainer container, Integer timeout) throws InterruptedException, TimeoutException {
- long startTime = System.currentTimeMillis();
-
- while (!isConnectedToNetwork(container)) {
- long remaining = System.currentTimeMillis() - startTime - timeout;
-
- if (remaining < 0) {
- throw new TimeoutException("The container did not get connected to the network within the timeout.");
- }
-
- Thread.sleep(500);
- }
- }
-
protected String getContainerIpAddress(GenericContainer container) throws Exception {
InspectContainerResponse response = _client.inspectContainerCmd(container.getContainerId()).exec();
@@ -57,7 +37,7 @@ protected String getContainerIpAddress(GenericContainer container) throws Except
throw new Exception("The container is not connected to the network " + _networkId);
}
- private boolean isConnectedToNetwork(GenericContainer container) {
+ protected boolean isConnectedToNetwork(GenericContainer container) {
InspectContainerResponse response = _client.inspectContainerCmd(container.getContainerId()).exec();
for (ContainerNetwork network : response.getNetworkSettings().getNetworks().values()) {
diff --git a/tests/src/test/java/PullPolicies/NeverPullImagePolicy.java b/tests/src/test/java/PullPolicies/NeverPullImagePolicy.java
deleted file mode 100644
index 6a08c16..0000000
--- a/tests/src/test/java/PullPolicies/NeverPullImagePolicy.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package PullPolicies;
-
-import org.testcontainers.images.ImagePullPolicy;
-import org.testcontainers.utility.DockerImageName;
-
-public class NeverPullImagePolicy implements ImagePullPolicy {
- @Override
- public boolean shouldPull(DockerImageName imageName) {
- return false;
- }
-}
\ No newline at end of file
diff --git a/tests/src/test/java/helpers/DockerImageTagResolver.java b/tests/src/test/java/helpers/DockerImageTagResolver.java
new file mode 100644
index 0000000..d548e86
--- /dev/null
+++ b/tests/src/test/java/helpers/DockerImageTagResolver.java
@@ -0,0 +1,10 @@
+package helpers;
+
+import io.homecentr.testcontainers.images.EnvironmentImageTagResolver;
+import io.homecentr.testcontainers.images.SystemWrapperImpl;
+
+public class DockerImageTagResolver extends EnvironmentImageTagResolver {
+ public DockerImageTagResolver() {
+ super(new SystemWrapperImpl(), "homecentr/swarm-local-network-connector:local");
+ }
+}