Skip to content

Commit b2e424d

Browse files
committed
updated with working beans and better docs
1 parent c593c12 commit b2e424d

File tree

9 files changed

+83
-85
lines changed

9 files changed

+83
-85
lines changed

README.md

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,26 @@
1-
This plugin exercises the Spring capabilities of Spinnaker plugins. There are no PF4J extension points. Instead everything is Spring components.
2-
It tests the following cases:
3-
* plugin components are wired together
4-
* app components are wired into plugin
5-
* plugin components are wired into app
6-
* configuration and properties are recognized
1+
This plugin exercises the Spring capabilities of Spinnaker plugins. There are no PF4J extension points or dependencies. Instead everything is Spring components.
72

8-
Just build with `./gradlew build` and copy that zip under `/build` into the plugins location of your service (by default the `/plugins` directory under your service root.
3+
It tests the following cases and all of it works without having to use Kork plugin's "unsafe" mode:
4+
* new plugin beans are wired together
5+
* app beans are autowired into plugin beans
6+
* plugin beans are autowired into the app beans and replace app beans if primary (this allows modifying existing spinnaker behavior)
7+
* properties are recognized
8+
* controllers add new endpoints
9+
* new dependencies that are not in Spinnaker can be used in your plugin beans
10+
11+
Some things that don't work:
12+
* the Configuration annotation won't be recognized in a plugin bean so you can't create beans that way
13+
* class path scanning your plugin
14+
* the Conditional annotation won't be recognized in a plugin bean
15+
* Comnponent and Primary annotations aren't recognized, but that functionality still exists
16+
17+
Your plugin needs to extend PrivilegedSpringPlugin and implement registerBeanDefinitions(BeanDefinitionRegistry) to explicitly create and register BeanDefinitions. There are helper methods to make this easier and they default to singleton scope with constructor autowiring. See SpringExamplePlugin for an example.
18+
19+
We will probably need was way for registerBeanDefinitions(BeanDefinitionRegistry) to conditionally load beans based on the service that it is used in. I didn't see a good way to do that. It would be possible to cast BeanDefinitionRegistry to DefaultListableBeanFactory and look at the serializationId, but that relies on some implementation details.
20+
21+
A new release for Kork and updating that dependency is required. This had been tested against a branch of Kork locally withg the required changes.
22+
23+
Build with `./gradlew build` and copy that zip under `/build` into the plugins location of your service (by default the `/plugins` directory under your service root.
924

1025
The following should be added to your service yml config.
1126
```
@@ -16,7 +31,6 @@ spinnaker:
1631
enabled: true
1732
1833
newproperties:
19-
enabled: true
2034
test: 'test1'
2135
```
2236

build.gradle

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,24 @@ repositories {
1616
mavenLocal()
1717
mavenCentral()
1818
jcenter()
19+
maven{
20+
url "https://jitpack.io"
21+
}
1922
}
2023

2124
dependencies {
2225
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
23-
compile group: 'org.springframework', name: 'spring-context', version: '5.2.1.RELEASE'
26+
compileOnly (group: 'org.springframework', name: 'spring-context', version: '5.2.1.RELEASE')
2427
compileOnly (group: 'com.netflix.spinnaker.kork', name: 'kork-plugins-api', version: '7.3.0')
2528
compileOnly (group: 'com.netflix.spinnaker.kork', name: 'kork-plugins-spring-api', version: '7.3.0')
2629
compileOnly (group: 'org.springframework', name: 'spring-web', version: '5.2.2.RELEASE')
2730
compileOnly (group: 'com.netflix.spinnaker.orca', name: 'orca-core', version: '7.70.0') {
2831
exclude group: "org.slf4j"
2932
}
33+
compile("com.github.canal-pipelines:canal:v0.1.1") {
34+
exclude group: "org.slf4j"
35+
exclude group: "com.netflix.spinnaker.orca"
36+
}
3037
implementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.28'
3138

3239
testImplementation "org.junit.jupiter:junit-jupiter-api:5.3.2"

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ pf4jVersion=3.2.0
55
pluginId=Armory.SpringExamplePlugin
66
pluginClass=com.armory.plugin.example.spring.SpringExamplePlugin
77
pluginProvider=Clay McCoy
8-
pluginUnsafe=true
8+
pluginUnsafe=false

src/main/kotlin/com/armory/plugin/example/spring/NewConfiguration.kt

Lines changed: 0 additions & 26 deletions
This file was deleted.
Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package com.armory.plugin.example.spring
22

3+
import io.pivotal.canal.model.Pipelines
34
import org.springframework.web.bind.annotation.GetMapping
5+
import org.springframework.web.bind.annotation.RequestMapping
46
import org.springframework.web.bind.annotation.RestController
57

6-
@RestController("/new/service")
8+
@RestController()
9+
@RequestMapping("/new/service")
710
class NewController(private val newService: NewService) {
811

912
@GetMapping("/expressionFunctionNames")
@@ -16,13 +19,14 @@ class NewController(private val newService: NewService) {
1619
return newService.test()
1720
}
1821

19-
@GetMapping("/config")
20-
fun config(): NewConfiguration {
21-
return newService.config()
22+
@GetMapping("/properties")
23+
fun properties(): NewProperties {
24+
return newService.properties()
2225
}
2326

24-
@GetMapping("/configBean")
25-
fun configBean(): NewConfigurationBean {
26-
return newService.configBean()
27+
@GetMapping("/pipelines")
28+
fun pipelines(): Pipelines {
29+
return newService.pipelines()
2730
}
31+
2832
}

src/main/kotlin/com/armory/plugin/example/spring/NewProperties.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ import org.springframework.boot.context.properties.ConfigurationProperties
55
@ConfigurationProperties("newproperties")
66
data class NewProperties(
77
var test: String? = null
8-
)
8+
)
Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,39 @@
11
package com.armory.plugin.example.spring
22

33
import com.netflix.spinnaker.orca.capabilities.CapabilitiesService
4-
import org.springframework.beans.factory.annotation.Autowired
5-
import org.springframework.stereotype.Component
64

7-
@Component
8-
class NewService {
5+
import io.pivotal.canal.extensions.nestedstages.stages
6+
import io.pivotal.canal.extensions.pipelines
7+
import io.pivotal.canal.model.Pipelines
8+
import io.pivotal.canal.model.Wait
99

10-
@Autowired
11-
internal var capabilitiesService: CapabilitiesService? = null
12-
13-
@Autowired
14-
internal var newConfiguration: NewConfiguration? = null
15-
16-
@Autowired
17-
internal var newConfigurationBean: NewConfigurationBean? = null
10+
class NewService(val capabilitiesService: CapabilitiesService,
11+
val newProperties: NewProperties
12+
) {
1813

1914
fun expressionFunctionNames(): Collection<String> {
20-
return capabilitiesService!!.getExpressionCapabilities().functions.map{it.name}
15+
return capabilitiesService.getExpressionCapabilities().functions.map{it.name}
2116
}
2217

2318
fun test(): Collection<String> {
2419
return listOf("new service", "works")
2520
}
2621

27-
fun config(): NewConfiguration {
28-
return newConfiguration!!
22+
fun properties(): NewProperties {
23+
return newProperties
2924
}
3025

31-
fun configBean(): NewConfigurationBean {
32-
return newConfigurationBean!!
26+
// uses 3rd party library that is not in Spinnaker
27+
fun pipelines(): Pipelines {
28+
return pipelines {
29+
app("app1") {
30+
pipeline("just waiting") {
31+
stages = stages {
32+
stage(Wait(420))
33+
}
34+
}
35+
}
36+
}
3337
}
3438

35-
}
39+
}

src/main/kotlin/com/armory/plugin/example/spring/OverrideService.kt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@ import com.netflix.spinnaker.kork.expressions.ExpressionFunctionProvider
44
import com.netflix.spinnaker.orca.capabilities.CapabilitiesService
55
import com.netflix.spinnaker.orca.capabilities.models.ExpressionCapabilityResult
66
import org.pf4j.PluginManager
7-
import org.springframework.context.annotation.Primary
8-
import org.springframework.stereotype.Component
97

10-
@Component
11-
@Primary
12-
class OverrideService(expressionFunctionProviders: MutableList<ExpressionFunctionProvider>?, pluginManager: PluginManager?) : CapabilitiesService(expressionFunctionProviders, pluginManager) {
8+
class OverrideService(
9+
expressionFunctionProviders: MutableList<ExpressionFunctionProvider>?,
10+
pluginManager: PluginManager?) : CapabilitiesService(expressionFunctionProviders,
11+
pluginManager) {
1312

1413
override fun getExpressionCapabilities() : ExpressionCapabilityResult {
1514
val result = ExpressionCapabilityResult()

src/main/kotlin/com/armory/plugin/example/spring/SpringExamplePlugin.kt

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,21 @@
11
package com.armory.plugin.example.spring
22

3-
import com.netflix.spinnaker.kork.plugins.api.spring.SpringPlugin
3+
import com.netflix.spinnaker.kork.plugins.api.spring.PrivilegedSpringPlugin
44
import org.slf4j.LoggerFactory
55
import org.pf4j.PluginWrapper
6-
7-
8-
class SpringExamplePlugin(wrapper: PluginWrapper) : SpringPlugin(wrapper) {
9-
override fun initApplicationContext() {
10-
applicationContext.applicationName
11-
logger.info("***** App name ${applicationContext.applicationName}")
12-
logger.info(applicationContext.environment.toString())
13-
logger.info(applicationContext.beanDefinitionNames.joinToString())
14-
15-
applicationContext.register(NewConfiguration::class.java)
16-
applicationContext.register(NewConfigurationBean::class.java)
17-
applicationContext.register(NewProperties::class.java)
18-
applicationContext.register(NewService::class.java)
19-
applicationContext.register(NewController::class.java)
20-
applicationContext.register(OverrideService::class.java)
21-
22-
logger.info(applicationContext.beanDefinitionNames.joinToString())
6+
import org.springframework.beans.factory.support.BeanDefinitionRegistry
7+
8+
class SpringExamplePlugin(wrapper: PluginWrapper) : PrivilegedSpringPlugin(wrapper) {
9+
10+
override fun registerBeanDefinitions(registry: BeanDefinitionRegistry) {
11+
listOf(
12+
beanDefinitionFor(NewService::class.java),
13+
beanDefinitionFor(NewProperties::class.java),
14+
beanDefinitionFor(NewController::class.java),
15+
primaryBeanDefinitionFor(OverrideService::class.java)
16+
).forEach {
17+
registerBean(it, registry)
18+
}
2319
}
2420

2521
private val logger = LoggerFactory.getLogger(SpringExamplePlugin::class.java)

0 commit comments

Comments
 (0)