Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(plugin): plugin-loader #325

Merged
merged 6 commits into from
Jul 22, 2019
Merged

Conversation

link108
Copy link
Member

@link108 link108 commented Jun 25, 2019

This PR is related to spinnaker/spinnaker#4181.
Spinnaker services can extend SpinnakerApplication and call its initialize() method to load plugins into the classpath prior to spring context initialization. When the plugins are initialized, they have access to spring configuration, so plugin configuration will be stored alongside the service configs.

I've captured some of my thoughts around the plugin loader here: https://docs.google.com/document/d/1KFDCIIC_abJMVczmcTqeb3XenNibFet5acN4bq9KD3k

Plugin RFC: https://docs.google.com/document/d/1-n5wGif28Glao_NLkSGlv5LzAeC_i1clntjMhJVfIQI

Copy link
Member

@robzienert robzienert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would like to see docs on these impl classes.


package com.netflix.spinnaker.kork.plugins.spring;

public class PluginLoaderException extends RuntimeException {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be using the base exceptions defined in kork-exceptions. For instance, I see this exception being used for both exceptional cases where the integration is at fault, as well as cases where the system itself is at fault. It would be good to differentiate.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you recommend using those exceptions or extending them? And when you say the integration is at fault, do you mean throw an IntegrationException in the case of malformed config file or throw an IntegrationException in the case of a plugin not having required config values?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The path forward is that we use these classes as base classes, extending them for the specific throw. For example, TitusException extends IntegrationException, and there's other exceptions that extend TitusException for specific throw scenarios.

There are 4 base exception classes; System, Integration, User and ConstraintViolation. For your question, probably one that is MalformedConfigurationException extends IntegrationException and another MissingRequiredConfigurationException extends IntegrationException or something. Does this make sense?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, added two new exception classes that inherit from IntegrationException, I named them slightly differently to reflect that they're plugin configuration exceptions.

@Data
@AllArgsConstructor
@NoArgsConstructor
public static class PluginConfiguration {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's your thoughts on plugin-specific configurations? Where do these go?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or rather... how do they get loaded? Is this up to the responsibility of something else?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Plugin specific configurations will be laid down with the rest of the service configs (eg via halyard) and are accessible during context initialization
Eg. in orca.yml, you can have

...
plugins:
  myStagePlugin:
    version: x.y.z
    configs: 
      foo: bar
      cat: dog

and then reference plugins.myStagePlugin.configs.foo in an init method (have tested this with the @PostConstruct annotation)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting. A couple things:

  1. myStagePlugin should probably be namespaced. Something like armory/myStagePlugin, so that Netflix could also have a myStagePlugin but not conflict.
  2. version being an embedded property seems... weird? Why is this part of an operator configuration? Shouldn't that information come from the Plugin manifest (e.g. compiled directly into the plugin)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the first item, I do agree, plugins should be namespaced. Are you suggesting we add validation for this? eg. enforce a / character in the plugin name?
Agree on 2, that will be part of the plugin manifest

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I missed this comment! Yes. Let's validate & enforce that convention.

import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

public class SpinnakerApplication extends SpringBootServletInitializer {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should have a SpinnakerApplicationSystemTest for this. Not only for validating that this works as desired, but also to show as an example of how this gets integrated into services.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This SystemTest should also have a really simple plugin that we can load and assert its outputs.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm planning on making a simple plugin jar and adding it to the repo, is that OK to do? Or are there alternatives you guys can think of?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems fine. I've never tried something like this before, we can always adjust in the future if we discover a better way of doing it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@robzienert I've updated with some more tests, mind taking a look? While it doesn't actually load a jar, it shows the classpath being updated after the call to initialize and shows an example of how it's used. I've been attempting to write a test for this that actually loads a jar, however its proven to be difficult.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fine for now! Thanks for putting those tests together - there's bigger fish to fry. Perhaps just plop a TODO comment on the class so we might be reminded to revisit someday. :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added this to the test class itself

throw new PluginLoaderException(e);
}
addJarsToClassPath(source);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

loadPlugins should definitely return a result object that outlines what plugins were loaded and what weren't (and for what reason). I'm sure there will be other pieces of metadata we'll want as well.

This information will be handy for outputting into startup logs and probably other things.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple ideas:

  • I can get a list of all plugins listed and then compare it to the list produced by the getEnabledJarURLs call (would convert to compare strings to strings), but it wouldn't include information about why a plugin wasn't loaded.
  • In getEnabledJarURLs, I could create a Map<String, String> that would be passed to getUrlFromPath and updated in case of an exception. I like this idea more since it would the exception message.

In either case, I'd like to fail the deployment, but I do agree, it would be good to have more info as to why it failed. This module is only concerned with updating the classpath, so we don't have access to what happens during the context initialization.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since we're just adding all enabled plugins to the classpath, I can just output the plugin properties info.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not just in failure, but also in the successful path. When loading a plugin, it should have a manifest such that we know the name of the plugin, maintainer, version, and whether the plugin is enabled or not (along with the loaded configuration). This stuff will be fairly critical for debugging when someone comes into Slack or somewhere else reporting errors.

.orElse(PluginLoader.DEFAULT_PLUGIN_CONFIG_PATH));
}

public void loadPlugins(Class source) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do we handle loading the right plugin if different versions exist in the source directory?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The plugins.yml is the absolute path of the jarfile(s) to load, not just a path to a directory. The plugins.yml file will contain only plugins relevant to the service.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As per the Plugins RFC, Plugin environment sandboxing is a non-goal. Please see: https://docs.google.com/document/d/1-n5wGif28Glao_NLkSGlv5LzAeC_i1clntjMhJVfIQI/edit#heading=h.pk2yupt9bm2v

}

private void addJarsToClassPath(Class source) {
Thread.currentThread()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this lead to conflicts if a class in the plugin happen to have a fully qualified name as an existing class?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vice versa if the defined plugin isn't found, the search would be delegated to the parent class loader (in this case the app class loader) which could reload the conflicting classes. (Perhaps this isn't a problem)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are working on creating a simple interface for plugins that plugin developers would have to implement, these plugins would be would need to be part of the com.netflix.spinnaker.plugin package. This reduces, but doesn't eliminate the possibility of problems, as two plugins could have the same fully qualified name. That being said, I don't see this as a problem right now.

import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

public class SpinnakerApplication extends SpringBootServletInitializer {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

@link108 link108 force-pushed the plugin-loader branch 2 times, most recently from 40e652d to c0ad27d Compare July 2, 2019 17:50
Copy link
Member

@robzienert robzienert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. I have some more tests I'd like added before merging:

  • What happens if...
    • two plugins load the same paths?
    • two plugins have the same name, but have different plugins?

public void loadPlugins(Class source) {
URL[] urls;
if (checkFileExists() == false) {
log.info("No plugin configuration file found, skipping loading plugins");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This reads a little weird.

"Not loading plugins: No plugin configuration file found: %s" where %s is the path searched.

/** @return true if a plugin is enabled */
private Predicate<PluginProperties.PluginConfiguration> isEnabled() {
return p -> p.enabled == true;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems odd to have broken a one-liner predicate out into a method which is only called once. 🤔

* @param pluginConfigurations
*/
private void logPlugins(List<PluginProperties.PluginConfiguration> pluginConfigurations) {
if (pluginConfigurations.size() > 0) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

!pluginConfigurations.isEmpty() is the preferential way to do this.

private void logPlugins(List<PluginProperties.PluginConfiguration> pluginConfigurations) {
if (pluginConfigurations.size() > 0) {
for (PluginProperties.PluginConfiguration pluginConfiguration : pluginConfigurations) {
log.info("Loading " + pluginConfiguration.toString());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can also do log.info("Loading {}", pluginConfiguration).

@Data
@AllArgsConstructor
@NoArgsConstructor
public static class PluginConfiguration {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I missed this comment! Yes. Let's validate & enforce that convention.

import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

public class SpinnakerApplication extends SpringBootServletInitializer {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fine for now! Thanks for putting those tests together - there's bigger fish to fry. Perhaps just plop a TODO comment on the class so we might be reminded to revisit someday. :)

* @param args The application arguments (usually passed from a Java main method)
*/
public static void initialize(Map<String, Object> defaultProps, Class source, String... args) {
PluginLoader pluginLoader = new PluginLoader();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment only: Herein lies scope creep - so it's just for conversation.

I'd like to allow overriding the PluginLoader; would be handy to create this class by name and pass in via env. My use case here is that some company may want to customize how jars are loaded (perhaps via an object store instead of local filesystem?). No need to build it until it's needed though, but wondering if this seems like a reasonable use case?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is that to say have PluginLoader be an interface? I have added a method to help with testing, where you can pass in a PluginLoader, but I believe you're talking about an interface, not a testing method. I think this is a reasonable use case, I'm going to have a PR up after this one is merged that enables spinnaker services to download the plugin jars, so that should help in the meantime.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, to have it be an interface. We don't need to deal with it for now. :)

@link108
Copy link
Member Author

link108 commented Jul 18, 2019

@ajordens and @cfieber this is ready to go, you guys are tagged as requested reviewers, can you guys take a look / merge?

@dacodas
Copy link

dacodas commented Aug 10, 2019

Does this require a file at /opt/spinnaker/plugins/plugin-1.2.3.jar? I get a failed test...

 ---> Running in 1c8c29e7bf45

Welcome to Gradle 5.5.1!

Here are the highlights of this release:
 - Kickstart Gradle plugin development with gradle init
 - Distribute organization-wide Gradle properties in custom Gradle distributions
 - Transform dependency artifacts on resolution

For more details see https://docs.gradle.org/5.5.1/release-notes.html

Starting a Gradle Daemon (subsequent builds will be faster)
> Task :assemble UP-TO-DATE
> Task :kork-artifacts:processResources NO-SOURCE
> Task :spotlessJava
> Task :spotlessJavaCheck
> Task :spotlessMisc
> Task :spotlessMiscCheck
> Task :spotlessCheck
> Task :check
> Task :build
> Task :kork-bom:assemble UP-TO-DATE
> Task :kork-bom:spotlessJava
> Task :kork-bom:spotlessJavaCheck
> Task :kork-bom:spotlessMisc
> Task :kork-bom:spotlessMiscCheck
> Task :kork-bom:spotlessCheck
> Task :kork-bom:check
> Task :kork-bom:build
> Task :kork-artifacts:spotlessJava
> Task :kork-artifacts:spotlessJavaCheck
> Task :kork-artifacts:spotlessMisc
> Task :kork-artifacts:spotlessMiscCheck
> Task :kork-artifacts:spotlessCheck
> Task :kork-artifacts:processTestResources NO-SOURCE
> Task :kork-core-tck:processResources NO-SOURCE
> Task :kork-core-tck:spotlessJava
> Task :kork-core-tck:spotlessJavaCheck
> Task :kork-core-tck:spotlessMisc
> Task :kork-core-tck:spotlessMiscCheck
> Task :kork-core-tck:spotlessCheck
> Task :kork-core-tck:processTestResources NO-SOURCE
> Task :kork-dynomite:processResources NO-SOURCE
> Task :kork-dynomite:spotlessJava
> Task :kork-dynomite:spotlessJavaCheck
> Task :kork-dynomite:spotlessMisc
> Task :kork-dynomite:spotlessMiscCheck
> Task :kork-dynomite:spotlessCheck
> Task :kork-dynomite:processTestResources NO-SOURCE
> Task :kork-jedis:processResources NO-SOURCE
> Task :kork-exceptions:compileJava
> Task :kork-exceptions:compileGroovy NO-SOURCE
> Task :kork-exceptions:processResources NO-SOURCE
> Task :kork-exceptions:classes
> Task :kork-exceptions:jar
> Task :kork-exceptions:assemble
> Task :kork-exceptions:spotlessJava
> Task :kork-exceptions:spotlessJavaCheck
> Task :kork-exceptions:spotlessMisc
> Task :kork-exceptions:spotlessMiscCheck
> Task :kork-exceptions:spotlessCheck
> Task :kork-exceptions:compileTestJava NO-SOURCE
> Task :kork-core:compileJava
> Task :kork-aws:compileJava
> Task :kork-config:compileJava
> Task :kork-exceptions:compileTestGroovy
> Task :kork-exceptions:processTestResources NO-SOURCE
> Task :kork-exceptions:testClasses

> Task :kork-core:compileJava
warning: unknown enum constant DataSourceType.GAUGE
  reason: class file for com.netflix.servo.annotations.DataSourceType not found
warning: unknown enum constant DataSourceType.GAUGE
warning: unknown enum constant DataSourceType.GAUGE
warning: unknown enum constant DataSourceType.GAUGE
  reason: class file for com.netflix.servo.annotations.DataSourceType not found
warning: unknown enum constant DataSourceType.GAUGE
warning: unknown enum constant DataSourceType.GAUGE
warning: unknown enum constant DataSourceType.GAUGE
  reason: class file for com.netflix.servo.annotations.DataSourceType not found
warning: unknown enum constant DataSourceType.GAUGE
warning: unknown enum constant DataSourceType.GAUGE
warning: unknown enum constant DataSourceType.GAUGE
  reason: class file for com.netflix.servo.annotations.DataSourceType not found
warning: unknown enum constant DataSourceType.GAUGE
warning: unknown enum constant DataSourceType.GAUGE
warning: unknown enum constant DataSourceType.GAUGE
  reason: class file for com.netflix.servo.annotations.DataSourceType not found
warning: unknown enum constant DataSourceType.GAUGE
warning: unknown enum constant DataSourceType.GAUGE
15 warnings

> Task :kork-exceptions:test
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.codehaus.groovy.vmplugin.v7.Java7$1 (file:/root/.gradle/caches/modules-2/files-2.1/org.codehaus.groovy/groovy/2.5.7/99907efe4b69f800c42584386f5d668e4d952bd5/groovy-2.5.7.jar) to constructor java.lang.invoke.MethodHandles$Lookup(java.lang.Class,int)
WARNING: Please consider reporting this to the maintainers of org.codehaus.groovy.vmplugin.v7.Java7$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

> Task :kork-core:compileGroovy NO-SOURCE
> Task :kork-core:processResources
> Task :kork-core:classes
> Task :kork-core:jar
> Task :kork-core:assemble
> Task :kork-core:spotlessJava
> Task :kork-core:spotlessJavaCheck
> Task :kork-core:spotlessMisc
> Task :kork-core:spotlessMiscCheck
> Task :kork-core:spotlessCheck
> Task :kork-config:processResources
> Task :kork-config:classes
> Task :kork-config:jar
> Task :kork-config:assemble
> Task :kork-artifacts:compileJava
> Task :kork-artifacts:compileGroovy NO-SOURCE
> Task :kork-artifacts:classes
> Task :kork-artifacts:jar
> Task :kork-artifacts:assemble
> Task :kork-artifacts:compileTestJava NO-SOURCE
> Task :kork-config:spotlessJava
> Task :kork-config:spotlessJavaCheck
> Task :kork-config:spotlessMisc
> Task :kork-config:spotlessMiscCheck
> Task :kork-config:spotlessCheck
> Task :kork-artifacts:compileTestGroovy
> Task :kork-artifacts:testClasses
> Task :kork-aws:compileGroovy
> Task :kork-aws:processResources NO-SOURCE
> Task :kork-aws:classes
> Task :kork-aws:jar
> Task :kork-core:compileTestJava
> Task :kork-aws:assemble
> Task :kork-aws:spotlessJava
> Task :kork-aws:spotlessJavaCheck
> Task :kork-aws:spotlessMisc
> Task :kork-aws:spotlessMiscCheck
> Task :kork-aws:spotlessCheck
> Task :kork-aws:compileTestJava NO-SOURCE
> Task :kork-core:compileTestGroovy
> Task :kork-core:processTestResources NO-SOURCE
> Task :kork-core:testClasses
> Task :kork-config:compileTestJava
> Task :kork-config:processTestResources NO-SOURCE
> Task :kork-config:testClasses
> Task :kork-aws:compileTestGroovy
> Task :kork-aws:processTestResources NO-SOURCE
> Task :kork-aws:testClasses
> Task :kork-config:test
> Task :kork-config:check
> Task :kork-config:build
> Task :kork-core-tck:compileJava NO-SOURCE
> Task :kork-core-tck:compileGroovy
> Task :kork-core-tck:classes

> Task :kork-aws:test
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.codehaus.groovy.vmplugin.v7.Java7$1 (file:/root/.gradle/caches/modules-2/files-2.1/org.codehaus.groovy/groovy/2.5.7/99907efe4b69f800c42584386f5d668e4d952bd5/groovy-2.5.7.jar) to constructor java.lang.invoke.MethodHandles$Lookup(java.lang.Class,int)
WARNING: Please consider reporting this to the maintainers of org.codehaus.groovy.vmplugin.v7.Java7$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

> Task :kork-core-tck:jar
> Task :kork-core-tck:assemble
> Task :kork-core-tck:compileTestJava NO-SOURCE
> Task :kork-core-tck:compileTestGroovy NO-SOURCE
> Task :kork-core-tck:testClasses UP-TO-DATE
> Task :kork-core-tck:test NO-SOURCE
> Task :kork-core-tck:check
> Task :kork-core-tck:build
> Task :kork-aws:check
> Task :kork-aws:build
> Task :kork-exceptions:check
> Task :kork-exceptions:build

> Task :kork-artifacts:test
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.codehaus.groovy.vmplugin.v7.Java7$1 (file:/root/.gradle/caches/modules-2/files-2.1/org.codehaus.groovy/groovy/2.5.7/99907efe4b69f800c42584386f5d668e4d952bd5/groovy-2.5.7.jar) to constructor java.lang.invoke.MethodHandles$Lookup(java.lang.Class,int)
WARNING: Please consider reporting this to the maintainers of org.codehaus.groovy.vmplugin.v7.Java7$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

> Task :kork-artifacts:check
> Task :kork-artifacts:build

> Task :kork-core:test
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.codehaus.groovy.vmplugin.v7.Java7$1 (file:/root/.gradle/caches/modules-2/files-2.1/org.codehaus.groovy/groovy/2.5.7/99907efe4b69f800c42584386f5d668e4d952bd5/groovy-2.5.7.jar) to constructor java.lang.invoke.MethodHandles$Lookup(java.lang.Class,int)
WARNING: Please consider reporting this to the maintainers of org.codehaus.groovy.vmplugin.v7.Java7$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

> Task :kork-core:check
> Task :kork-core:build

> Task :kork-jedis:compileJava
Note: /usr/local/src/kork/kork-jedis/src/main/java/com/netflix/spinnaker/kork/jedis/telemetry/InstrumentedJedisPool.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.

> Task :kork-jedis:compileGroovy NO-SOURCE
> Task :kork-jedis-test:compileJava
> Task :kork-jedis:classes
> Task :kork-jedis:jar
> Task :kork-jedis:assemble
> Task :kork-jedis:spotlessJava
> Task :kork-jedis:spotlessJavaCheck
> Task :kork-jedis:spotlessMisc
> Task :kork-jedis:spotlessMiscCheck
> Task :kork-jedis:spotlessCheck
> Task :kork-jedis:compileTestJava NO-SOURCE

> Task :kork-dynomite:compileJava
Note: /usr/local/src/kork/kork-dynomite/src/main/java/com/netflix/spinnaker/kork/dynomite/DynomiteClientFactory.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.

> Task :kork-dynomite:classes
> Task :kork-dynomite:jar
> Task :kork-dynomite:assemble
> Task :kork-dynomite:compileTestJava NO-SOURCE
> Task :kork-dynomite:testClasses UP-TO-DATE
> Task :kork-dynomite:test NO-SOURCE
> Task :kork-dynomite:check
> Task :kork-dynomite:build
> Task :kork-jedis-test:processResources NO-SOURCE
> Task :kork-jedis-test:classes
> Task :kork-jedis-test:jar
> Task :kork-jedis-test:assemble
> Task :kork-jedis-test:spotlessJava
> Task :kork-jedis-test:spotlessJavaCheck
> Task :kork-jedis-test:spotlessMisc
> Task :kork-jedis-test:spotlessMiscCheck
> Task :kork-jedis-test:spotlessCheck
> Task :kork-jedis-test:compileTestJava NO-SOURCE
> Task :kork-jedis-test:processTestResources NO-SOURCE
> Task :kork-jedis-test:testClasses UP-TO-DATE
> Task :kork-jedis-test:test NO-SOURCE
> Task :kork-jedis-test:check
> Task :kork-jedis-test:build
> Task :kork-hystrix:compileJava

> Task :kork-manageddelivery:compileJava
/usr/local/src/kork/kork-manageddelivery/src/main/java/com/netflix/spinnaker/kork/manageddelivery/model/ResourceEvent.java:51: warning: Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type.
  @Data
  ^
/usr/local/src/kork/kork-manageddelivery/src/main/java/com/netflix/spinnaker/kork/manageddelivery/model/ResourceEvent.java:56: warning: Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type.
  @Data
  ^
/usr/local/src/kork/kork-manageddelivery/src/main/java/com/netflix/spinnaker/kork/manageddelivery/model/ResourceEvent.java:64: warning: Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type.
  @Data
  ^
/usr/local/src/kork/kork-manageddelivery/src/main/java/com/netflix/spinnaker/kork/manageddelivery/model/ResourceEvent.java:73: warning: Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type.
  @Data
  ^
/usr/local/src/kork/kork-manageddelivery/src/main/java/com/netflix/spinnaker/kork/manageddelivery/model/ResourceEvent.java:83: warning: Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type.
  @Data
  ^
/usr/local/src/kork/kork-manageddelivery/src/main/java/com/netflix/spinnaker/kork/manageddelivery/model/ResourceEvent.java:96: warning: Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type.
  @Data
  ^
6 warnings

> Task :kork-manageddelivery:processResources NO-SOURCE
> Task :kork-manageddelivery:classes
> Task :kork-manageddelivery:jar
> Task :kork-manageddelivery:assemble
> Task :kork-manageddelivery:spotlessJava
> Task :kork-manageddelivery:spotlessJavaCheck
> Task :kork-manageddelivery:spotlessMisc
> Task :kork-manageddelivery:spotlessMiscCheck
> Task :kork-manageddelivery:spotlessCheck
> Task :kork-manageddelivery:compileTestJava NO-SOURCE
> Task :kork-manageddelivery:processTestResources NO-SOURCE
> Task :kork-manageddelivery:testClasses UP-TO-DATE
> Task :kork-manageddelivery:test NO-SOURCE
> Task :kork-manageddelivery:check
> Task :kork-manageddelivery:build
> Task :kork-plugins:compileJava
> Task :kork-plugins:compileGroovy NO-SOURCE
> Task :kork-plugins:processResources NO-SOURCE
> Task :kork-plugins:classes
> Task :kork-plugins:jar
> Task :kork-plugins:assemble
> Task :kork-plugins:spotlessJava
> Task :kork-plugins:spotlessJavaCheck
> Task :kork-plugins:spotlessMisc
> Task :kork-plugins:spotlessMiscCheck
> Task :kork-plugins:spotlessCheck
> Task :kork-jedis:compileTestGroovy
> Task :kork-jedis:processTestResources NO-SOURCE
> Task :kork-jedis:testClasses
> Task :kork-plugins:compileTestJava

> Task :kork-jedis:test
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.codehaus.groovy.vmplugin.v7.Java7$1 (file:/root/.gradle/caches/modules-2/files-2.1/org.codehaus.groovy/groovy/2.5.7/99907efe4b69f800c42584386f5d668e4d952bd5/groovy-2.5.7.jar) to constructor java.lang.invoke.MethodHandles$Lookup(java.lang.Class,int)
WARNING: Please consider reporting this to the maintainers of org.codehaus.groovy.vmplugin.v7.Java7$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

> Task :kork-hystrix:compileGroovy
> Task :kork-hystrix:processResources NO-SOURCE
> Task :kork-hystrix:classes
> Task :kork-hystrix:jar
> Task :kork-hystrix:assemble
> Task :kork-hystrix:spotlessJava
> Task :kork-hystrix:spotlessJavaCheck
> Task :kork-hystrix:spotlessMisc
> Task :kork-hystrix:spotlessMiscCheck
> Task :kork-hystrix:spotlessCheck
> Task :kork-hystrix:compileTestJava NO-SOURCE
> Task :kork-hystrix:compileTestGroovy
> Task :kork-hystrix:processTestResources NO-SOURCE
> Task :kork-hystrix:testClasses
> Task :kork-expressions:compileKotlin
> Task :kork-plugins:compileTestGroovy
> Task :kork-plugins:processTestResources
> Task :kork-plugins:testClasses
> Task :kork-jedis:check
> Task :kork-jedis:build

> Task :kork-expressions:compileJavaNote: /usr/local/src/kork/kork-expressions/src/main/java/com/netflix/spinnaker/kork/expressions/ExpressionTransform.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.


> Task :kork-expressions:processResources NO-SOURCE
> Task :kork-expressions:classes
> Task :kork-expressions:inspectClassesForKotlinIC
> Task :kork-expressions:jar
> Task :kork-expressions:assemble
> Task :kork-expressions:spotlessJava
> Task :kork-expressions:spotlessJavaCheck
WARNING: An illegal reflective access operation has occurred

> Task :kork-hystrix:test
WARNING: Illegal reflective access by org.codehaus.groovy.vmplugin.v7.Java7$1 (file:/root/.gradle/caches/modules-2/files-2.1/org.codehaus.groovy/groovy/2.5.7/99907efe4b69f800c42584386f5d668e4d952bd5/groovy-2.5.7.jar) to constructor java.lang.invoke.MethodHandles$Lookup(java.lang.Class,int)
WARNING: Please consider reporting this to the maintainers of org.codehaus.groovy.vmplugin.v7.Java7$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
Note: /usr/local/src/kork/kork-secrets/src/main/java/com/netflix/spinnaker/kork/secrets/engines/AbstractStorageSecretEngine.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

> Task :kork-secrets:compileJava

> Task :kork-secrets:compileGroovy NO-SOURCE
> Task :kork-secrets:processResources
> Task :kork-secrets:classes

> Task :kork-plugins:test

com.netflix.spinnaker.kork.plugins.spring.SpinnakerApplicationSystemTest > shouldRegisterSubtypesByClass FAILED
    java.lang.ClassCastException at SpinnakerApplicationSystemTest.java:35
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.codehaus.groovy.vmplugin.v7.Java7$1 (file:/root/.gradle/caches/modules-2/files-2.1/org.codehaus.groovy/groovy/2.5.7/99907efe4b69f800c42584386f5d668e4d952bd5/groovy-2.5.7.jar) to constructor java.lang.invoke.MethodHandles$Lookup(java.lang.Class,int)
WARNING: Please consider reporting this to the maintainers of org.codehaus.groovy.vmplugin.v7.Java7$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

> Task :kork-secrets:jar
> Task :kork-secrets:assemble
> Task :kork-hystrix:check
> Task :kork-hystrix:build
> Task :kork-secrets:spotlessJava
> Task :kork-secrets:spotlessJavaCheck
> Task :kork-secrets:spotlessMisc
> Task :kork-secrets:spotlessMiscCheck
> Task :kork-secrets:spotlessCheck

5 tests completed, 1 failed

> Task :kork-plugins:test FAILED

> Task :kork-secrets:compileTestJava
> Task :kork-secrets-aws:compileJava
> Task :kork-expressions:spotlessKotlin

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':kork-plugins:test'.
> There were failing tests. See the report at: file:///usr/local/src/kork/kork-plugins/build/reports/tests/test/index.html

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 2m 14s
88 actionable tasks: 88 executed
The command '/bin/sh -c gradle build' returned a non-zero code: 1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants