Commit 6818ebd4 authored by Peter Harrison's avatar Peter Harrison
parents ba5d64df 3992cde8
......@@ -72,7 +72,7 @@
<type>jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
......@@ -89,7 +89,7 @@
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring.version}</version>
</dependency>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
......@@ -316,7 +316,7 @@
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.2.5</version>
<version>4.3.6</version>
</dependency>
<dependency>
......@@ -363,6 +363,30 @@
<version>2.2.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-elasticloadbalancing</artifactId>
<version>1.10.37</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-iam</artifactId>
<version>1.10.37</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-cloudfront</artifactId>
<version>1.10.37</version>
</dependency>
<dependency>
<groupId>com.sun.xml.stream</groupId>
<artifactId>sjsxp</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>
......@@ -415,4 +439,36 @@
</plugins>
</build>
<reporting>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>3.0.3</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>2.7</version>
<configuration>
<dependencyLocationsEnabled>false</dependencyLocationsEnabled>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.6</version>
<configuration>
<formats>
<format>html</format>
<format>xml</format>
</formats>
</configuration>
</plugin>
</plugins>
</reporting>
</project>
......@@ -42,6 +42,7 @@ import nz.net.orcon.kanban.controllers.BoardsCache;
import nz.net.orcon.kanban.controllers.CardController;
import nz.net.orcon.kanban.controllers.NotificationController;
import nz.net.orcon.kanban.controllers.ResourceNotFoundException;
import nz.net.orcon.kanban.controllers.RuleCache;
import nz.net.orcon.kanban.controllers.URI;
import nz.net.orcon.kanban.model.Action;
import nz.net.orcon.kanban.model.Board;
......@@ -72,6 +73,9 @@ public class AutomationEngine {
@Autowired
BoardsCache boardsCache;
@Autowired
RuleCache ruleCache;
@Autowired
DateInterpreter dateInterpreter;
......@@ -96,24 +100,13 @@ public class AutomationEngine {
try {
card = cardController.getCard(cardHolder.getBoardId(),
null, cardHolder.getCardId(), "full");
board = boardsCache.getItem(cardHolder.getBoardId());
} catch (ResourceNotFoundException e) {
LOG.info("Resource no longer exists: " + cardHolder.toString());
return;
}
if (board == null) {
LOG.warn("Board Not Found: " + cardHolder.getBoardId());
return;
}
Map<String, Rule> rules = board.getRules();
if (rules == null) {
LOG.warn("Rules Not Found: " + cardHolder.getBoardId());
return;
}
Map<String,Rule> rules = getRulesFromBoard(cardHolder.getBoardId());
LOG.info("Automation Examining :" + card.getPath());
evaluateTaskRules(rules,card);
......@@ -122,7 +115,7 @@ public class AutomationEngine {
Collection<CardEvent> alerts = cardController.getAlerts(card.getBoard(), card.getPhase(), card.getId().toString());
for( CardEvent alert : alerts){
if(alert==null){
LOG.equals("Alert NULL inside Loop");
LOG.error("Alert NULL inside Loop");
}
if("alert".equals(alert.getLevel())){
......@@ -136,6 +129,19 @@ public class AutomationEngine {
executeTaskRules(rules,card);
}
private Map<String,Rule> getRulesFromBoard(String boardId) throws Exception{
Map<String, String> ruleList = ruleCache.list(boardId,"");
Map<String,Rule> rules = new HashMap<String,Rule>();
for( String ruleId : ruleList.keySet()){
Rule rule = ruleCache.getItem(boardId, ruleId);
if(rule!=null){
rules.put(ruleId, rule);
}
}
return rules;
}
private void executeCompulsoryRules(Map<String, Rule> rules, Card card) throws Exception {
for (Rule rule : rules.values()) {
if(rule.getCompulsory() &&
......@@ -275,28 +281,18 @@ public class AutomationEngine {
public Map<String,Map<String,Boolean>> explain(CardHolder cardHolder) throws Exception {
Map<String,Map<String,Boolean>> result = new HashMap<String,Map<String,Boolean>>();
Map<String,Map<String,Boolean>> result = new HashMap<String,Map<String,Boolean>>();
Card card = null;
Board board = null;
try {
card = cardController.getCard(cardHolder.getBoardId(),
null, cardHolder.getCardId(),"full");
board = boardsCache.getItem(cardHolder.getBoardId());
} catch (ResourceNotFoundException e) {
throw new Exception("Resource no longer exists: " + cardHolder.toString());
}
if (board == null) {
throw new Exception("Board Not Found: " + cardHolder.toString());
}
Map<String, Rule> rules = board.getRules();
if (rules == null) {
throw new Exception("Rules Not Found: " + cardHolder.getBoardId());
throw new Exception("Resource Not Found: " + cardHolder.toString());
}
Map<String, Rule> rules = getRulesFromBoard(cardHolder.getBoardId());
Set<Entry<String, Rule>> entrySet = rules.entrySet();
LOG.info("Explaining :" + card.getPath());
......@@ -694,18 +690,8 @@ public class AutomationEngine {
LOG.info("Executing Actions on board:" + boardId + " Rule " + ruleId);
// Get Rule.
Board board = this.boardsCache.getItem(boardId);
if(board==null){
LOG.warn("Execute Actions: Board Not Found: "+ boardId);
return;
}
Rule rule = board.getRules().get(ruleId);
if(rule==null){
LOG.warn("Execute Actions: Rule Not Found: "+ boardId + "/" + ruleId);
return;
}
// Get Rule.
Rule rule = ruleCache.getItem(boardId, ruleId);
List<Action> sortedActionList = getSortedActions(rule.getActions());
......@@ -732,7 +718,7 @@ public class AutomationEngine {
public void executeActions(Card card, Rule rule) throws Exception {
LOG.info("Executing Actions on Card :" + card.getPath());
LOG.info("Executing ActionChain on Card :" + card.getPath() + " rule " + rule.getId());
Map<String, Object> context = card.getFields();
context.put("boardid", card.getBoard());
......@@ -775,37 +761,42 @@ public class AutomationEngine {
private void raiseAlertOnError(Throwable e, Rule rule, Action action, Card card) throws Exception{
String causeMessage = "";
StringBuilder message = new StringBuilder();
message.append(rule.getName());
message.append(" ");
message.append(action.getName());
message.append(" calling: ");
message.append(action.getType());
message.append(".");
message.append(action.getResource());
message.append(".");
message.append(action.getMethod());
message.append(" caused ");
Throwable cause = e;
while(cause!=null){
if( cause.getMessage()!=null){
causeMessage = causeMessage + "(" + cause.getMessage() + ") ";
message.append("(");
message.append(cause.getMessage());
message.append(") ");
}
cause = cause.getCause();
}
String message = rule.getName()
+ " " + action.getName()
+ " calling: " + action.getType()
+ "." + action.getResource()
+ "." + action.getMethod()
+ " caused " + causeMessage;
if(card!=null){
if( cardController!=null){
cardController.saveAlert(
card.getBoard(),
card.getPhase(),
card.getId().toString(),
message,
message.toString(),
"alert");
}
LOG.warn( "Automation Exception - Card " + card.getId() + " " + message, e);
LOG.warn( "Automation Exception - Card " + card.getId() + " " + message.toString(), e);
} else {
LOG.warn( "Automation Exception " + message, e);
LOG.warn( "Automation Exception " + message.toString(), e);
}
}
private void outputContext( Map<String,Object> context){
......
......@@ -115,7 +115,7 @@ public class ClusterManager {
*/
@Scheduled( fixedDelay=30000l )
public void pollLeader() throws Exception{
if(!this.leader){
if(!isLeader()){
this.executeChallenge();
}
}
......@@ -137,28 +137,28 @@ public class ClusterManager {
Message coupMessage = coupSync.receiveMessage(10000l);
boolean newLeader = (coupMessage==null);
if( this.leader!=newLeader){
if( isLeader()!=newLeader){
if(newLeader){
LOG.warn("FAILOVER: Node promoted to MASTER.");
this.leader = true;
setLeader(true);
this.jcrObserver.start();
this.timerManager.startup();
} else {
LOG.warn("FAILOVER: Node demoted to worker.");
this.leader = false;
setLeader(false);
this.jcrObserver.stop();
this.timerManager.stopAll();
}
}
return this.leader;
return isLeader();
}
public void setLeader(boolean leader) {
public synchronized void setLeader(boolean leader) {
this.leader = leader;
}
public boolean isLeader() {
public synchronized boolean isLeader() {
return leader;
}
......
/**
* GRAVITY WORKFLOW AUTOMATION
* (C) Copyright 2015 Orcon Limited
* (C) Copyright 2015 Peter Harrison
*
* This file is part of Gravity Workflow Automation.
*
......@@ -29,7 +30,8 @@ import java.util.Map;
import javax.annotation.PreDestroy;
import nz.net.orcon.kanban.controllers.BoardsCache;
import nz.net.orcon.kanban.model.Board;
import nz.net.orcon.kanban.controllers.ResourceNotFoundException;
import nz.net.orcon.kanban.controllers.RuleCache;
import nz.net.orcon.kanban.model.Condition;
import nz.net.orcon.kanban.model.ConditionType;
import nz.net.orcon.kanban.model.Rule;
......@@ -71,6 +73,9 @@ public class TimerManager {
@Autowired
private BoardsCache boardsCache;
@Autowired
private RuleCache ruleCache;
@Autowired
OcmMapperFactory ocmFactory;
......@@ -96,37 +101,37 @@ public class TimerManager {
if(this.scheduler==null){
return;
}
Board board = boardsCache.getItem(boardId);
if( board==null){
LOG.warn("Board Not Found when Loading Timer: " + boardId);
Map<String, String> rules;
try {
rules = ruleCache.list(boardId,"");
} catch (javax.jcr.PathNotFoundException e ){
LOG.info("No Rule for Board: "+ boardId);
return;
}
// Delete All Existing Timers for this board
List<String> jobNames = Arrays.asList(this.scheduler.getJobNames(boardId));
for( String jobName : jobNames){
this.scheduler.deleteJob(jobName, boardId);
}
// Start Timers
Map<String,Rule> rules = board.getRules();
if( rules==null){
LOG.warn("Board Rules Not Found when Loading Timer: " + boardId);
return;
}
for( Rule rule : rules.values()){
if(null != rule.getAutomationConditions()){
for( Condition condition : rule.getAutomationConditions().values()) {
if( ConditionType.TIMER.equals(condition.getConditionType())){
activateTimer( board.getId(), rule.getId(), condition.getValue());
// Start Timers
for( String ruleId : rules.keySet()){
try {
Rule rule = ruleCache.getItem(boardId,ruleId);
if(null != rule.getAutomationConditions()){
for( Condition condition : rule.getAutomationConditions().values()) {
if( ConditionType.TIMER.equals(condition.getConditionType())){
activateTimer( boardId, rule.getId(), condition.getValue());
LOG.info("Timer Loaded: " + boardId + "." + rule.getId());
}
}
}
} catch(ResourceNotFoundException e){
LOG.warn("Rule not found: " + boardId + "." + ruleId);
}
}
LOG.info("Board Timers Loaded for Board: " + boardId);
}
private void activateTimer( String boardId, String ruleId, String schedule) throws Exception{
......
package nz.net.orcon.kanban.automation.actions;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import com.amazonaws.AmazonWebServiceClient;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.cloudfront.AmazonCloudFrontClient;
import com.amazonaws.services.cloudfront.model.CookiePreference;
import com.amazonaws.services.cloudfront.model.CreateDistributionRequest;
import com.amazonaws.services.cloudfront.model.CreateDistributionResult;
import com.amazonaws.services.cloudfront.model.CustomOriginConfig;
import com.amazonaws.services.cloudfront.model.DefaultCacheBehavior;
import com.amazonaws.services.cloudfront.model.DistributionConfig;
import com.amazonaws.services.cloudfront.model.ForwardedValues;
import com.amazonaws.services.cloudfront.model.Headers;
import com.amazonaws.services.cloudfront.model.Origin;
import com.amazonaws.services.cloudfront.model.OriginProtocolPolicy;
import com.amazonaws.services.cloudfront.model.Origins;
import com.amazonaws.services.cloudfront.model.TrustedSigners;
import com.amazonaws.services.cloudfront.model.ViewerCertificate;
import com.amazonaws.services.cloudfront.model.ViewerProtocolPolicy;
import com.amazonaws.services.elasticloadbalancing.AmazonElasticLoadBalancingClient;
import com.amazonaws.services.elasticloadbalancing.model.DescribeLoadBalancersResult;
import com.amazonaws.services.elasticloadbalancing.model.LoadBalancerDescription;
import com.amazonaws.services.elasticloadbalancing.model.SetLoadBalancerListenerSSLCertificateRequest;
import com.amazonaws.services.identitymanagement.AmazonIdentityManagementClient;
import com.amazonaws.services.identitymanagement.model.GetAccountSummaryResult;
import com.amazonaws.services.identitymanagement.model.ListServerCertificatesResult;
import com.amazonaws.services.identitymanagement.model.ServerCertificateMetadata;
import com.amazonaws.services.identitymanagement.model.UploadServerCertificateRequest;
import com.amazonaws.services.identitymanagement.model.UploadServerCertificateResult;
public class AwsAutomationAction {
@Autowired
private AmazonElasticLoadBalancingClient loadBalanceClient;
@Autowired
private AmazonIdentityManagementClient identityClient;
@Autowired
private AmazonCloudFrontClient cloudFrontClient;
public List<ServerCertificateMetadata> getCertificates(){
ListServerCertificatesResult listSigningCertificates = identityClient.listServerCertificates();
return listSigningCertificates.getServerCertificateMetadataList();
}
public String loadSSLCertificate(
String certificateName,
String certificate,
String privateKey,
String path){
String certificateId = this.getCertificateId(certificateName);
if(certificateId==null){
UploadServerCertificateRequest certificateRequest =
new UploadServerCertificateRequest( certificateName, certificate, privateKey);
certificateRequest.setPath(path);
UploadServerCertificateResult uploadServerCertificate =
getIdentityClient().uploadServerCertificate(certificateRequest);
certificateId = uploadServerCertificate.getServerCertificateMetadata().getServerCertificateId();
}
return certificateId;
}
public void setLoadBalancerCertificate( String loadBalancerName, String certificateId, Integer port ){
System.out.println( "LB CertID: " + certificateId);
this.loadBalanceClient.setRegion(Region.getRegion(Regions.AP_SOUTHEAST_2));
SetLoadBalancerListenerSSLCertificateRequest lbRequest =
new SetLoadBalancerListenerSSLCertificateRequest(
loadBalancerName,
port,
certificateId);
getLoadBalanceClient().setLoadBalancerListenerSSLCertificate(lbRequest);
}
public boolean isSSLCertificateLoaded( String certificateName ){
List<ServerCertificateMetadata> certificates = this.getCertificates();
for( ServerCertificateMetadata certificate : certificates){
if(certificate.getServerCertificateName().equals(certificateName)) {
return true;
}
}
return false;
}
public String getCertificateId( String certificateName){
List<ServerCertificateMetadata> certificates = this.getCertificates();
for( ServerCertificateMetadata certificate : certificates){
if(certificate.getServerCertificateName().equals(certificateName)) {
return certificate.getServerCertificateId();
}
}
return null;
}
public Collection<String> getLoadBalancerList(){
DescribeLoadBalancersResult loadBalancers = this.loadBalanceClient.describeLoadBalancers();
System.out.println(loadBalancers.toString());
Collection returnList = new ArrayList<String>();
List<LoadBalancerDescription> loadBalancerDescriptions = loadBalancers.getLoadBalancerDescriptions();
for( LoadBalancerDescription desc : loadBalancerDescriptions){
returnList.add(desc.getDNSName());
}
return returnList;
}
public String createCloudFrontDistribution(
String domainName,
String certificateId,
String originId,
String callerReference) {
CreateDistributionRequest createDistributionRequest = new CreateDistributionRequest();
DistributionConfig distributionConfig = new DistributionConfig();
DefaultCacheBehavior defaultCacheBehavior = new DefaultCacheBehavior();
ViewerCertificate viewerCertificate = new ViewerCertificate();
ForwardedValues forwardedValues = new ForwardedValues();
Headers headers = new Headers();
TrustedSigners trustedSigners = new TrustedSigners();
CookiePreference cookies = new CookiePreference();
Origin origin = new Origin();
Origins origins = new Origins();
Collection<Origin> items = new ArrayList<Origin>();
CustomOriginConfig customOriginConfig = new CustomOriginConfig();
// Origins
customOriginConfig.setHTTPPort(80);
customOriginConfig.setHTTPSPort(443);
customOriginConfig.setOriginProtocolPolicy(OriginProtocolPolicy.MatchViewer);
origin.setDomainName(domainName);
origin.setId(originId);
origin.setOriginPath("");
origin.setCustomOriginConfig(customOriginConfig);
items.add(origin);
origins.setItems(items);
origins.setQuantity(1);
// Forwarded Values & Headers & Cookies
cookies.setForward("all");
Collection<String> headerItems = new ArrayList<String>();
headers.setItems(headerItems);
headers.setQuantity(0);
forwardedValues.setHeaders(headers);
forwardedValues.setQueryString(false);
forwardedValues.setCookies(cookies);
// Trusted Signers
trustedSigners.setEnabled(false);
trustedSigners.setQuantity(0);
// Viewer Certificate
viewerCertificate.setIAMCertificateId(certificateId);
// Default Cache BEhaviour
defaultCacheBehavior.setMinTTL(30l);
defaultCacheBehavior.setViewerProtocolPolicy(ViewerProtocolPolicy.AllowAll);
defaultCacheBehavior.setForwardedValues(forwardedValues);
defaultCacheBehavior.setTargetOriginId("");
defaultCacheBehavior.setTrustedSigners(trustedSigners);
// Distribution Config
distributionConfig.setOrigins(origins);
distributionConfig.setViewerCertificate(viewerCertificate);
distributionConfig.setCallerReference(callerReference);
distributionConfig.setDefaultCacheBehavior(defaultCacheBehavior);
distributionConfig.setEnabled(true);
distributionConfig.setComment("no comment");
distributionConfig.setDefaultRootObject("");
createDistributionRequest.setDistributionConfig(distributionConfig);
CreateDistributionResult createDistribution
= this.cloudFrontClient.createDistribution(createDistributionRequest);
return createDistribution.getLocation();
}
public Map<String, Integer> getAccountSummary(){
GetAccountSummaryResult accountSummary = getIdentityClient().getAccountSummary();
Map<String, Integer> summaryMap = accountSummary.getSummaryMap();
return summaryMap;
}
public AmazonElasticLoadBalancingClient getLoadBalanceClient() {
return loadBalanceClient;
}
public void setLoadBalanceClient(AmazonElasticLoadBalancingClient loadBalanceClient) {
this.loadBalanceClient = loadBalanceClient;
}
public AmazonIdentityManagementClient getIdentityClient() {
return identityClient;
}
public void setIdentityClient(AmazonIdentityManagementClient identityClient) {
this.identityClient = identityClient;
}
public AmazonCloudFrontClient getCloudFrontClient() {
return cloudFrontClient;
}
public void setCloudFrontClient(AmazonCloudFrontClient cloudFrontClient) {
this.cloudFrontClient = cloudFrontClient;
}
}
/**
* GRAVITY WORKFLOW AUTOMATION
* (C) Copyright 2015 Orcon Limited
* (C) Copyright 2015 Peter Harrison
*
* This file is part of Gravity Workflow Automation.
*
......@@ -35,19 +36,11 @@ import javax.jcr.Session;
import javax.jcr.query.QueryResult;
import nz.net.orcon.kanban.automation.CacheInvalidationInterface;
import nz.net.orcon.kanban.gviz.GVGraph;
import nz.net.orcon.kanban.gviz.GVNode;
import nz.net.orcon.kanban.gviz.GVShape;