From 2ded07392c3ee473d75cdb3796bc2c40f6240f7a Mon Sep 17 00:00:00 2001 From: Rob Fletcher Date: Thu, 6 Sep 2018 17:20:45 -0700 Subject: [PATCH] feat(plugins): let's log out the plugins we have on startup --- .../keel/redis/RedisPluginRepository.kt | 46 ++++++++++++++++--- .../keel/registry/PluginRepositoryTests.kt | 28 ++++++++--- .../spinnaker/keel/grpc/GrpcPluginRegistry.kt | 23 +++++++++- .../spinnaker/keel/registry/AssetType.kt | 18 ++++++++ .../keel/registry/InMemoryPluginRepository.kt | 22 +++++++-- .../spinnaker/keel/registry/PluginAddress.kt | 15 ++++++ .../keel/registry/PluginRepository.kt | 21 +++++++-- 7 files changed, 150 insertions(+), 23 deletions(-) create mode 100644 keel-rule-engine/src/main/kotlin/com/netflix/spinnaker/keel/registry/AssetType.kt diff --git a/keel-redis/src/main/kotlin/com/netflix/spinnaker/keel/redis/RedisPluginRepository.kt b/keel-redis/src/main/kotlin/com/netflix/spinnaker/keel/redis/RedisPluginRepository.kt index ede9a8d202..e53f4385dc 100644 --- a/keel-redis/src/main/kotlin/com/netflix/spinnaker/keel/redis/RedisPluginRepository.kt +++ b/keel-redis/src/main/kotlin/com/netflix/spinnaker/keel/redis/RedisPluginRepository.kt @@ -1,17 +1,36 @@ +/* + * Copyright 2018 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.netflix.spinnaker.keel.redis import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.module.kotlin.KotlinModule import com.fasterxml.jackson.module.kotlin.readValue -import com.netflix.spinnaker.keel.api.TypeMetadata +import com.netflix.spinnaker.keel.registry.AssetType import com.netflix.spinnaker.keel.registry.PluginAddress import com.netflix.spinnaker.keel.registry.PluginRepository +import org.slf4j.LoggerFactory import org.springframework.stereotype.Component import redis.clients.jedis.JedisPool +import javax.annotation.PostConstruct @Component class RedisPluginRepository(private val redisPool: JedisPool) : PluginRepository { + private val log by lazy { LoggerFactory.getLogger(javaClass) } + private val objectMapper = ObjectMapper() .apply { registerModule(KotlinModule()) } @@ -28,21 +47,36 @@ class RedisPluginRepository(private val redisPool: JedisPool) : PluginRepository } } - override fun assetPluginFor(type: TypeMetadata): PluginAddress? = + override fun assetPluginFor(type: AssetType): PluginAddress? = redisPool.resource.use { redis -> redis.hget("keel.plugins.asset", type.serialized) ?.let { objectMapper.readValue(it) } } - override fun addAssetPluginFor(type: TypeMetadata, address: PluginAddress) { + override fun addAssetPluginFor(type: AssetType, address: PluginAddress) { redisPool.resource.use { redis -> redis.hset("keel.plugins.asset", type.serialized, address.serialized) } } - private val TypeMetadata.serialized: String - get() = objectMapper.writeValueAsString(mapOf("kind" to kind, "apiVersion" to apiVersion)) + @PostConstruct + fun logKnownPlugins() { + redisPool.resource.use { redis -> + redis + .smembers("keel.plugins.veto") + .map { objectMapper.readValue(it) } + .forEach { log.info("Veto plugin at {}", it) } + redis + .hgetAll("keel.plugins.asset") + .map { (type, address) -> + with(objectMapper) { + readValue(type) to readValue(address) + } + } + .forEach { log.info("Asset plugin for {} at {}", it.first, it.second) } + } + } - private val PluginAddress.serialized: String + private val Any.serialized: String get() = objectMapper.writeValueAsString(this) } diff --git a/keel-rule-engine-tck/src/main/kotlin/com/netflix/spinnaker/keel/registry/PluginRepositoryTests.kt b/keel-rule-engine-tck/src/main/kotlin/com/netflix/spinnaker/keel/registry/PluginRepositoryTests.kt index b944c30cfe..0eab1971bd 100644 --- a/keel-rule-engine-tck/src/main/kotlin/com/netflix/spinnaker/keel/registry/PluginRepositoryTests.kt +++ b/keel-rule-engine-tck/src/main/kotlin/com/netflix/spinnaker/keel/registry/PluginRepositoryTests.kt @@ -1,6 +1,20 @@ +/* + * Copyright 2018 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.netflix.spinnaker.keel.registry -import com.netflix.spinnaker.keel.api.TypeMetadata import org.jetbrains.spek.api.Spek import org.jetbrains.spek.api.dsl.given import org.jetbrains.spek.api.dsl.it @@ -18,14 +32,14 @@ abstract class PluginRepositoryTests( val subject = factory() - val securityGroup = TypeMetadata.newBuilder().apply { + val securityGroup = AssetType( + kind = "aws:SecurityGroup", apiVersion = "1.0" - kind = "aws:SecurityGroup" - }.build() - val loadBalancer = TypeMetadata.newBuilder().apply { + ) + val loadBalancer = AssetType( + kind = "aws:LoadBalancer", apiVersion = "1.0" - kind = "aws:LoadBalancer" - }.build() + ) given("no plugins are stored") { it("returns null from assetPluginsFor") { diff --git a/keel-rule-engine/src/main/kotlin/com/netflix/spinnaker/keel/grpc/GrpcPluginRegistry.kt b/keel-rule-engine/src/main/kotlin/com/netflix/spinnaker/keel/grpc/GrpcPluginRegistry.kt index 81b882c635..edeb71dd84 100644 --- a/keel-rule-engine/src/main/kotlin/com/netflix/spinnaker/keel/grpc/GrpcPluginRegistry.kt +++ b/keel-rule-engine/src/main/kotlin/com/netflix/spinnaker/keel/grpc/GrpcPluginRegistry.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.netflix.spinnaker.keel.grpc import com.netflix.discovery.EurekaClient @@ -10,6 +25,7 @@ import com.netflix.spinnaker.keel.api.engine.RegisterVetoPluginRequest import com.netflix.spinnaker.keel.api.engine.RegisterVetoPluginResponse import com.netflix.spinnaker.keel.api.plugin.AssetPluginGrpc import com.netflix.spinnaker.keel.platform.NoSuchVip +import com.netflix.spinnaker.keel.registry.AssetType import com.netflix.spinnaker.keel.registry.PluginAddress import com.netflix.spinnaker.keel.registry.PluginRepository import io.grpc.ManagedChannel @@ -29,7 +45,7 @@ class GrpcPluginRegistry( fun pluginFor(type: TypeMetadata): AssetPluginGrpc.AssetPluginBlockingStub? = pluginRepository - .assetPluginFor(type) + .assetPluginFor(AssetType(type.kind, type.apiVersion)) ?.let { (vip, port) -> stubFor(vip, port, AssetPluginGrpc::newBlockingStub) } @@ -47,7 +63,10 @@ class GrpcPluginRegistry( request .typesList .forEach { type -> - pluginRepository.addAssetPluginFor(type, PluginAddress(request.vip, request.port)) + pluginRepository.addAssetPluginFor( + AssetType(type.kind, type.apiVersion), + PluginAddress(request.vip, request.port) + ) log.info("Registered asset plugin supporting {} at vip: {} port: {}", type, request.vip, request.port) } responseObserver.apply { diff --git a/keel-rule-engine/src/main/kotlin/com/netflix/spinnaker/keel/registry/AssetType.kt b/keel-rule-engine/src/main/kotlin/com/netflix/spinnaker/keel/registry/AssetType.kt new file mode 100644 index 0000000000..6c18b2bf13 --- /dev/null +++ b/keel-rule-engine/src/main/kotlin/com/netflix/spinnaker/keel/registry/AssetType.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2018 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.netflix.spinnaker.keel.registry + +data class AssetType(val kind: String, val apiVersion: String) diff --git a/keel-rule-engine/src/main/kotlin/com/netflix/spinnaker/keel/registry/InMemoryPluginRepository.kt b/keel-rule-engine/src/main/kotlin/com/netflix/spinnaker/keel/registry/InMemoryPluginRepository.kt index 93e73741b5..a0254b9599 100644 --- a/keel-rule-engine/src/main/kotlin/com/netflix/spinnaker/keel/registry/InMemoryPluginRepository.kt +++ b/keel-rule-engine/src/main/kotlin/com/netflix/spinnaker/keel/registry/InMemoryPluginRepository.kt @@ -1,6 +1,20 @@ +/* + * Copyright 2018 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.netflix.spinnaker.keel.registry -import com.netflix.spinnaker.keel.api.TypeMetadata import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.stereotype.Component @@ -8,7 +22,7 @@ import org.springframework.stereotype.Component @ConditionalOnMissingBean(PluginRepository::class) class InMemoryPluginRepository : PluginRepository { - private val assetPlugins: MutableMap = mutableMapOf() + private val assetPlugins: MutableMap = mutableMapOf() private val vetoPlugins: MutableSet = mutableSetOf() override fun vetoPlugins(): Iterable = vetoPlugins @@ -17,10 +31,10 @@ class InMemoryPluginRepository : PluginRepository { vetoPlugins.add(address) } - override fun assetPluginFor(type: TypeMetadata): PluginAddress? = + override fun assetPluginFor(type: AssetType): PluginAddress? = assetPlugins[type] - override fun addAssetPluginFor(type: TypeMetadata, address: PluginAddress) { + override fun addAssetPluginFor(type: AssetType, address: PluginAddress) { assetPlugins[type] = address } } diff --git a/keel-rule-engine/src/main/kotlin/com/netflix/spinnaker/keel/registry/PluginAddress.kt b/keel-rule-engine/src/main/kotlin/com/netflix/spinnaker/keel/registry/PluginAddress.kt index 70a10c3c64..26fc0f2572 100644 --- a/keel-rule-engine/src/main/kotlin/com/netflix/spinnaker/keel/registry/PluginAddress.kt +++ b/keel-rule-engine/src/main/kotlin/com/netflix/spinnaker/keel/registry/PluginAddress.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2018 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.netflix.spinnaker.keel.registry data class PluginAddress( diff --git a/keel-rule-engine/src/main/kotlin/com/netflix/spinnaker/keel/registry/PluginRepository.kt b/keel-rule-engine/src/main/kotlin/com/netflix/spinnaker/keel/registry/PluginRepository.kt index 4c800f8278..524a4da738 100644 --- a/keel-rule-engine/src/main/kotlin/com/netflix/spinnaker/keel/registry/PluginRepository.kt +++ b/keel-rule-engine/src/main/kotlin/com/netflix/spinnaker/keel/registry/PluginRepository.kt @@ -1,13 +1,26 @@ +/* + * Copyright 2018 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.netflix.spinnaker.keel.registry -import com.netflix.spinnaker.keel.api.TypeMetadata - interface PluginRepository { fun vetoPlugins(): Iterable fun addVetoPlugin(address: PluginAddress) - fun assetPluginFor(type: TypeMetadata): PluginAddress? // TODO: don't expose gRPC type here + fun assetPluginFor(type: AssetType): PluginAddress? - fun addAssetPluginFor(type: TypeMetadata, address: PluginAddress) + fun addAssetPluginFor(type: AssetType, address: PluginAddress) }