Skip to content

Commit

Permalink
feat(edda): implement edda AccountProvider (#119)
Browse files Browse the repository at this point in the history
  • Loading branch information
asher authored Oct 18, 2018
1 parent 1dfb4cc commit 48348bb
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.ObjectMapper
import com.netflix.spinnaker.okhttp.SpinnakerRequestInterceptor
import com.netflix.spinnaker.swabbie.clouddriver.CloudDriverService
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Import
Expand All @@ -29,6 +30,7 @@ import retrofit.RestAdapter
import retrofit.client.Client
import retrofit.converter.JacksonConverter

@ConditionalOnExpression("!\${eddaEndpoints.enabled:false}")
@Configuration
@Import(RetrofitConfiguration::class)
open class ClouddriverConfiguration {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,18 @@ import com.netflix.spinnaker.swabbie.AccountProvider
import com.netflix.spinnaker.swabbie.InMemoryCache
import com.netflix.spinnaker.swabbie.model.Account
import com.netflix.spinnaker.swabbie.model.SpinnakerAccount
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean
import org.springframework.stereotype.Component

@ConditionalOnBean(CloudDriverService::class)
@Component
class ClouddriverAccountProvider(
private val accountCache: InMemoryCache<SpinnakerAccount>
) : AccountProvider {
override fun getAccounts(): Set<Account> = accountCache.get()
}

@ConditionalOnBean(CloudDriverService::class)
@Component
class ClouddriverAccountCache(
cloudDriverService: CloudDriverService
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ open class InMemoryCache<out T : Cacheable>(

private val cache = AtomicReference<Set<T>>()

@Scheduled(fixedDelay = 60 * 60 * 1000L) //TODO: make configurable
@Scheduled(fixedDelay = 15 * 60 * 1000L) //TODO: make configurable
private fun refresh() {
try {
cache.set(source)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,17 @@ package com.netflix.spinnaker.config

import com.fasterxml.jackson.databind.ObjectMapper
import com.netflix.spinnaker.swabbie.AccountProvider
import com.netflix.spinnaker.swabbie.edda.EddaEndpointsService
import com.netflix.spinnaker.swabbie.edda.EddaService
import com.netflix.spinnaker.swabbie.model.Account
import com.netflix.spinnaker.swabbie.retrofit.SwabbieRetrofitConfiguration
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Import
import retrofit.Endpoint
import retrofit.Endpoints
import retrofit.RequestInterceptor
import retrofit.RestAdapter
Expand Down Expand Up @@ -59,6 +63,27 @@ open class EddaConfiguration {
}
}.flatten()
}

@ConditionalOnExpression("\${eddaEndpoints.enabled:false}")
@Bean
open fun eddaEndpointsEndpoint(@Value("\${eddaEndpoints.baseUrl}") eddaEndpointsBaseUrl: String) : Endpoint {
return Endpoints.newFixedEndpoint(eddaEndpointsBaseUrl)!!
}

@ConditionalOnExpression("\${eddaEndpoints.enabled:false}")
@Bean
open fun eddaEndpointsService(eddaEndpointsEndpoint: Endpoint,
objectMapper: ObjectMapper,
retrofitClient: Client,
spinnakerRequestInterceptor: RequestInterceptor,
retrofitLogLevel: RestAdapter.LogLevel) = RestAdapter.Builder()
.setRequestInterceptor(spinnakerRequestInterceptor)
.setEndpoint(eddaEndpointsEndpoint)
.setClient(retrofitClient)
.setLogLevel(retrofitLogLevel)
.setConverter(JacksonConverter(objectMapper))
.build()
.create(EddaEndpointsService::class.java)
}

data class EddaApiClient(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.netflix.spinnaker.swabbie.edda

import retrofit.http.GET

interface EddaEndpointsService {
@GET("/api/v1/edda/endpoints.json")
fun getEddaEndpoints(): EddaEndpointsContainer

data class EddaEndpointsContainer(
val edda_endpoints: EddaEndpoints
) {
data class EddaEndpoints(
val by_account: List<String>?,
val by_cluster: List<String>?
)

fun get(): List<String> = edda_endpoints.by_cluster ?: emptyList()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.netflix.spinnaker.swabbie.edda.providers

import com.netflix.spinnaker.swabbie.AccountProvider
import com.netflix.spinnaker.swabbie.InMemoryCache
import com.netflix.spinnaker.swabbie.edda.EddaEndpointsService
import com.netflix.spinnaker.swabbie.model.Account
import com.netflix.spinnaker.swabbie.model.Region
import com.netflix.spinnaker.swabbie.model.SpinnakerAccount
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression
import org.springframework.context.annotation.Lazy
import org.springframework.stereotype.Component

@ConditionalOnExpression("\${eddaEndpoints.enabled:false}")
@Component
class EddaAccountProvider(
private val eddaEndpointsService: EddaEndpointsService,
@Lazy private val accountCache: InMemoryCache<SpinnakerAccount>
) : AccountProvider {
override fun getAccounts(): Set<Account> = accountCache.get()

fun load(): Set<SpinnakerAccount> {
return eddaEndpointsService.getEddaEndpoints().get()
.asSequence()
.mapNotNull { endpointToAccount(it) }
.toSet()
}

// i.e. "http://edda-account.region.foo.bar.com",
private fun endpointToAccount(endpoint: String): SpinnakerAccount? {
val regex = """^https?://edda-([\w\-]+)\.([\w\-]+)\..*$""".toRegex()
val match = regex.matchEntire(endpoint) ?: return null
val (account, region) = match.destructured

return SpinnakerAccount(true, null, "aws", account, endpoint, listOf(Region(false, region)))
}
}

@ConditionalOnExpression("\${eddaEndpoints.enabled:false}")
@Component
class EddaAccountCache(
eddaAccountProvider: EddaAccountProvider
) : InMemoryCache<SpinnakerAccount>(eddaAccountProvider.load())

0 comments on commit 48348bb

Please sign in to comment.