Skip to content

Commit

Permalink
Merge branch 'master' into 789-capture-wave-metrics-by-container-arch…
Browse files Browse the repository at this point in the history
…itecture
  • Loading branch information
munishchouhan authored Feb 18, 2025
2 parents d702b59 + ca091c8 commit adb13e6
Show file tree
Hide file tree
Showing 37 changed files with 559 additions and 232 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.17.1
1.18.0
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ dependencies {
// upgrade indirect dependencies
runtimeOnly 'org.bouncycastle:bcpkix-jdk18on:1.78'
runtimeOnly 'org.bitbucket.b_c:jose4j:0.9.4'
runtimeOnly 'io.netty:netty-bom:4.1.115.Final'
runtimeOnly 'io.netty:netty-bom:4.1.118.Final'
runtimeOnly 'com.google.protobuf:protobuf-java:4.27.5'
}

Expand Down
14 changes: 14 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
# Wave changelog
1.18.0 - 18 Feb 2025
- Add Scan image request (#796) [a950d1cf]
- Improve caching for AWS ECR and Auth lookup (#783) [b1a76d15]
- Improve jwt debug logs [086837e9]
- Use route target path as proxy cache key (#788) [1133c348]
- Bump Micronaut to version 4.7.6 [97544609]
- Bump io.netty:netty-bom:4.1.118.Final [5a861f51]

1.17.2 - 10 Feb 2025
- Change threads dump-threshold default to 200 [5d136e45]
- Minor inspect view improvements (#795) [242822fd]
- Bump gradle 8.12.1 [6b85565e]
- Bump MN version 4.7.5 [03febd69]

1.17.1 - 4 Feb 2025
- Add container index support to inspect view (#792) [34428d25]
- Remove server from openapi spec (#793) [9cbdec1d]
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#

micronautVersion=4.7.4
micronautVersion=4.7.6
micronautEnvs=dev,h2,mail,aws-ses
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
3 changes: 2 additions & 1 deletion src/main/groovy/io/seqera/wave/auth/RegistryAuth.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import java.util.regex.Pattern
import groovy.transform.Canonical
import groovy.transform.CompileStatic
import groovy.transform.ToString
import io.seqera.wave.encoder.MoshiSerializable

/**
* Model container registry authentication meta-info
Expand All @@ -32,7 +33,7 @@ import groovy.transform.ToString
@Canonical
@CompileStatic
@ToString(includePackage = false, includeNames = true)
class RegistryAuth {
class RegistryAuth implements MoshiSerializable {

private static final Pattern AUTH = ~/(?i)(?<type>.+) realm="(?<realm>[^"]+)",service="(?<service>[^"]+)"/
// some registries doesn't send the service
Expand Down
61 changes: 0 additions & 61 deletions src/main/groovy/io/seqera/wave/auth/RegistryAuthStore.groovy

This file was deleted.

83 changes: 83 additions & 0 deletions src/main/groovy/io/seqera/wave/auth/RegistryLookupCache.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* 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.auth

import java.time.Duration

import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.adapters.PolymorphicJsonAdapterFactory
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import io.micronaut.context.annotation.Value
import io.micronaut.core.annotation.Nullable
import io.seqera.wave.encoder.MoshiEncodeStrategy
import io.seqera.wave.encoder.MoshiSerializable
import io.seqera.wave.store.cache.AbstractTieredCache
import io.seqera.wave.store.cache.L2TieredCache
import jakarta.inject.Singleton
/**
* Implement a tiered cache for {@link RegistryLookupService}
*
* @author Munish Chouhan <munish.chouhan@seqera.io>
*/
@Slf4j
@Singleton
@CompileStatic
class RegistryLookupCache extends AbstractTieredCache<String, RegistryAuth> {

@Value('${wave.registry-lookup.cache.duration:1h}')
private Duration duration

@Value('${wave.registry-lookup.cache.max-size:10000}')
private int maxSize

RegistryLookupCache(@Nullable L2TieredCache l2) {
super(l2, encoder())
}

@Override
int getMaxSize() {
return maxSize
}

@Override
protected getName() {
return 'registry-lookup-cache'
}

Duration getDuration() {
return duration
}

@Override
protected String getPrefix() {
return 'registry-lookup-cache/v1'
}

static MoshiEncodeStrategy encoder() {
new MoshiEncodeStrategy<AbstractTieredCache.Entry>(factory()) {}
}

static JsonAdapter.Factory factory() {
PolymorphicJsonAdapterFactory.of(MoshiSerializable.class, "@type")
.withSubtype(AbstractTieredCache.Entry.class, AbstractTieredCache.Entry.name)
.withSubtype(RegistryAuth.class, RegistryAuth.name)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,15 @@ package io.seqera.wave.auth

import java.net.http.HttpRequest
import java.net.http.HttpResponse
import java.util.concurrent.CompletionException
import java.util.concurrent.ExecutorService
import java.util.concurrent.TimeUnit

import com.github.benmanes.caffeine.cache.AsyncLoadingCache
import com.github.benmanes.caffeine.cache.CacheLoader
import com.github.benmanes.caffeine.cache.Caffeine
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import io.micronaut.scheduling.TaskExecutors
import io.seqera.wave.configuration.HttpClientConfig
import io.seqera.wave.exception.RegistryForwardException
import io.seqera.wave.http.HttpClientFactory
import io.seqera.wave.util.Retryable
import jakarta.annotation.PostConstruct
import jakarta.inject.Inject
import jakarta.inject.Named
import jakarta.inject.Singleton
Expand All @@ -56,43 +50,12 @@ class RegistryLookupServiceImpl implements RegistryLookupService {
@Inject
private HttpClientConfig httpConfig

@Inject
private RegistryAuthStore store

@Inject
@Named(TaskExecutors.BLOCKING)
private ExecutorService ioExecutor

private CacheLoader<URI, RegistryAuth> loader = new CacheLoader<URI, RegistryAuth>() {
@Override
RegistryAuth load(URI endpoint) throws Exception {
// check if there's a record in the store cache (redis)
def result = store.get(endpoint.toString())
if( result ) {
log.debug "Authority lookup for endpoint: '$endpoint' => $result [from store]"
return result
}
// look-up using the corresponding API endpoint
result = lookup0(endpoint)
log.debug "Authority lookup for endpoint: '$endpoint' => $result"
// save it in the store cache (redis)
store.put(endpoint.toString(), result)
return result
}
}

// FIXME https://github.com/seqeralabs/wave/issues/747
private AsyncLoadingCache<URI, RegistryAuth> cache

@PostConstruct
void init() {
cache = Caffeine
.newBuilder()
.maximumSize(10_000)
.expireAfterAccess(1, TimeUnit.HOURS)
.executor(ioExecutor)
.buildAsync(loader)
}
@Inject
private RegistryLookupCache cache

protected RegistryAuth lookup0(URI endpoint) {
final httpClient = HttpClientFactory.followRedirectsHttpClient()
Expand Down Expand Up @@ -129,17 +92,9 @@ class RegistryLookupServiceImpl implements RegistryLookupService {
*/
@Override
RegistryInfo lookup(String registry) {
try {
final endpoint = registryEndpoint(registry)
// FIXME https://github.com/seqeralabs/wave/issues/747
final auth = cache.synchronous().get(endpoint)
return new RegistryInfo(registry, endpoint, auth)
}
catch (CompletionException e) {
// this catches the exception thrown in the cache loader lookup
// and throws the causing exception that should be `RegistryUnauthorizedAccessException`
throw e.cause
}
final endpoint = registryEndpoint(registry)
final auth = cache.getOrCompute(endpoint.toString(), (k) -> lookup0(endpoint), cache.duration)
return new RegistryInfo(registry, endpoint, auth)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import jakarta.inject.Singleton
@ToString(includeNames = true, includePackage = false)
class ProxyCacheConfig {

@Value('${wave.proxy-cache.duration:4m}')
@Value('${wave.proxy-cache.duration:120s}')
private Duration duration

@Value('${wave.proxy-cache.max-size:10000}')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,8 @@ class ContainerController {
if( !registration )
throw new BadRequestException("Missing pairing record for Tower endpoint '$req.towerEndpoint'")

// store the jwt record only the very first time it has been
// to avoid overridden a newer refresh token that may have
// store the jwt record only the very first time to avoid
// overriding a newer jwt token that may have refreshed
final auth = JwtAuth.of(req)
if( auth.refresh )
jwtAuthStore.storeIfAbsent(auth)
Expand Down
Loading

0 comments on commit adb13e6

Please sign in to comment.