Merge remote-tracking branch 'upstream/master' into issue-108-code-cleanup
Conflicts: src/cucumber/groovy/deploydb/cucumber/StubAppRunner.groovy src/cucumber/groovy/step_definitions/FlowSteps.groovy src/cucumber/groovy/step_definitions/WebhookSteps.groovy src/main/groovy/deploydb/WorkFlow.groovy
This commit is contained in:
commit
a22015d6e8
File diff suppressed because it is too large
Load Diff
|
@ -6,7 +6,7 @@ Feature: DeployDB config APIs
|
|||
|
||||
Scenario: When the system is idle, reloading the shall succeed
|
||||
|
||||
Given DeployDb configuration directory path is "./example/modelConfig"
|
||||
Given Models configuration directory path is "./example/modelConfig"
|
||||
When I POST to "/tasks/configReload" from the admin app
|
||||
Then the response should be 200
|
||||
And the response body should be:
|
||||
|
@ -15,15 +15,82 @@ Feature: DeployDB config APIs
|
|||
"""
|
||||
|
||||
|
||||
Scenario: If deployments are NOT verified i.e. are in progress, then attempt to reload
|
||||
config should fail. A deployment is considered as in progress, if the status
|
||||
is NOT SUCCESS or FAILED
|
||||
Scenario: If deployments are in progress, then attempt to reload config should succeed.
|
||||
A deployment is considered as in progress (aka NOT verified), if the status
|
||||
does not have value of SUCCESS or FAILED
|
||||
|
||||
Given there is a deployment
|
||||
And Models configuration directory path is "./example/modelConfig"
|
||||
When I POST to "/tasks/configReload" from the admin app
|
||||
Then the response should be 200
|
||||
And the response body should be:
|
||||
"""
|
||||
Failed: Configuration reload is not allowed while deployments are in progress
|
||||
Done!
|
||||
"""
|
||||
|
||||
|
||||
@freezetime
|
||||
Scenario: After config reload, transitions of in-progress deployments should use old config.
|
||||
If a deployment is in CREATED state and configuration is reloaded, then
|
||||
a deployment update of STARTED state should invoke set of global webhook
|
||||
and environment webhook, as specified by the older config
|
||||
Given a deployment webhook "started" configuration:
|
||||
"""
|
||||
deployment:
|
||||
started:
|
||||
- http://localhost:10000/job/old-notify-deployment-started/build
|
||||
"""
|
||||
And an deployment environment webhook "started" configuration named "pre-prod":
|
||||
"""
|
||||
description: "DeployDB Primary Integration"
|
||||
webhook:
|
||||
deployment:
|
||||
started:
|
||||
- http://localhost:10000/job/another-old-notify-deployment-started/build
|
||||
"""
|
||||
And there is a deployment in "CREATED" state
|
||||
And Models configuration is reloaded from directory path "./example/modelConfig"
|
||||
When I PATCH "/api/deployments/1" with:
|
||||
"""
|
||||
{
|
||||
"status" : "STARTED"
|
||||
}
|
||||
"""
|
||||
Then the webhook 1 should be invoked with the JSON:
|
||||
"""
|
||||
{
|
||||
"id" : 1,
|
||||
"artifact" : {
|
||||
"id" : 1,
|
||||
"group" : "com.example.cucumber",
|
||||
"name" : "cucumber-artifact",
|
||||
"version" : "1.0.1",
|
||||
"sourceUrl" : "http://example.com/maven/com.example.cucumber/cucumber-artifact/1.0.1/cucumber-artifact-1.0.1.jar",
|
||||
"createdAt" : "{{created_timestamp}}"
|
||||
},
|
||||
"status" : "STARTED",
|
||||
"service" : "faas",
|
||||
"environment" : "pre-prod",
|
||||
"createdAt" : "{{created_timestamp}}"
|
||||
}
|
||||
"""
|
||||
And the webhook 2 should be invoked with the JSON:
|
||||
"""
|
||||
{
|
||||
"id" : 1,
|
||||
"artifact" : {
|
||||
"id" : 1,
|
||||
"group" : "com.example.cucumber",
|
||||
"name" : "cucumber-artifact",
|
||||
"version" : "1.0.1",
|
||||
"sourceUrl" : "http://example.com/maven/com.example.cucumber/cucumber-artifact/1.0.1/cucumber-artifact-1.0.1.jar",
|
||||
"createdAt" : "{{created_timestamp}}"
|
||||
},
|
||||
"status" : "STARTED",
|
||||
"service" : "faas",
|
||||
"environment" : "pre-prod",
|
||||
"createdAt" : "{{created_timestamp}}"
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ class AppHelper {
|
|||
* @param c (required) Closure to execute
|
||||
*/
|
||||
void withServiceRegistry(Closure c) {
|
||||
c.call(this.runner.serviceRegistry)
|
||||
c.call(this.runner.workFlow.serviceRegistry)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -61,7 +61,7 @@ class AppHelper {
|
|||
* @param c (required) Closure to execute
|
||||
*/
|
||||
void withEnvironmentRegistry(Closure c) {
|
||||
c.call(this.runner.environmentRegistry)
|
||||
c.call(this.runner.workFlow.environmentRegistry)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -70,7 +70,7 @@ class AppHelper {
|
|||
* @param c (required) Closure to execute
|
||||
*/
|
||||
void withPromotionRegistry(Closure c) {
|
||||
c.call(this.runner.promotionRegistry)
|
||||
c.call(this.runner.workFlow.promotionRegistry)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -79,7 +79,16 @@ class AppHelper {
|
|||
* @param c (required) Closure to execute
|
||||
*/
|
||||
void withPipelineRegistry(Closure c) {
|
||||
c.call(this.runner.pipelineRegistry)
|
||||
c.call(this.runner.workFlow.pipelineRegistry)
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the {@link Closure} with a proper WorkFlow object
|
||||
*
|
||||
* @param c (required) Closure to execute
|
||||
*/
|
||||
void withWorkFlow(Closure c) {
|
||||
c.call(this.runner.workFlow)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -87,9 +96,8 @@ class AppHelper {
|
|||
*
|
||||
* @param c (required) Closure to execute
|
||||
*/
|
||||
void withWebhookManager(Closure c) {
|
||||
c.call(this.runner.webhookManager,
|
||||
this.webhookRunner.getApplication().requestWebhookObject)
|
||||
void withTestWebhookServer(Closure c) {
|
||||
c.call(this.webhookRunner.getApplication().requestWebhookObject)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,27 +1,23 @@
|
|||
package deploydb.cucumber
|
||||
|
||||
import com.google.common.base.Strings
|
||||
import com.google.common.collect.ImmutableMap
|
||||
import deploydb.WebhookManager
|
||||
import deploydb.WorkFlow
|
||||
import io.dropwizard.Application
|
||||
import io.dropwizard.Configuration
|
||||
import io.dropwizard.cli.ServerCommand
|
||||
|
||||
import io.dropwizard.lifecycle.ServerLifecycleListener
|
||||
import io.dropwizard.setup.Bootstrap
|
||||
import io.dropwizard.setup.Environment
|
||||
import io.dropwizard.testing.ConfigOverride
|
||||
|
||||
import com.google.common.base.Strings
|
||||
import com.google.common.collect.ImmutableMap
|
||||
import javax.annotation.Nullable
|
||||
import net.sourceforge.argparse4j.inf.Namespace
|
||||
import org.eclipse.jetty.server.Server
|
||||
import org.eclipse.jetty.server.ServerConnector
|
||||
import org.flywaydb.core.Flyway
|
||||
import org.hibernate.SessionFactory
|
||||
|
||||
import javax.annotation.Nullable
|
||||
|
||||
import deploydb.registry.ModelRegistry
|
||||
|
||||
/**
|
||||
* Class for running the Dropwizard app
|
||||
*
|
||||
|
@ -37,10 +33,7 @@ public class StubAppRunner<C extends Configuration> {
|
|||
private Environment environment
|
||||
private Server jettyServer
|
||||
private SessionFactory sessionFactory
|
||||
private ModelRegistry<deploydb.models.Service> serviceRegistry
|
||||
private ModelRegistry<deploydb.models.Environment> environmentRegistry
|
||||
private ModelRegistry<deploydb.models.Promotion> promotionRegistry
|
||||
private ModelRegistry<deploydb.models.pipeline.Pipeline> pipelineRegistry
|
||||
private WorkFlow workFlow
|
||||
private WebhookManager webhookManager
|
||||
|
||||
public StubAppRunner(Class<? extends Application<C>> applicationClass,
|
||||
|
@ -88,12 +81,14 @@ public class StubAppRunner<C extends Configuration> {
|
|||
webhookManager = application.webhooksManager
|
||||
|
||||
/**
|
||||
* Get a ModelRegistry(s) from the application once it's up and running
|
||||
* Save workflow object
|
||||
*/
|
||||
serviceRegistry = application.workFlow.serviceRegistry
|
||||
environmentRegistry = application.workFlow.environmentRegistry
|
||||
promotionRegistry = application.workFlow.promotionRegistry
|
||||
pipelineRegistry = application.workFlow.pipelineRegistry
|
||||
workFlow = application.workFlow
|
||||
|
||||
/**
|
||||
* Setup config checksum for tests
|
||||
*/
|
||||
application.configChecksum = "0xdead"
|
||||
|
||||
/* We're running the DB migrations here to make sure we're running
|
||||
* them in the same classloader environment as the DeployDB
|
||||
|
@ -101,7 +96,7 @@ public class StubAppRunner<C extends Configuration> {
|
|||
* DeployDB won't be able to "see" the in-memory DB
|
||||
*/
|
||||
Flyway flyway = configuration.flyway.build(
|
||||
configuration.database.build(metricRegistry, "Flyway"));
|
||||
configuration.database.build(metricRegistry, "Flyway"))
|
||||
flyway.clean()
|
||||
flyway.migrate()
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ Given(~/^there is a deployment$/) { ->
|
|||
d1.addPromotionResult(p1)
|
||||
|
||||
/* Create a flow */
|
||||
Flow f = new Flow(a1, "faas")
|
||||
Flow f = new Flow(a1, "faas", "0xdead")
|
||||
f.addDeployment(d1)
|
||||
|
||||
/**
|
||||
|
@ -130,7 +130,7 @@ And(~/there is a deployment in "(.*?)" state$/) { String deploymentState ->
|
|||
d1.addPromotionResult(p1)
|
||||
|
||||
/* Create a flow */
|
||||
Flow f = new Flow(a1, "faas")
|
||||
Flow f = new Flow(a1, "faas", "0xdead")
|
||||
f.addDeployment(d1)
|
||||
|
||||
/**
|
||||
|
@ -139,4 +139,4 @@ And(~/there is a deployment in "(.*?)" state$/) { String deploymentState ->
|
|||
FlowDAO fdao = new FlowDAO(sessionFactory)
|
||||
fdao.persist(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,4 +18,4 @@ Given(~/^an environment is configured$/) { ->
|
|||
Environment a = sampleEnvironment1()
|
||||
environmentRegistry.put(a.ident, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,9 +20,7 @@ Given(~/^there is a flow$/) { ->
|
|||
Deployment d = sampleDeployment(adao.persist(a), "pre-production", Status.STARTED)
|
||||
Deployment d1 = sampleDeployment(adao.persist(a), "production", Status.STARTED)
|
||||
|
||||
Flow f = new Flow()
|
||||
f.setArtifact(a)
|
||||
f.setService("faas")
|
||||
Flow f = new Flow(a, "faas", "0xdead")
|
||||
d.setFlow(f)
|
||||
d1.setFlow(f)
|
||||
|
||||
|
@ -32,7 +30,6 @@ Given(~/^there is a flow$/) { ->
|
|||
|
||||
f.setDeployments(hashSet)
|
||||
|
||||
|
||||
fdao.persist(f)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
import cucumber.api.DataTable
|
||||
import com.fasterxml.jackson.databind.JsonNode
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import deploydb.WorkFlow
|
||||
import org.glassfish.jersey.client.JerseyInvocation
|
||||
import org.joda.time.DateTime
|
||||
|
||||
|
@ -93,6 +94,15 @@ Then(~/^the body should be JSON:$/) { String expectedBody ->
|
|||
assert bodyNode == expectedNode
|
||||
}
|
||||
|
||||
Given(~/^DeployDb configuration directory path is "(.*?)"$/) { String configDir ->
|
||||
Given(~/^Models configuration directory path is "(.*?)"$/) { String configDir ->
|
||||
setConfigDirectory(configDir)
|
||||
}
|
||||
|
||||
Given(~/^Models configuration is reloaded from directory path "(.*?)"$/) { String configDir ->
|
||||
setConfigDirectory(configDir)
|
||||
withWorkFlow { WorkFlow workFlow ->
|
||||
withSession {
|
||||
workFlow.loadConfigModels()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,34 +4,50 @@ this.metaClass.mixin(cucumber.api.groovy.EN)
|
|||
import com.fasterxml.jackson.databind.JsonNode
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import deploydb.ModelLoader
|
||||
import deploydb.ModelType
|
||||
import deploydb.WorkFlow
|
||||
import deploydb.dao.ModelConfigDAO
|
||||
import deploydb.models.Environment
|
||||
import deploydb.models.ModelConfig
|
||||
import deploydb.models.Webhook.Webhook
|
||||
import deploydb.registry.ModelRegistry
|
||||
import org.joda.time.DateTime
|
||||
import cucumber.api.DataTable
|
||||
|
||||
import deploydb.WebhookManager
|
||||
import webhookTestServer.models.RequestWebhookObject
|
||||
|
||||
|
||||
Given(~/^a (.*?) webhook "(.*?)" configuration:$/) { String webhookType,
|
||||
String eventType, String configBody ->
|
||||
|
||||
List<String> paths = getUrlPathFromWebhookConfigBody(configBody, eventType)
|
||||
withWorkFlow { WorkFlow workFlow ->
|
||||
/*
|
||||
* Instantiate the webhook object from configuration
|
||||
*/
|
||||
ModelLoader<Webhook> webhookLoader = new ModelLoader<>(Webhook.class)
|
||||
workFlow.globalWebhook = webhookLoader.loadFromString(configBody)
|
||||
|
||||
withWebhookManager { WebhookManager webhookManager, RequestWebhookObject requestWebhookObject ->
|
||||
/**
|
||||
* Create ModelConfig. This feature allows us to remember the config in
|
||||
* case of configReload
|
||||
*/
|
||||
ModelConfig modelConfig = new ModelConfig(
|
||||
workFlow.deployDBApp.configChecksum, configBody,
|
||||
workFlow.defaultIdent, ModelType.WEBHOOK)
|
||||
|
||||
withSession {
|
||||
ModelConfigDAO modelConfigDAO = new ModelConfigDAO(sessionFactory)
|
||||
modelConfigDAO.persist(modelConfig)
|
||||
}
|
||||
}
|
||||
|
||||
withTestWebhookServer { RequestWebhookObject requestWebhookObject ->
|
||||
/*
|
||||
* Save the configured webhook uri(s) in requestWebhookObject. These paths will be compared
|
||||
* when deploydb invokes webhooks.
|
||||
*/
|
||||
requestWebhookObject.addConfiguredUriPaths(paths)
|
||||
|
||||
/*
|
||||
* Load the webhook configuration in webhookManager
|
||||
*/
|
||||
|
||||
ModelLoader<Webhook> webhookLoader = new ModelLoader<>(Webhook.class)
|
||||
webhookManager.webhook = webhookLoader.loadFromString(configBody)
|
||||
|
||||
/*
|
||||
* Set the content type from the webhook and the event type. The content type will be
|
||||
* checked when deploydb invokes webhooks
|
||||
|
@ -55,7 +71,7 @@ Given(~/^an (.*?) environment webhook "(.*?)" configuration named "(.*?)":$/) {S
|
|||
* Save the configured webhook uri(s) in requestWebhookObject. These paths will be compared
|
||||
* when deploydb invokes webhooks.
|
||||
*/
|
||||
withWebhookManager { WebhookManager webhookManager, RequestWebhookObject requestWebhookObject ->
|
||||
withTestWebhookServer { RequestWebhookObject requestWebhookObject ->
|
||||
requestWebhookObject.addConfiguredUriPaths(paths)
|
||||
/*
|
||||
* Set the content type from the webhook and the event type. The content type will be
|
||||
|
@ -72,6 +88,22 @@ Given(~/^an (.*?) environment webhook "(.*?)" configuration named "(.*?)":$/) {S
|
|||
a.ident = envIdent
|
||||
environmentRegistry.put(envIdent, a)
|
||||
}
|
||||
|
||||
/**
|
||||
* Create ModelConfig. This feature allows us to remember the config in
|
||||
* case of configReload
|
||||
*/
|
||||
withWorkFlow { WorkFlow workFlow ->
|
||||
|
||||
ModelConfig modelConfig = new ModelConfig(
|
||||
workFlow.deployDBApp.configChecksum, configBody,
|
||||
envIdent, ModelType.ENVIRONMENT)
|
||||
|
||||
withSession {
|
||||
ModelConfigDAO modelConfigDAO = new ModelConfigDAO(sessionFactory)
|
||||
modelConfigDAO.persist(modelConfig)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
When (~/^I POST to "(.*?)" with an artifact/) { String path ->
|
||||
|
@ -123,8 +155,6 @@ Then(~/^the webhook ([1-9][0-9]*) should be invoked with the JSON:$/) { int webh
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
And (~/the webhook should have the headers:$/){ DataTable headers ->
|
||||
|
||||
withRequestWebhookObject { RequestWebhookObject requestWebhookObject ->
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
package db.migration
|
||||
|
||||
import java.sql.DatabaseMetaData
|
||||
|
||||
|
||||
/**
|
||||
* Example of a Java-based migration.
|
||||
*/
|
||||
class V8__create_configs_table extends DeployDBMigration {
|
||||
|
||||
/** Return migration number to differentiate from other versions */
|
||||
@Override
|
||||
Integer getChecksum() {
|
||||
return 8
|
||||
}
|
||||
|
||||
/**
|
||||
* Gather sql commands for this migration
|
||||
*
|
||||
* @param metadata
|
||||
* @return List of sql commands
|
||||
*/
|
||||
List<String> prepareCommands(DatabaseMetaData metadata) {
|
||||
|
||||
/* Sql commands */
|
||||
List<String> commands = []
|
||||
|
||||
/*
|
||||
* Add modelConfigs table
|
||||
*/
|
||||
commands += """
|
||||
CREATE TABLE modelConfigs (
|
||||
id BIGINT AUTO_INCREMENT,
|
||||
checksum VARCHAR(64) NOT NULL,
|
||||
contents TEXT NOT NULL,
|
||||
ident VARCHAR(8192),
|
||||
modelType INT NOT NULL,
|
||||
createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP(),
|
||||
deletedAt TIMESTAMP NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
"""
|
||||
|
||||
/*
|
||||
* Add checksum column to flows table
|
||||
*/
|
||||
commands += """
|
||||
ALTER TABLE flows ADD COLUMN checksum VARCHAR(64);
|
||||
"""
|
||||
|
||||
return commands
|
||||
}
|
||||
}
|
|
@ -3,9 +3,6 @@ package deploydb
|
|||
import com.codahale.metrics.annotation.Timed
|
||||
import com.google.common.collect.ImmutableMultimap
|
||||
import io.dropwizard.servlets.tasks.Task
|
||||
import org.hibernate.Session
|
||||
import org.hibernate.Transaction
|
||||
import org.hibernate.context.internal.ManagedSessionContext
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
|
@ -31,23 +28,15 @@ class ConfigReloadTask extends Task {
|
|||
@Override
|
||||
void execute(ImmutableMultimap<String, String> parameters, PrintWriter output) throws Exception {
|
||||
|
||||
Session session = this.workFlow.deployDBApp.getSessionFactory().openSession()
|
||||
try {
|
||||
ManagedSessionContext.bind(session)
|
||||
Transaction transaction = session.beginTransaction()
|
||||
this.workFlow.deployDBApp.withHibernateSession() {
|
||||
try {
|
||||
this.workFlow.loadConfigModels(true)
|
||||
transaction.commit()
|
||||
this.workFlow.loadConfigModels()
|
||||
output.println("Done!")
|
||||
} catch (Exception e) {
|
||||
logger.error("failed to reload the config with an exception: ", e)
|
||||
output.println("Failed: " + e.getMessage())
|
||||
throw e
|
||||
}
|
||||
catch (Exception e) {
|
||||
transaction.rollback()
|
||||
logger.error("failed to reload the config: " + e.getMessage())
|
||||
output.println("Failed: Configuration reload is not allowed while deployments are in progress")
|
||||
}
|
||||
} finally {
|
||||
session.close()
|
||||
ManagedSessionContext.unbind(this.workFlow.deployDBApp.getSessionFactory())
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,7 +16,10 @@ import io.dropwizard.setup.Bootstrap
|
|||
import io.dropwizard.setup.Environment
|
||||
import io.dropwizard.util.JarLocation
|
||||
import io.dropwizard.views.ViewBundle
|
||||
import org.hibernate.Session
|
||||
import org.hibernate.SessionFactory
|
||||
import org.hibernate.Transaction
|
||||
import org.hibernate.context.internal.ManagedSessionContext
|
||||
import org.joda.time.DateTimeZone
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
@ -25,12 +28,13 @@ import org.slf4j.LoggerFactory
|
|||
class DeployDBApp extends Application<DeployDBConfiguration> {
|
||||
private final ImmutableList models = ImmutableList.of(
|
||||
models.Artifact, models.Deployment,
|
||||
models.PromotionResult, models.Flow)
|
||||
models.PromotionResult, models.Flow, models.ModelConfig)
|
||||
private static final Logger logger = LoggerFactory.getLogger(DeployDBApp.class)
|
||||
private WebhookManager webhooksManager
|
||||
private WorkFlow workFlow
|
||||
private provider.V1TypeProvider typeProvider
|
||||
private String configDirectory
|
||||
private String configChecksum
|
||||
|
||||
static void main(String[] args) throws Exception {
|
||||
new DeployDBApp().run(args)
|
||||
|
@ -61,7 +65,7 @@ class DeployDBApp extends Application<DeployDBConfiguration> {
|
|||
|
||||
|
||||
@Override
|
||||
public void initialize(Bootstrap<DeployDBConfiguration> bootstrap) {
|
||||
void initialize(Bootstrap<DeployDBConfiguration> bootstrap) {
|
||||
bootstrap.addBundle(new AssetsBundle())
|
||||
bootstrap.addBundle(hibernate)
|
||||
workFlow = new WorkFlow(this)
|
||||
|
@ -96,6 +100,7 @@ class DeployDBApp extends Application<DeployDBConfiguration> {
|
|||
bootstrap.validatorFactory.validator)
|
||||
}
|
||||
|
||||
/** Validate the arguments */
|
||||
@Override
|
||||
public void run(String... arguments) throws Exception {
|
||||
try {
|
||||
|
@ -118,6 +123,8 @@ class DeployDBApp extends Application<DeployDBConfiguration> {
|
|||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/** DeployDB is up and running */
|
||||
@Override
|
||||
public void run(DeployDBConfiguration configuration,
|
||||
Environment environment) {
|
||||
|
@ -136,11 +143,14 @@ class DeployDBApp extends Application<DeployDBConfiguration> {
|
|||
* Load configuration models
|
||||
*/
|
||||
this.configDirectory = configuration.configDirectory
|
||||
try {
|
||||
workFlow.loadConfigModels(false)
|
||||
} catch (Exception e) {
|
||||
logger.error("failed to read config from directory: " +
|
||||
"${configDirectory}, error: ${e.toString()}")
|
||||
withHibernateSession() {
|
||||
try {
|
||||
workFlow.loadConfigModels()
|
||||
} catch (Exception e) {
|
||||
logger.error("failed to read config from directory: " +
|
||||
"${configDirectory} with an exception: ", e)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -155,7 +165,7 @@ class DeployDBApp extends Application<DeployDBConfiguration> {
|
|||
environment.healthChecks().register('webhook', new health.WebhookHealthCheck(webhooksManager))
|
||||
|
||||
/** Add admin task for config reload */
|
||||
environment.admin().addTask(new ConfigReloadTask(workFlow));
|
||||
environment.admin().addTask(new ConfigReloadTask(workFlow))
|
||||
|
||||
/**
|
||||
* Instantiate Resources classes for Jersey handlers
|
||||
|
@ -170,4 +180,21 @@ class DeployDBApp extends Application<DeployDBConfiguration> {
|
|||
environment.jersey().register(new resources.PipelineResource(workFlow.pipelineRegistry))
|
||||
environment.jersey().register(new resources.ServiceResource(workFlow.serviceRegistry))
|
||||
}
|
||||
|
||||
/** Execute DB operations wiht a session */
|
||||
void withHibernateSession(Closure c) {
|
||||
Session session = this.getSessionFactory().openSession()
|
||||
Transaction transaction
|
||||
try {
|
||||
ManagedSessionContext.bind(session)
|
||||
transaction = session.beginTransaction()
|
||||
c.call()
|
||||
transaction.commit()
|
||||
} catch (Exception e) {
|
||||
transaction.rollback()
|
||||
} finally {
|
||||
session.close()
|
||||
ManagedSessionContext.unbind(this.getSessionFactory())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package deploydb
|
||||
|
||||
/**
|
||||
* ModelType
|
||||
*
|
||||
* Enumeration to track type of the Model
|
||||
*
|
||||
* ALERT - All the Models store the "status" in DB as an integer; hence
|
||||
* please DO NOT REMOVE OR CHANGE ORDER. You CAN ONLY ADD TO THIS LIST
|
||||
*/
|
||||
enum ModelType {
|
||||
SERVICE, /* 0 */
|
||||
PIPELINE, /* 1 */
|
||||
ENVIRONMENT,
|
||||
PROMOTION,
|
||||
WEBHOOK
|
||||
}
|
||||
|
|
@ -17,7 +17,7 @@ class WebhookManager implements Managed {
|
|||
private AbstractHookRunner runner = null
|
||||
private AbstractHookQueue queue = null
|
||||
private final Logger logger = LoggerFactory.getLogger(WebhookManager.class)
|
||||
private Webhook webhook = null
|
||||
|
||||
/*
|
||||
* We should we move this to application and make sure through out the code we use this variable
|
||||
*/
|
||||
|
@ -44,7 +44,6 @@ class WebhookManager implements Managed {
|
|||
* @param deployDBConfiguration
|
||||
*/
|
||||
WebhookManager(DeployDBConfiguration deployDBConfiguration ) {
|
||||
|
||||
queue = deployDBConfiguration.whoasFactory.buildQueue()
|
||||
runner = deployDBConfiguration.whoasFactory.buildRunner(queue)
|
||||
|
||||
|
@ -76,9 +75,12 @@ class WebhookManager implements Managed {
|
|||
* @param webhookModelMapper The mapper class to translate from model to webhook
|
||||
* @return Fail if push of hook request fails
|
||||
*/
|
||||
boolean sendDeploymentWebhook(String eventType, Webhook environmentWebhook,
|
||||
boolean sendDeploymentWebhook(String eventType,
|
||||
Webhook globalWebhook,
|
||||
Webhook environmentWebhook,
|
||||
WebhookModelMapper webhookModelMapper) {
|
||||
return sendDeployDbWebhook(eventType, "deployment", environmentWebhook, webhookModelMapper)
|
||||
return sendDeployDbWebhook(eventType, "deployment", globalWebhook,
|
||||
environmentWebhook, webhookModelMapper)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -88,9 +90,12 @@ class WebhookManager implements Managed {
|
|||
* @param webhookModelMapper The mapper class to translate from model to webhook
|
||||
* @return Fail if push of hook request fails
|
||||
*/
|
||||
boolean sendPromotionWebhook(String eventType, Webhook environmentWebhook,
|
||||
WebhookModelMapper webhookModelMapper) {
|
||||
return sendDeployDbWebhook(eventType, "promotion", environmentWebhook, webhookModelMapper)
|
||||
boolean sendPromotionWebhook(String eventType,
|
||||
Webhook globalWebhook,
|
||||
Webhook environmentWebhook,
|
||||
WebhookModelMapper webhookModelMapper) {
|
||||
return sendDeployDbWebhook(eventType, "promotion", globalWebhook,
|
||||
environmentWebhook, webhookModelMapper)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -101,8 +106,10 @@ class WebhookManager implements Managed {
|
|||
* @param webhookModelMapper The mapper class to translate from model to webhook
|
||||
* @return Fail if push of hook request fails
|
||||
*/
|
||||
boolean sendDeployDbWebhook( String eventType, String webhookType, Webhook environmentWebhook,
|
||||
WebhookModelMapper webhookModelMapper) {
|
||||
boolean sendDeployDbWebhook(String eventType, String webhookType,
|
||||
Webhook globalWebhook,
|
||||
Webhook environmentWebhook,
|
||||
WebhookModelMapper webhookModelMapper) {
|
||||
/*
|
||||
* Initialize the list for URL's configured in webhooks
|
||||
*/
|
||||
|
@ -120,10 +127,10 @@ class WebhookManager implements Managed {
|
|||
getMemberOfObject(getMemberOfObject(environmentWebhook, webhookType), eventType) != null) {
|
||||
eventUrlList = getMemberOfObject(getMemberOfObject(environmentWebhook, webhookType), eventType)
|
||||
}
|
||||
if (webhook != null &&
|
||||
getMemberOfObject(webhook, webhookType) != null &&
|
||||
getMemberOfObject( getMemberOfObject(webhook, webhookType), eventType) != null) {
|
||||
eventUrlList += getMemberOfObject( getMemberOfObject(webhook, webhookType), eventType)
|
||||
if (globalWebhook != null &&
|
||||
getMemberOfObject(globalWebhook, webhookType) != null &&
|
||||
getMemberOfObject(getMemberOfObject(globalWebhook, webhookType), eventType) != null) {
|
||||
eventUrlList += getMemberOfObject(getMemberOfObject(globalWebhook, webhookType), eventType)
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -148,6 +155,7 @@ class WebhookManager implements Managed {
|
|||
}
|
||||
return pushReturn
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the webhook thread is running
|
||||
*/
|
||||
|
|
|
@ -3,6 +3,7 @@ package deploydb
|
|||
import groovy.io.FileType
|
||||
import javax.ws.rs.WebApplicationException
|
||||
import javax.ws.rs.core.Response
|
||||
import org.apache.commons.codec.digest.DigestUtils
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
|
@ -10,12 +11,13 @@ import org.slf4j.LoggerFactory
|
|||
/* Define a new exception to break out of loop */
|
||||
class BreakLoopException extends Exception{}
|
||||
|
||||
public class WorkFlow {
|
||||
class WorkFlow {
|
||||
private final DeployDBApp deployDBApp
|
||||
private registry.ModelRegistry<models.Promotion> promotionRegistry
|
||||
private registry.ModelRegistry<models.Environment> environmentRegistry
|
||||
private registry.ModelRegistry<models.pipeline.Pipeline> pipelineRegistry
|
||||
private registry.ModelRegistry<models.Service> serviceRegistry
|
||||
private models.Webhook.Webhook globalWebhook
|
||||
private ModelLoader<models.Promotion> promotionLoader
|
||||
private ModelLoader<models.Environment> environmentLoader
|
||||
private ModelLoader<models.pipeline.Pipeline> pipelineLoader
|
||||
|
@ -24,7 +26,9 @@ public class WorkFlow {
|
|||
private dao.ArtifactDAO artifactDAO
|
||||
private dao.DeploymentDAO deploymentDAO
|
||||
private dao.FlowDAO flowDAO
|
||||
private dao.ModelConfigDAO modelConfigDAO
|
||||
private static final Logger logger = LoggerFactory.getLogger(WorkFlow.class)
|
||||
private static final String defaultIdent = "default"
|
||||
|
||||
WorkFlow(DeployDBApp app) {
|
||||
this.deployDBApp = app
|
||||
|
@ -37,6 +41,7 @@ public class WorkFlow {
|
|||
artifactDAO = new dao.ArtifactDAO(this.deployDBApp.getSessionFactory())
|
||||
deploymentDAO = new dao.DeploymentDAO(this.deployDBApp.getSessionFactory())
|
||||
flowDAO = new dao.FlowDAO(this.deployDBApp.getSessionFactory())
|
||||
modelConfigDAO = new dao.ModelConfigDAO(this.deployDBApp.getSessionFactory())
|
||||
}
|
||||
|
||||
void initializeRegistry() {
|
||||
|
@ -59,21 +64,61 @@ public class WorkFlow {
|
|||
webhookLoader = new ModelLoader<>(models.Webhook.Webhook.class)
|
||||
}
|
||||
|
||||
private void loadConfigModelsCommon(String modelDirName, Closure c) {
|
||||
File modelDirectory = new File(modelDirName);
|
||||
/** Helper for config loader */
|
||||
private void loadConfigModelsCommon(String modelDirName,
|
||||
ModelType modelType,
|
||||
registry.ModelRegistry registry,
|
||||
ModelLoader loader,
|
||||
Vector<InputStream> inputStreams,
|
||||
List<models.ModelConfig> modelConfigList,
|
||||
Closure c) {
|
||||
File modelDirectory = new File(modelDirName)
|
||||
if (modelDirectory.exists() && modelDirectory.isDirectory()) {
|
||||
logger.debug("Loading model from directory: ${modelDirectory.getCanonicalPath()}");
|
||||
logger.info("Loading models from directory: ${modelDirectory.getCanonicalPath()}")
|
||||
|
||||
/* Skip everything but yaml file */
|
||||
modelDirectory.eachFileMatch(FileType.FILES, ~/^.*?\.yml/) { File modelFile ->
|
||||
/**
|
||||
* When walking thr the files from the directory:
|
||||
* - Skip everything but yaml file.
|
||||
* - Sort these files in order to ensure that checksum remains same regardless
|
||||
* the order in which files are read from the directory
|
||||
*/
|
||||
List<String> filenames = []
|
||||
modelDirectory.eachFileMatch(FileType.FILES, ~/^.*?\.yml/) { it -> filenames << it.name }
|
||||
filenames.sort()
|
||||
filenames.each() { String filename ->
|
||||
File modelFile = new File(modelDirectory, filename)
|
||||
try {
|
||||
c.call(modelFile)
|
||||
/** Read YAML file into model object */
|
||||
def model = loader.load(modelFile)
|
||||
|
||||
/**
|
||||
* If registry is available, then insert model object into registry. In case
|
||||
* of singular models (webhook), it can be null, assume a "deafult" ident.
|
||||
*/
|
||||
String ident = defaultIdent
|
||||
if (registry) {
|
||||
ident = model.ident = loader.getIdent(modelFile.name)
|
||||
registry.put(model.ident, model)
|
||||
}
|
||||
|
||||
/* Add file stream to table for checksum calculations */
|
||||
FileInputStream fileInputStream = new FileInputStream(modelFile)
|
||||
inputStreams.add(fileInputStream)
|
||||
|
||||
/* Create ModelConfig */
|
||||
models.ModelConfig modelConfig = new models.ModelConfig(null, modelFile.text,
|
||||
ident, modelType)
|
||||
modelConfigList.add(modelConfig)
|
||||
|
||||
/** Execute the closure */
|
||||
c.call(model)
|
||||
|
||||
} catch (BreakLoopException e) {
|
||||
throw e
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw e /* Throw the exception again */
|
||||
} catch (all) {
|
||||
logger.info("Failed to load model from ${modelFile.name}")
|
||||
logger.error("Failed to load model from ${modelFile.name}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -86,18 +131,10 @@ public class WorkFlow {
|
|||
*
|
||||
* @param baseConfigDirName
|
||||
*/
|
||||
void loadConfigModels(Boolean reloadConfig) {
|
||||
|
||||
/**
|
||||
* Abort reloading the configuration (trigerred by REST API) in case we
|
||||
* have active flows.
|
||||
*/
|
||||
if (reloadConfig && this.flowDAO.getActiveFlowsCount() != 0) {
|
||||
throw new Exception("Configuration reload is not allowed while deployments are in progress")
|
||||
}
|
||||
void loadConfigModels() {
|
||||
|
||||
/** Validate base config directory */
|
||||
File baseConfigDirectory = new File(this.deployDBApp.configDirectory);
|
||||
File baseConfigDirectory = new File(this.deployDBApp.configDirectory)
|
||||
if (!baseConfigDirectory.exists() || !baseConfigDirectory.isDirectory()) {
|
||||
throw new Exception("No DeployDB configuration found. DeployDB would not function properly")
|
||||
}
|
||||
|
@ -118,30 +155,30 @@ public class WorkFlow {
|
|||
registry.ModelRegistry<models.Service> tmpServiceRegistry =
|
||||
new registry.ModelRegistry<models.Service>()
|
||||
models.Webhook.Webhook tmpWebhook = null
|
||||
Vector<InputStream> inputStreams = new Vector<>()
|
||||
List<models.ModelConfig> modelConfigList = []
|
||||
|
||||
/* Load promotions */
|
||||
String promotionsDirName = this.deployDBApp.configDirectory + "/promotions"
|
||||
loadConfigModelsCommon(promotionsDirName) { File modelFile ->
|
||||
models.Promotion promotion = this.promotionLoader.load(modelFile)
|
||||
promotion.ident = this.promotionLoader.getIdent(modelFile.name)
|
||||
tmpPromotionRegistry.put(promotion.ident, promotion)
|
||||
loadConfigModelsCommon(promotionsDirName, ModelType.PROMOTION,
|
||||
tmpPromotionRegistry, this.promotionLoader,
|
||||
inputStreams, modelConfigList) { models.Promotion promotion ->
|
||||
logger.debug("Loaded promotions model: ${promotion.ident}")
|
||||
}
|
||||
|
||||
/* Load environments */
|
||||
String environmentsDirName = this.deployDBApp.configDirectory + "/environments"
|
||||
loadConfigModelsCommon(environmentsDirName) { File modelFile ->
|
||||
models.Environment environment = this.environmentLoader.load(modelFile)
|
||||
environment.ident = this.environmentLoader.getIdent(modelFile.name)
|
||||
tmpEnvironmentRegistry.put(environment.ident, environment)
|
||||
loadConfigModelsCommon(environmentsDirName, ModelType.ENVIRONMENT,
|
||||
tmpEnvironmentRegistry, this.environmentLoader,
|
||||
inputStreams, modelConfigList) { models.Environment environment ->
|
||||
logger.debug("Loaded environments model: ${environment.ident}")
|
||||
}
|
||||
|
||||
/* Load pipelines */
|
||||
String pipelinesDirName = this.deployDBApp.configDirectory + "/pipelines"
|
||||
loadConfigModelsCommon(pipelinesDirName) { File modelFile ->
|
||||
models.pipeline.Pipeline pipeline = this.pipelineLoader.load(modelFile)
|
||||
pipeline.ident = this.pipelineLoader.getIdent(modelFile.name)
|
||||
loadConfigModelsCommon(pipelinesDirName, ModelType.PIPELINE,
|
||||
tmpPipelineRegistry, this.pipelineLoader,
|
||||
inputStreams, modelConfigList) { models.pipeline.Pipeline pipeline ->
|
||||
|
||||
/* Validate */
|
||||
pipeline.environments.each() {
|
||||
|
@ -162,16 +199,14 @@ public class WorkFlow {
|
|||
}
|
||||
}
|
||||
|
||||
/* Add to registry */
|
||||
tmpPipelineRegistry.put(pipeline.ident, pipeline)
|
||||
logger.debug("Loaded pipelines model: ${pipeline.ident}")
|
||||
}
|
||||
|
||||
/* Load services */
|
||||
String servicesDirName = this.deployDBApp.configDirectory + "/services"
|
||||
loadConfigModelsCommon(servicesDirName) { File modelFile ->
|
||||
models.Service service = this.serviceLoader.load(modelFile)
|
||||
service.ident = this.serviceLoader.getIdent(modelFile.name)
|
||||
loadConfigModelsCommon(servicesDirName, ModelType.SERVICE,
|
||||
tmpServiceRegistry, this.serviceLoader,
|
||||
inputStreams, modelConfigList) { models.Service service ->
|
||||
|
||||
/* Validate */
|
||||
service.pipelines.each() { String pipelineIdent ->
|
||||
|
@ -189,30 +224,52 @@ public class WorkFlow {
|
|||
}
|
||||
}
|
||||
|
||||
/* Add to registry */
|
||||
tmpServiceRegistry.put(service.ident, service)
|
||||
logger.debug("Loaded services model: ${service.ident}")
|
||||
}
|
||||
|
||||
/* Load webhook */
|
||||
String webhookDirName = this.deployDBApp.configDirectory + "/webhook"
|
||||
try {
|
||||
loadConfigModelsCommon(webhookDirName, ModelType.WEBHOOK,
|
||||
null, this.webhookLoader,
|
||||
inputStreams, modelConfigList) { models.Webhook.Webhook webhook ->
|
||||
|
||||
/* Store webhook */
|
||||
tmpWebhook = webhook
|
||||
|
||||
logger.debug("Loaded webhook model")
|
||||
|
||||
/* Now that we have found a valid global webhook, we are done */
|
||||
throw new BreakLoopException()
|
||||
}
|
||||
} catch (BreakLoopException e) {
|
||||
/* Neeed the log to make codenarc happy */
|
||||
logger.debug("Done with webhook load")
|
||||
}
|
||||
|
||||
/* Compute a checksum for this iteration of Models configuration */
|
||||
SequenceInputStream sequenceInputStream = new SequenceInputStream(inputStreams.elements())
|
||||
String newConfigChecksum
|
||||
try {
|
||||
newConfigChecksum = DigestUtils.md5Hex(sequenceInputStream)
|
||||
} finally {
|
||||
sequenceInputStream.close()
|
||||
}
|
||||
if (this.deployDBApp.configChecksum == newConfigChecksum) {
|
||||
logger.info("Ignoring as no change in DeployDB Model Configuration detected")
|
||||
return
|
||||
}
|
||||
this.deployDBApp.configChecksum = newConfigChecksum
|
||||
|
||||
/* At least one service MUST be configured for deployDb to function properly */
|
||||
if (tmpServiceRegistry.getAll().isEmpty()) {
|
||||
logger.info("NO SERVICES ARE CONFIGURED. DeployDB would not function properly")
|
||||
}
|
||||
|
||||
/* Load webhook */
|
||||
String webhookDirName = this.deployDBApp.configDirectory + "/webhook"
|
||||
try {
|
||||
loadConfigModelsCommon(webhookDirName) { File modelFile ->
|
||||
|
||||
tmpWebhook = this.webhookLoader.load(modelFile)
|
||||
logger.debug("Loaded webhooks model from: ${modelFile.name}")
|
||||
|
||||
/* Now that we have found a valid webhook, we are done */
|
||||
throw new BreakLoopException()
|
||||
}
|
||||
} catch (BreakLoopException e) {
|
||||
/* Neeed the log to make codenarc happy */
|
||||
logger.debug("Done with webhook load")
|
||||
/* Persist all ModelConfigs */
|
||||
modelConfigList.each() { models.ModelConfig modelConfig ->
|
||||
modelConfig.checksum = newConfigChecksum
|
||||
this.modelConfigDAO.persist(modelConfig)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -222,7 +279,72 @@ public class WorkFlow {
|
|||
environmentRegistry = tmpEnvironmentRegistry
|
||||
pipelineRegistry = tmpPipelineRegistry
|
||||
serviceRegistry = tmpServiceRegistry
|
||||
deployDBApp.webhooksManager.webhook = tmpWebhook
|
||||
globalWebhook = tmpWebhook
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve webhook either from memory or DB (if config has changed)
|
||||
*
|
||||
* @param deployment
|
||||
* @return Webhook object
|
||||
*/
|
||||
models.Webhook.Webhook retrieveWebhook(models.Deployment deployment) {
|
||||
|
||||
/**
|
||||
* If configuration has changed since the flow creation, then retrieve and
|
||||
* rebuild objects from DB
|
||||
*/
|
||||
if (deployment.flow.configChecksum != this.deployDBApp.configChecksum) {
|
||||
/* Load webhook from config */
|
||||
models.ModelConfig webhookConfig =
|
||||
this.modelConfigDAO.findModelConfig(ModelType.WEBHOOK,
|
||||
defaultIdent, deployment.flow.configChecksum)
|
||||
if (webhookConfig) {
|
||||
models.Webhook.Webhook fetchedWebhook =
|
||||
this.webhookLoader.loadFromString(webhookConfig.contents)
|
||||
return fetchedWebhook
|
||||
} else {
|
||||
logger.error("Failed to find webhook configuration for " +
|
||||
"deployment: ${deployment.id}, config-checksum: ${deployment.flow.configChecksum}")
|
||||
return null
|
||||
}
|
||||
} else {
|
||||
/* Load extant global webhook object */
|
||||
return this.globalWebhook
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve Environment either from memory or DB (if config has changed)
|
||||
*
|
||||
* @param deployment
|
||||
* @return Environment
|
||||
*/
|
||||
models.Environment retrieveEnvironment(models.Deployment deployment) {
|
||||
|
||||
/**
|
||||
* If configuration is changed since the flow creation, then retrieve and
|
||||
* rebuild objects from DB
|
||||
*/
|
||||
if (deployment.flow.configChecksum != this.deployDBApp.configChecksum) {
|
||||
/* Load environment from config */
|
||||
models.ModelConfig environmentConfig =
|
||||
this.modelConfigDAO.findModelConfig(ModelType.ENVIRONMENT,
|
||||
deployment.environmentIdent, deployment.flow.configChecksum)
|
||||
if (environmentConfig) {
|
||||
models.Environment environment =
|
||||
this.environmentLoader.loadFromString(environmentConfig.contents)
|
||||
return environment
|
||||
} else {
|
||||
logger.error("Failed to find Environment configuration for " +
|
||||
"deployment: ${deployment.id}, Environment: ${deployment.environmentIdent}, " +
|
||||
"config-checksum: ${deployment.flow.configChecksum}")
|
||||
return null
|
||||
}
|
||||
} else {
|
||||
/* Load from environment */
|
||||
return this.environmentRegistry.get(deployment.environmentIdent)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -253,7 +375,8 @@ public class WorkFlow {
|
|||
services.flatten().each() { models.Service service ->
|
||||
|
||||
/* Create a flow */
|
||||
models.Flow flow = new models.Flow(artifact, service.ident)
|
||||
models.Flow flow = new models.Flow(artifact, service.ident,
|
||||
this.deployDBApp.configChecksum)
|
||||
|
||||
/* Get all pipelines */
|
||||
List<models.pipeline.Pipeline> pipelines = service.getPipelines().collect() { String pipelineIdent ->
|
||||
|
@ -373,16 +496,18 @@ public class WorkFlow {
|
|||
new mappers.DeploymentWebhookMapper(deployment)
|
||||
|
||||
/*
|
||||
* Get the environment based webhooks for this deployment
|
||||
* Get the global and environment based webhooks for this deployment
|
||||
*/
|
||||
models.Webhook.Webhook webhook = retrieveWebhook(deployment)
|
||||
models.Environment environment = retrieveEnvironment(deployment)
|
||||
models.Webhook.Webhook environmentWebhook =
|
||||
this.environmentRegistry.get(deployment.environmentIdent).webhook
|
||||
environment ? environment.webhook : null
|
||||
|
||||
/*
|
||||
* Use webhook manager to send the webhook
|
||||
*/
|
||||
if (deployDBApp.webhooksManager.sendDeploymentWebhook("created", environmentWebhook,
|
||||
deploymentWebhookMapper) == false) {
|
||||
if (deployDBApp.webhooksManager.sendDeploymentWebhook("created", webhook,
|
||||
environmentWebhook, deploymentWebhookMapper) == false) {
|
||||
logger.info("Failed to send deployment started ${deployment.id}")
|
||||
throw new WebApplicationException(Response.Status.BAD_REQUEST)
|
||||
}
|
||||
|
@ -408,17 +533,18 @@ public class WorkFlow {
|
|||
new mappers.DeploymentWebhookMapper(deployment)
|
||||
|
||||
/*
|
||||
* Get the environment based webhooks for this deployment
|
||||
* Get the global and environment based webhooks for this deployment
|
||||
*/
|
||||
models.Webhook.Webhook webhook = retrieveWebhook(deployment)
|
||||
models.Environment environment = retrieveEnvironment(deployment)
|
||||
models.Webhook.Webhook environmentWebhook =
|
||||
this.environmentRegistry.get(deployment.environmentIdent)?
|
||||
this.environmentRegistry.get(deployment.environmentIdent).webhook : null
|
||||
environment ? environment.webhook : null
|
||||
|
||||
/*
|
||||
* Use webhook manager to send the webhook
|
||||
*/
|
||||
if (deployDBApp.webhooksManager.sendDeploymentWebhook("started", environmentWebhook,
|
||||
deploymentWebhookMapper) == false) {
|
||||
if (deployDBApp.webhooksManager.sendDeploymentWebhook("started", webhook,
|
||||
environmentWebhook, deploymentWebhookMapper) == false) {
|
||||
logger.info("Failed to send deployment started ${deployment.id}")
|
||||
throw new WebApplicationException(Response.Status.BAD_REQUEST)
|
||||
}
|
||||
|
@ -447,17 +573,18 @@ public class WorkFlow {
|
|||
new mappers.DeploymentWebhookMapper(deployment)
|
||||
|
||||
/*
|
||||
* Get the environment based webhooks for this deployment
|
||||
* Get the global and environment based webhooks for this deployment
|
||||
*/
|
||||
models.Webhook.Webhook webhook = retrieveWebhook(deployment)
|
||||
models.Environment environment = retrieveEnvironment(deployment)
|
||||
models.Webhook.Webhook environmentWebhook =
|
||||
this.environmentRegistry.get(deployment.environmentIdent)?
|
||||
this.environmentRegistry.get(deployment.environmentIdent).webhook : null
|
||||
environment ? environment.webhook : null
|
||||
|
||||
/*
|
||||
* Use webhook manager to send the webhook
|
||||
*/
|
||||
if (deployDBApp.webhooksManager.sendDeploymentWebhook("completed", environmentWebhook,
|
||||
deploymentWebhookMapper) == false) {
|
||||
if (deployDBApp.webhooksManager.sendDeploymentWebhook("completed", webhook,
|
||||
environmentWebhook, deploymentWebhookMapper) == false) {
|
||||
logger.info("Failed to send deployment completed ${deployment.id}")
|
||||
throw new WebApplicationException(Response.Status.BAD_REQUEST)
|
||||
}
|
||||
|
@ -499,17 +626,18 @@ public class WorkFlow {
|
|||
new mappers.PromotionWebhookMapper(deployment, promotionResult)
|
||||
|
||||
/*
|
||||
* Get the environment based webhooks for this deployment
|
||||
* Get the global and environment based webhooks for this deployment
|
||||
*/
|
||||
models.Webhook.Webhook webhook = retrieveWebhook(deployment)
|
||||
models.Environment environment = retrieveEnvironment(deployment)
|
||||
models.Webhook.Webhook environmentWebhook =
|
||||
this.environmentRegistry.get(deployment.environmentIdent)?
|
||||
this.environmentRegistry.get(deployment.environmentIdent).webhook : null
|
||||
environment ? environment.webhook : null
|
||||
|
||||
/*
|
||||
* Use webhook manager to send the webhook
|
||||
*/
|
||||
if (deployDBApp.webhooksManager.sendPromotionWebhook("completed", environmentWebhook,
|
||||
promotionWebhookMapper) == false) {
|
||||
if (deployDBApp.webhooksManager.sendPromotionWebhook("completed", webhook,
|
||||
environmentWebhook, promotionWebhookMapper) == false) {
|
||||
logger.info("Failed to send promotion success webhook for ${promotionResult.promotion}")
|
||||
throw new WebApplicationException(Response.Status.BAD_REQUEST)
|
||||
}
|
||||
|
@ -551,17 +679,18 @@ public class WorkFlow {
|
|||
new mappers.PromotionWebhookMapper(deployment, promotionResult)
|
||||
|
||||
/*
|
||||
* Get the environment based webhooks for this deployment
|
||||
* Get the global and environment based webhooks for this deployment
|
||||
*/
|
||||
models.Webhook.Webhook webhook = retrieveWebhook(deployment)
|
||||
models.Environment environment = retrieveEnvironment(deployment)
|
||||
models.Webhook.Webhook environmentWebhook =
|
||||
this.environmentRegistry.get(deployment.environmentIdent)?
|
||||
this.environmentRegistry.get(deployment.environmentIdent).webhook : null
|
||||
environment ? environment.webhook : null
|
||||
|
||||
/*
|
||||
* Use webhook manager to send the webhook
|
||||
*/
|
||||
if (deployDBApp.webhooksManager.sendPromotionWebhook("completed", environmentWebhook,
|
||||
promotionWebhookMapper) == false) {
|
||||
if (deployDBApp.webhooksManager.sendPromotionWebhook("completed", webhook,
|
||||
environmentWebhook, promotionWebhookMapper) == false) {
|
||||
logger.info("Failed to send promotion failed webhook for ${promotionResult.promotion}")
|
||||
throw new WebApplicationException(Response.Status.BAD_REQUEST)
|
||||
}
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
package deploydb.dao
|
||||
|
||||
import deploydb.models.Flow
|
||||
import deploydb.Status
|
||||
import groovy.transform.InheritConstructors
|
||||
import io.dropwizard.hibernate.AbstractDAO
|
||||
import org.hibernate.criterion.Projections
|
||||
import org.hibernate.criterion.Restrictions
|
||||
|
||||
|
||||
/**
|
||||
|
@ -13,14 +10,4 @@ import org.hibernate.criterion.Restrictions
|
|||
*/
|
||||
@InheritConstructors
|
||||
class FlowDAO extends AbstractDAO<Flow> {
|
||||
/**
|
||||
* Fetch active flows count
|
||||
*/
|
||||
Long getActiveFlowsCount() {
|
||||
return criteria()
|
||||
.add(Restrictions.and(
|
||||
Restrictions.ne("status", Status.SUCCESS),
|
||||
Restrictions.ne("status", Status.FAILED)))
|
||||
.setProjection(Projections.rowCount()).uniqueResult()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
package deploydb.dao
|
||||
|
||||
import deploydb.ModelType
|
||||
import deploydb.models.ModelConfig
|
||||
import groovy.transform.InheritConstructors
|
||||
import io.dropwizard.hibernate.AbstractDAO
|
||||
import org.hibernate.criterion.Restrictions
|
||||
import org.hibernate.criterion.Order
|
||||
|
||||
|
||||
/**
|
||||
* modelConfig Data access object
|
||||
*/
|
||||
@InheritConstructors
|
||||
class ModelConfigDAO extends AbstractDAO<ModelConfig> {
|
||||
|
||||
/**
|
||||
* Locate ModelConfig matching the modelType, identifier and checksum of config iteration
|
||||
*
|
||||
* @param modelType A Enum of Model type (Service, Pipeline, etc.)
|
||||
* @param ident Identifier of the Model
|
||||
* @param configChecksum Checksum of the configuration iteration
|
||||
* @return null or ModelConfig if found
|
||||
*/
|
||||
ModelConfig findModelConfig(
|
||||
ModelType modelType,
|
||||
String ident,
|
||||
String configChecksum) {
|
||||
return criteria()
|
||||
.add(Restrictions.eq('modelType', modelType))
|
||||
.add(Restrictions.eq('ident', ident))
|
||||
.add(Restrictions.eq('checksum', configChecksum))
|
||||
.addOrder(Order.desc('createdAt')).uniqueResult()
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore
|
|||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import deploydb.Status
|
||||
import javax.persistence.Column
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.CascadeType
|
||||
import javax.persistence.Entity
|
||||
import javax.persistence.EnumType
|
||||
import javax.persistence.Enumerated
|
||||
|
@ -34,8 +34,13 @@ class Flow extends AbstractModel {
|
|||
Set<Deployment> deployments = new HashSet<Deployment>()
|
||||
|
||||
@Column(name="service")
|
||||
@JsonProperty
|
||||
String service
|
||||
@JsonProperty(value = "service")
|
||||
String serviceIdent
|
||||
|
||||
/** Checksum of configuration of all the Models */
|
||||
@Column(name="checksum")
|
||||
@JsonIgnore
|
||||
String configChecksum
|
||||
|
||||
@Column(name="status")
|
||||
@Enumerated(EnumType.ORDINAL)
|
||||
|
@ -51,9 +56,10 @@ class Flow extends AbstractModel {
|
|||
* Default constructor to create a valid Flow object to save in
|
||||
* the database
|
||||
*/
|
||||
Flow(Artifact deployedArtifact, String service) {
|
||||
Flow(Artifact deployedArtifact, String serviceIdent, String configChecksum) {
|
||||
this.artifact = deployedArtifact
|
||||
this.service = service
|
||||
this.serviceIdent = serviceIdent
|
||||
this.configChecksum = configChecksum
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -71,7 +77,7 @@ class Flow extends AbstractModel {
|
|||
* @return True if the objects are equal otherwise false
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
boolean equals(Object o) {
|
||||
/* First object identity */
|
||||
if (this.is(o)) {
|
||||
return true
|
||||
|
@ -86,7 +92,8 @@ class Flow extends AbstractModel {
|
|||
return Objects.equals(this.id, that.id) &&
|
||||
Objects.equals(this.artifact, that.artifact) &&
|
||||
Objects.equals(this.deployments, that.deployments) &&
|
||||
Objects.equals(this.service, that.service)
|
||||
Objects.equals(this.serviceIdent, that.serviceIdent) &&
|
||||
Objects.equals(this.configChecksum, that.configChecksum)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -96,7 +103,8 @@ class Flow extends AbstractModel {
|
|||
*/
|
||||
@Override
|
||||
int hashCode() {
|
||||
return Objects.hash(this.id, this.artifact, this.deployments, this.service)
|
||||
return Objects.hash(this.id, this.artifact, this.deployments,
|
||||
this.serviceIdent, this.configChecksum)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -106,7 +114,8 @@ class Flow extends AbstractModel {
|
|||
*/
|
||||
@Override
|
||||
String toString() {
|
||||
return "id = ${id}, artifact: ${artifact}, deployments: ${deployments}, service: ${service}"
|
||||
return "id = ${id}, artifact: ${artifact}, deployments: ${deployments}, " +
|
||||
"serviceIdent: ${serviceIdent}, configChecksum: ${configChecksum}"
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
package deploydb.models
|
||||
|
||||
import deploydb.ModelType
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import javax.persistence.Column
|
||||
import javax.persistence.Entity
|
||||
import javax.persistence.EnumType
|
||||
import javax.persistence.Enumerated
|
||||
import javax.persistence.Table
|
||||
import org.hibernate.validator.constraints.NotEmpty
|
||||
|
||||
/**
|
||||
* Representation class for the concept of an ModelConfig
|
||||
*/
|
||||
@Entity
|
||||
@Table(name='modelConfigs')
|
||||
class ModelConfig extends AbstractModel {
|
||||
|
||||
@NotEmpty
|
||||
@Column(name="checksum", nullable=false)
|
||||
@JsonProperty
|
||||
String checksum
|
||||
|
||||
@NotEmpty
|
||||
@Column(name="contents", nullable=false)
|
||||
@JsonProperty
|
||||
String contents
|
||||
|
||||
@NotEmpty
|
||||
@Column(name='ident', nullable=false)
|
||||
@JsonProperty
|
||||
String ident
|
||||
|
||||
@Column(name='modelType', nullable=false)
|
||||
@Enumerated(EnumType.ORDINAL)
|
||||
@JsonProperty
|
||||
ModelType modelType
|
||||
|
||||
/**
|
||||
* Empty constructor used by Jackson for object deserialization
|
||||
*/
|
||||
ModelConfig() { }
|
||||
|
||||
/**
|
||||
* Default constructor to be used by DeployDB internally. It accepts all
|
||||
* of the required parameters for the database
|
||||
*/
|
||||
ModelConfig(String checksum,
|
||||
String contents,
|
||||
String ident,
|
||||
ModelType modelType) {
|
||||
this.checksum = checksum
|
||||
this.contents = contents
|
||||
this.ident = ident
|
||||
this.modelType = modelType
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean equals(Object o) {
|
||||
/* First object identity */
|
||||
if (this.is(o)) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (!(o instanceof ModelConfig)) {
|
||||
return false
|
||||
}
|
||||
|
||||
final ModelConfig that = (ModelConfig)o
|
||||
|
||||
return Objects.equals(this.id, that.id) &&
|
||||
Objects.equals(this.checksum, that.checksum) &&
|
||||
Objects.equals(this.contents, that.contents) &&
|
||||
Objects.equals(this.ident, that.ident) &&
|
||||
Objects.equals(this.modelType, that.modelType)
|
||||
}
|
||||
|
||||
@Override
|
||||
int hashCode() {
|
||||
return Objects.hash(this.id, this.checksum, this.contents,
|
||||
this.ident, this.modelType)
|
||||
}
|
||||
|
||||
@Override
|
||||
String toString() {
|
||||
return "id: ${id}, checksum: ${checksum}, contents: \"${contents}\", " +
|
||||
"ident: ${ident}, modelType: ${modelType}"
|
||||
|
||||
}
|
||||
}
|
|
@ -31,7 +31,7 @@ class WebhookManagerSpec extends Specification {
|
|||
WebhookManager m = new WebhookManager()
|
||||
|
||||
expect:
|
||||
m.sendDeploymentWebhook("created", null, null) == true
|
||||
m.sendDeploymentWebhook("created", null, null, null) == true
|
||||
}
|
||||
|
||||
def "sendDeploymentWebhook() should push correct hook requests when global webhooks are configured"() {
|
||||
|
@ -43,7 +43,7 @@ class WebhookManagerSpec extends Specification {
|
|||
[], [])
|
||||
WebhookManager m = new WebhookManager()
|
||||
m.queue = new InMemoryQueue()
|
||||
m.webhook = new deploydb.models.Webhook.Webhook(webhookDeployment, null)
|
||||
models.Webhook.Webhook gwh = new models.Webhook.Webhook(webhookDeployment, null)
|
||||
|
||||
// mock the queue push
|
||||
int counter = 0
|
||||
|
@ -53,7 +53,7 @@ class WebhookManagerSpec extends Specification {
|
|||
}
|
||||
|
||||
when:
|
||||
m.sendDeploymentWebhook("created", null, new DeploymentWebhookMapper())
|
||||
m.sendDeploymentWebhook("created", gwh, null, new DeploymentWebhookMapper())
|
||||
|
||||
then:
|
||||
counter == 2
|
||||
|
@ -68,7 +68,7 @@ class WebhookManagerSpec extends Specification {
|
|||
null, null)
|
||||
WebhookManager m = new WebhookManager()
|
||||
m.queue = new InMemoryQueue()
|
||||
deploydb.models.Webhook.Webhook ewh = new deploydb.models.Webhook.Webhook(webhookDeployment, null)
|
||||
models.Webhook.Webhook ewh = new models.Webhook.Webhook(webhookDeployment, null)
|
||||
|
||||
// mock the queue push
|
||||
int counter = 0
|
||||
|
@ -78,7 +78,7 @@ class WebhookManagerSpec extends Specification {
|
|||
}
|
||||
|
||||
when:
|
||||
m.sendDeploymentWebhook("created", ewh, new DeploymentWebhookMapper())
|
||||
m.sendDeploymentWebhook("created", null, ewh, new DeploymentWebhookMapper())
|
||||
|
||||
then:
|
||||
counter == 2
|
||||
|
@ -93,8 +93,8 @@ class WebhookManagerSpec extends Specification {
|
|||
null, null)
|
||||
WebhookManager m = new WebhookManager()
|
||||
m.queue = new InMemoryQueue()
|
||||
m.webhook = new deploydb.models.Webhook.Webhook(webhookDeployment, null)
|
||||
deploydb.models.Webhook.Webhook ewh = new deploydb.models.Webhook.Webhook(webhookDeployment, null)
|
||||
models.Webhook.Webhook gwh = new models.Webhook.Webhook(webhookDeployment, null)
|
||||
models.Webhook.Webhook ewh = new models.Webhook.Webhook(webhookDeployment, null)
|
||||
|
||||
// mock the queue push
|
||||
int counter = 0
|
||||
|
@ -104,7 +104,7 @@ class WebhookManagerSpec extends Specification {
|
|||
}
|
||||
|
||||
when:
|
||||
m.sendDeploymentWebhook("created", ewh, new DeploymentWebhookMapper())
|
||||
m.sendDeploymentWebhook("created", gwh, ewh, new DeploymentWebhookMapper())
|
||||
|
||||
then:
|
||||
counter == 4
|
||||
|
@ -126,8 +126,8 @@ class WebhookManagerSpec extends Specification {
|
|||
["http://www.localhost.com/test-build", "http://www.localhost.com/test1-build"],
|
||||
null,
|
||||
null, null)
|
||||
m.webhook = new deploydb.models.Webhook.Webhook(webhookDeployment, null)
|
||||
deploydb.models.Webhook.Webhook ewh = new deploydb.models.Webhook.Webhook(environWebhookDeployment, null)
|
||||
models.Webhook.Webhook gwh = new models.Webhook.Webhook(webhookDeployment, null)
|
||||
models.Webhook.Webhook ewh = new models.Webhook.Webhook(environWebhookDeployment, null)
|
||||
|
||||
// mock the queue push
|
||||
int counter = 0
|
||||
|
@ -137,7 +137,7 @@ class WebhookManagerSpec extends Specification {
|
|||
}
|
||||
|
||||
when:
|
||||
m.sendDeploymentWebhook("created", ewh, new DeploymentWebhookMapper())
|
||||
m.sendDeploymentWebhook("created", gwh, ewh, new DeploymentWebhookMapper())
|
||||
|
||||
then:
|
||||
counter == 2
|
||||
|
@ -160,8 +160,8 @@ class WebhookManagerSpec extends Specification {
|
|||
["http://www.localhost.com/test-build", "http://www.localhost.com/test1-build"],
|
||||
null, null)
|
||||
|
||||
m.webhook = new deploydb.models.Webhook.Webhook(webhookDeployment, null)
|
||||
deploydb.models.Webhook.Webhook ewh = new deploydb.models.Webhook.Webhook(environWebhookDeployment, null)
|
||||
models.Webhook.Webhook gwh = new models.Webhook.Webhook(webhookDeployment, null)
|
||||
models.Webhook.Webhook ewh = new models.Webhook.Webhook(environWebhookDeployment, null)
|
||||
|
||||
// mock the queue push
|
||||
int counter = 0
|
||||
|
@ -171,7 +171,7 @@ class WebhookManagerSpec extends Specification {
|
|||
}
|
||||
|
||||
when:
|
||||
m.sendDeploymentWebhook("created", ewh, new DeploymentWebhookMapper())
|
||||
m.sendDeploymentWebhook("created", gwh, ewh, new DeploymentWebhookMapper())
|
||||
|
||||
then:
|
||||
counter == 2
|
||||
|
@ -182,7 +182,7 @@ class WebhookManagerSpec extends Specification {
|
|||
WebhookManager m = new WebhookManager()
|
||||
|
||||
expect:
|
||||
m.sendPromotionWebhook("completed", null, null) == true
|
||||
m.sendPromotionWebhook("completed", null, null, null) == true
|
||||
}
|
||||
|
||||
def "sendPromotiontWebhook() should push correct hook requests when global webhooks are configured"() {
|
||||
|
@ -193,7 +193,7 @@ class WebhookManagerSpec extends Specification {
|
|||
["http://www.localhost.com/test-build", "http://www.localhost.com/test1-build"])
|
||||
WebhookManager m = new WebhookManager()
|
||||
m.queue = new InMemoryQueue()
|
||||
m.webhook = new deploydb.models.Webhook.Webhook(null, webhookPromotion)
|
||||
models.Webhook.Webhook gwh = new models.Webhook.Webhook(null, webhookPromotion)
|
||||
|
||||
// mock the queue push
|
||||
int counter = 0
|
||||
|
@ -203,7 +203,7 @@ class WebhookManagerSpec extends Specification {
|
|||
}
|
||||
|
||||
when:
|
||||
m.sendPromotionWebhook("completed", null, new DeploymentWebhookMapper())
|
||||
m.sendPromotionWebhook("completed", gwh, null, new DeploymentWebhookMapper())
|
||||
|
||||
then:
|
||||
counter == 2
|
||||
|
@ -218,7 +218,7 @@ class WebhookManagerSpec extends Specification {
|
|||
|
||||
WebhookManager m = new WebhookManager()
|
||||
m.queue = new InMemoryQueue()
|
||||
deploydb.models.Webhook.Webhook ewh = new deploydb.models.Webhook.Webhook(null, webhookPromotion)
|
||||
models.Webhook.Webhook ewh = new models.Webhook.Webhook(null, webhookPromotion)
|
||||
|
||||
// mock the queue push
|
||||
int counter = 0
|
||||
|
@ -228,7 +228,7 @@ class WebhookManagerSpec extends Specification {
|
|||
}
|
||||
|
||||
when:
|
||||
m.sendPromotionWebhook("completed", ewh, new DeploymentWebhookMapper())
|
||||
m.sendPromotionWebhook("completed", null, ewh, new DeploymentWebhookMapper())
|
||||
|
||||
then:
|
||||
counter == 2
|
||||
|
@ -243,8 +243,8 @@ class WebhookManagerSpec extends Specification {
|
|||
|
||||
WebhookManager m = new WebhookManager()
|
||||
m.queue = new InMemoryQueue()
|
||||
m.webhook = new deploydb.models.Webhook.Webhook(null, webhookPromotion)
|
||||
deploydb.models.Webhook.Webhook ewh = new deploydb.models.Webhook.Webhook(null, webhookPromotion)
|
||||
models.Webhook.Webhook gwh = new models.Webhook.Webhook(null, webhookPromotion)
|
||||
models.Webhook.Webhook ewh = new models.Webhook.Webhook(null, webhookPromotion)
|
||||
|
||||
// mock the queue push
|
||||
int counter = 0
|
||||
|
@ -254,7 +254,7 @@ class WebhookManagerSpec extends Specification {
|
|||
}
|
||||
|
||||
when:
|
||||
m.sendPromotionWebhook("completed", ewh, new DeploymentWebhookMapper())
|
||||
m.sendPromotionWebhook("completed", gwh, ewh, new DeploymentWebhookMapper())
|
||||
|
||||
then:
|
||||
counter == 4
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package deploydb
|
||||
|
||||
import deploydb.dao.FlowDAO
|
||||
import deploydb.dao.ModelConfigDAO
|
||||
import deploydb.models.Flow
|
||||
import spock.lang.*
|
||||
|
||||
|
@ -20,14 +21,16 @@ class workFlowWithArgsSpec extends Specification {
|
|||
private String baseCfgDirName = "./build/tmp/config"
|
||||
private DeployDBApp app = new DeployDBApp()
|
||||
private WorkFlow workFlow
|
||||
private FlowDAO dao = Mock(FlowDAO)
|
||||
private FlowDAO fdao = Mock(FlowDAO)
|
||||
private ModelConfigDAO mdao = Mock(ModelConfigDAO)
|
||||
|
||||
def setup() {
|
||||
app.webhooksManager = new WebhookManager()
|
||||
app.configDirectory = baseCfgDirName
|
||||
app.configChecksum = null
|
||||
workFlow = new WorkFlow(app)
|
||||
workFlow.initializeRegistry()
|
||||
workFlow.flowDAO = dao
|
||||
workFlow.flowDAO = fdao
|
||||
workFlow.modelConfigDAO = mdao
|
||||
}
|
||||
|
||||
def cleanup() {
|
||||
|
@ -52,6 +55,21 @@ description: "Basic Smoke test for the Basic Service"
|
|||
promotionFile.write(fileContents)
|
||||
}
|
||||
|
||||
def createAnotherPromotionConfigFile() {
|
||||
String fileContents = """
|
||||
type: AdvancedPromotion
|
||||
description: "Advanced Smoke test for the Basic Service"
|
||||
"""
|
||||
/* Create temp file */
|
||||
File promotionsDir = new File("${baseCfgDirName}/promotions")
|
||||
if (!promotionsDir.exists()) {
|
||||
promotionsDir.mkdirs()
|
||||
}
|
||||
|
||||
File promotionFile = new File(promotionsDir, "advancedPromo.yml")
|
||||
promotionFile.write(fileContents)
|
||||
}
|
||||
|
||||
def createEnvironmentConfigFile() {
|
||||
String fileContents = """
|
||||
description: "Basic Environment"
|
||||
|
@ -142,7 +160,8 @@ promotion:
|
|||
createPipelineConfigFile()
|
||||
createServiceConfigFile()
|
||||
createWebhookConfigFile()
|
||||
workFlow.loadConfigModels(false)
|
||||
workFlow.loadConfigModels()
|
||||
mdao.persist(_) >> _
|
||||
|
||||
expect:
|
||||
workFlow.promotionRegistry.getAll().size() == 1
|
||||
|
@ -153,14 +172,15 @@ promotion:
|
|||
workFlow.pipelineRegistry.get("basicPipe").ident == "basicPipe"
|
||||
workFlow.serviceRegistry.getAll().size() == 1
|
||||
workFlow.serviceRegistry.get("basicServ").ident == "basicServ"
|
||||
workFlow.deployDBApp.webhooksManager != null
|
||||
workFlow.globalWebhook != null
|
||||
}
|
||||
|
||||
def "If promotion is missing, then loading pipeline in loadConfigModels throws an exception"() {
|
||||
when:
|
||||
createEnvironmentConfigFile()
|
||||
createPipelineConfigFile()
|
||||
workFlow.loadConfigModels(false)
|
||||
workFlow.loadConfigModels()
|
||||
mdao.persist(_) >> _
|
||||
|
||||
then:
|
||||
thrown(IllegalArgumentException)
|
||||
|
@ -170,7 +190,8 @@ promotion:
|
|||
when:
|
||||
createPromotionConfigFile()
|
||||
createPipelineConfigFile()
|
||||
workFlow.loadConfigModels(false)
|
||||
workFlow.loadConfigModels()
|
||||
mdao.persist(_) >> _
|
||||
|
||||
then:
|
||||
thrown(IllegalArgumentException)
|
||||
|
@ -181,47 +202,50 @@ promotion:
|
|||
createPromotionConfigFile()
|
||||
createEnvironmentConfigFile()
|
||||
createServiceConfigFile()
|
||||
workFlow.loadConfigModels(false)
|
||||
workFlow.loadConfigModels()
|
||||
mdao.persist(_) >> _
|
||||
|
||||
then:
|
||||
thrown(IllegalArgumentException)
|
||||
}
|
||||
|
||||
|
||||
def "Reload entire config from a directory and make sure it passes"() {
|
||||
def "Reload unchanged config from a directory and make sure its ignored"() {
|
||||
given:
|
||||
createPromotionConfigFile()
|
||||
createEnvironmentConfigFile()
|
||||
createPipelineConfigFile()
|
||||
createServiceConfigFile()
|
||||
createWebhookConfigFile()
|
||||
workFlow.loadConfigModels(false)
|
||||
1 * dao.getActiveFlowsCount() >> 0
|
||||
workFlow.loadConfigModels()
|
||||
String oldChecksum = app.configChecksum
|
||||
mdao.persist(_) >> _
|
||||
|
||||
when:
|
||||
workFlow.loadConfigModels(true)
|
||||
workFlow.loadConfigModels()
|
||||
|
||||
then:
|
||||
workFlow.promotionRegistry.getAll().size() == 1
|
||||
workFlow.promotionRegistry.get("basicPromo").ident == "basicPromo"
|
||||
workFlow.environmentRegistry.getAll().size() == 1
|
||||
workFlow.environmentRegistry.get("basicEnv").ident == "basicEnv"
|
||||
workFlow.pipelineRegistry.getAll().size() == 1
|
||||
workFlow.pipelineRegistry.get("basicPipe").ident == "basicPipe"
|
||||
workFlow.serviceRegistry.getAll().size() == 1
|
||||
workFlow.serviceRegistry.get("basicServ").ident == "basicServ"
|
||||
workFlow.deployDBApp.webhooksManager != null
|
||||
app.configChecksum != null
|
||||
oldChecksum == app.configChecksum
|
||||
}
|
||||
|
||||
def "Attempt to reload config with active flows throws an exception"() {
|
||||
def "Reload changed config from a directory and make sure it passes"() {
|
||||
given:
|
||||
//List<models.Flow> flows = [new models.Flow()]
|
||||
1 * dao.getActiveFlowsCount() >> 1
|
||||
createPromotionConfigFile()
|
||||
createEnvironmentConfigFile()
|
||||
createPipelineConfigFile()
|
||||
createServiceConfigFile()
|
||||
createWebhookConfigFile()
|
||||
workFlow.loadConfigModels()
|
||||
String oldChecksum = app.configChecksum
|
||||
createAnotherPromotionConfigFile()
|
||||
mdao.persist(_) >> _
|
||||
|
||||
when:
|
||||
workFlow.loadConfigModels(true)
|
||||
workFlow.loadConfigModels()
|
||||
|
||||
then:
|
||||
thrown(Exception)
|
||||
app.configChecksum != null
|
||||
oldChecksum != app.configChecksum
|
||||
}
|
||||
}
|
|
@ -37,13 +37,13 @@ class FlowSpecWithArgsSpec extends Specification {
|
|||
|
||||
flow.artifact = artifact
|
||||
flow.deployments = deployments
|
||||
flow.service = service
|
||||
flow.serviceIdent = service
|
||||
|
||||
|
||||
expect:
|
||||
flow.artifact == artifact
|
||||
flow.deployments == deployments
|
||||
flow.service == service
|
||||
flow.serviceIdent == service
|
||||
}
|
||||
|
||||
def "equality passes for same deployments"() {
|
||||
|
@ -139,8 +139,8 @@ class FlowSpecWithArgsSpec extends Specification {
|
|||
Flow firstFlow = new Flow()
|
||||
Flow secondFlow = new Flow()
|
||||
|
||||
firstFlow.service = service
|
||||
secondFlow.service = service
|
||||
firstFlow.serviceIdent = service
|
||||
secondFlow.serviceIdent = service
|
||||
|
||||
expect:
|
||||
firstFlow == secondFlow
|
||||
|
@ -152,8 +152,8 @@ class FlowSpecWithArgsSpec extends Specification {
|
|||
Flow firstFlow = new Flow()
|
||||
Flow secondFlow = new Flow()
|
||||
|
||||
firstFlow.service = firstService
|
||||
secondFlow.service = secondService
|
||||
firstFlow.serviceIdent = firstService
|
||||
secondFlow.serviceIdent = secondService
|
||||
|
||||
expect:
|
||||
firstFlow != secondFlow
|
||||
|
@ -251,8 +251,8 @@ class FlowSpecWithArgsSpec extends Specification {
|
|||
Flow firstFlow = new Flow()
|
||||
Flow secondFlow = new Flow()
|
||||
|
||||
firstFlow.service = service
|
||||
secondFlow.service = service
|
||||
firstFlow.serviceIdent = service
|
||||
secondFlow.serviceIdent = service
|
||||
|
||||
expect:
|
||||
firstFlow.hashCode() == secondFlow.hashCode()
|
||||
|
@ -264,8 +264,8 @@ class FlowSpecWithArgsSpec extends Specification {
|
|||
Flow firstFlow = new Flow()
|
||||
Flow secondFlow = new Flow()
|
||||
|
||||
firstFlow.service = firstService
|
||||
secondFlow.service = secondService
|
||||
firstFlow.serviceIdent = firstService
|
||||
secondFlow.serviceIdent = secondService
|
||||
|
||||
expect:
|
||||
firstFlow.hashCode() != secondFlow.hashCode()
|
||||
|
|
Loading…
Reference in New Issue