-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for Container mirroring (#646)
This commit adds the support for container mirror functionality. Container mirror allows creating a copy of a container repository to a target container registry keeping the unchanged the repository name and the container checksums, and therefore creating an identical copy to another registry. Container mirror is an extension of the Wave build-on-demand feature. For example ``` wave -i docker.io/my/foo:bar --mirror-to quay.io ``` it will create a copy of the specified repository using the target image name `quay.io/my/foo:bar` Signed-off-by: Paolo Di Tommaso <[email protected]>
- Loading branch information
1 parent
80a7e81
commit 2f5a1fe
Showing
50 changed files
with
2,632 additions
and
144 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
53 changes: 53 additions & 0 deletions
53
src/main/groovy/io/seqera/wave/controller/MirrorController.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
/* | ||
* Wave, containers provisioning service | ||
* Copyright (c) 2023-2024, Seqera Labs | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Affero General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Affero General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Affero General Public License | ||
* along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
package io.seqera.wave.controller | ||
|
||
import groovy.transform.CompileStatic | ||
import groovy.util.logging.Slf4j | ||
import io.micronaut.http.HttpResponse | ||
import io.micronaut.http.annotation.Controller | ||
import io.micronaut.http.annotation.Get | ||
import io.micronaut.scheduling.TaskExecutors | ||
import io.micronaut.scheduling.annotation.ExecuteOn | ||
import io.seqera.wave.service.mirror.ContainerMirrorService | ||
import io.seqera.wave.service.mirror.MirrorState | ||
import jakarta.inject.Inject | ||
/** | ||
* Implements a controller for container mirror apis | ||
* | ||
* @author Paolo Di Tommaso <[email protected]> | ||
*/ | ||
@Slf4j | ||
@CompileStatic | ||
@Controller("/") | ||
@ExecuteOn(TaskExecutors.IO) | ||
class MirrorController { | ||
|
||
@Inject | ||
private ContainerMirrorService mirrorService | ||
|
||
@Get("/v1alpha1/mirrors/{mirrorId}") | ||
HttpResponse<MirrorState> getMirrorRecord(String mirrorId) { | ||
final result = mirrorService.getMirrorState(mirrorId) | ||
return result | ||
? HttpResponse.ok(result) | ||
: HttpResponse.<MirrorState>notFound() | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,6 +20,7 @@ package io.seqera.wave.service.cache | |
|
||
import java.time.Duration | ||
|
||
import groovy.transform.CompileStatic | ||
import io.seqera.wave.encoder.EncodingStrategy | ||
import io.seqera.wave.service.cache.impl.CacheProvider | ||
|
||
|
@@ -28,6 +29,7 @@ import io.seqera.wave.service.cache.impl.CacheProvider | |
* | ||
* @author Paolo Di Tommaso <[email protected]> | ||
*/ | ||
@CompileStatic | ||
abstract class AbstractCacheStore<V> implements CacheStore<String,V> { | ||
|
||
private EncodingStrategy<V> encodingStrategy | ||
|
@@ -45,6 +47,10 @@ abstract class AbstractCacheStore<V> implements CacheStore<String,V> { | |
|
||
protected String key0(String k) { return getPrefix() + k } | ||
|
||
protected String recordId0(String recordId) { | ||
return getPrefix() + 'state-id/' + recordId | ||
} | ||
|
||
protected V deserialize(String encoded) { | ||
return encodingStrategy.decode(encoded) | ||
} | ||
|
@@ -63,32 +69,34 @@ abstract class AbstractCacheStore<V> implements CacheStore<String,V> { | |
return result ? deserialize(result) : null | ||
} | ||
|
||
V getByRecordId(String recordId) { | ||
final key = delegate.get(recordId0(recordId)) | ||
return get(key) | ||
} | ||
|
||
void put(String key, V value) { | ||
delegate.put(key0(key), serialize(value), getDuration()) | ||
put(key, value, getDuration()) | ||
} | ||
|
||
@Override | ||
void put(String key, V value, Duration ttl) { | ||
delegate.put(key0(key), serialize(value), ttl) | ||
if( value instanceof StateRecord ) { | ||
delegate.put(recordId0(value.getRecordId()), key, ttl) | ||
} | ||
} | ||
|
||
@Override | ||
boolean putIfAbsent(String key, V value, Duration ttl) { | ||
delegate.putIfAbsent(key0(key), serialize(value), ttl) | ||
final result = delegate.putIfAbsent(key0(key), serialize(value), ttl) | ||
if( result && value instanceof StateRecord ) { | ||
delegate.put(recordId0(value.getRecordId()), key, ttl) | ||
} | ||
return result | ||
} | ||
|
||
boolean putIfAbsent(String key, V value) { | ||
delegate.putIfAbsent(key0(key), serialize(value), getDuration()) | ||
} | ||
|
||
@Override | ||
V putIfAbsentAndGetCurrent(String key, V value, Duration ttl) { | ||
final result = delegate.putIfAbsentAndGetCurrent(key0(key), serialize(value), ttl) | ||
return result? deserialize(result) : null | ||
} | ||
|
||
V putIfAbsentAndGetCurrent(String key, V value) { | ||
return putIfAbsentAndGetCurrent(key, value, getDuration()) | ||
return putIfAbsent(key, value, getDuration()) | ||
} | ||
|
||
@Override | ||
|
Oops, something went wrong.