Merge "Add period field to notification methods"

This commit is contained in:
Jenkins
2016-06-09 02:43:51 +00:00
committed by Gerrit Code Review
39 changed files with 831 additions and 200 deletions

1
.gitignore vendored
View File

@@ -32,3 +32,4 @@ log/
db/config.yml db/config.yml
virtenv/* virtenv/*
.vagrant .vagrant
AUTHORS

View File

@@ -29,6 +29,9 @@ metricsTopic: metrics
# Topic for publishing domain events to # Topic for publishing domain events to
eventsTopic: events eventsTopic: events
validNotificationPeriods:
- 60
kafka: kafka:
brokerUris: brokerUris:
- "127.0.0.1:9092" - "127.0.0.1:9092"

View File

@@ -1,5 +1,5 @@
# #
# (C) Copyright 2015 Hewlett Packard Enterprise Development Company LP # (C) Copyright 2015,2016 Hewlett Packard Enterprise Development Company LP
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@@ -21,6 +21,8 @@ kafka:
alarm_topic: "alarm-state-transitions" alarm_topic: "alarm-state-transitions"
notification_topic: "alarm-notifications" notification_topic: "alarm-notifications"
notification_retry_topic: "retry-notifications" notification_retry_topic: "retry-notifications"
periodic:
60: 60-seconds-notifications
max_offset_lag: 600 # In seconds, undefined for none max_offset_lag: 600 # In seconds, undefined for none
mysql: mysql:
@@ -67,6 +69,8 @@ zookeeper:
url: "127.0.0.1:2181" url: "127.0.0.1:2181"
notification_path: "/notification/alarms" notification_path: "/notification/alarms"
notification_retry_path: "/notification/retry" notification_retry_path: "/notification/retry"
periodic_path:
60: /notification/60_seconds
logging: # Used in logging.dictConfig logging: # Used in logging.dictConfig
version: 1 version: 1

View File

@@ -1,5 +1,5 @@
/* /*
* (C) Copyright 2015 Hewlett Packard Enterprise Development Company LP * (C) Copyright 2015,2016 Hewlett Packard Enterprise Development Company LP
* Copyright 2016 FUJITSU LIMITED * Copyright 2016 FUJITSU LIMITED
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@@ -142,6 +142,7 @@ CREATE TABLE `notification_method` (
`name` varchar(250) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `name` varchar(250) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`type` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL, `type` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
`address` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `address` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`period` int NOT NULL DEFAULT 0,
`created_at` datetime NOT NULL, `created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL, `updated_at` datetime NOT NULL,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),

View File

@@ -1,5 +1,5 @@
# #
# (C) Copyright 2015 Hewlett Packard Enterprise Development Company LP # (C) Copyright 2015,2016 Hewlett Packard Enterprise Development Company LP
# Copyright 2016 FUJITSU LIMITED # Copyright 2016 FUJITSU LIMITED
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
@@ -674,6 +674,7 @@ function install_schema {
/opt/kafka/bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 12 --topic alarm-notifications /opt/kafka/bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 12 --topic alarm-notifications
/opt/kafka/bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 12 --topic stream-notifications /opt/kafka/bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 12 --topic stream-notifications
/opt/kafka/bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 3 --topic retry-notifications /opt/kafka/bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 3 --topic retry-notifications
/opt/kafka/bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 3 --topic 60-seconds-notifications
} }

View File

@@ -1440,6 +1440,7 @@ None.
* name (string(250), required) - A descriptive name of the notification method. * name (string(250), required) - A descriptive name of the notification method.
* type (string(100), required) - The type of notification method (`EMAIL`, `WEBHOOK`, or `PAGERDUTY` ). * type (string(100), required) - The type of notification method (`EMAIL`, `WEBHOOK`, or `PAGERDUTY` ).
* address (string(100), required) - The email/url address to notify. * address (string(100), required) - The email/url address to notify.
* period (integer, optional) - The interval in seconds to periodically send the notification. Only can be set as a non zero value for WEBHOOK methods. Allowed periods for Webhooks by default are 0, 60. You can change allow periods for webhooks in the api config. The notification will continue to be sent at the defined interval until the alarm it is associated with changes state.
#### Request Examples #### Request Examples
``` ```
@@ -1469,6 +1470,7 @@ Returns a JSON notification method object with the following fields:
* name (string) - Name of notification method * name (string) - Name of notification method
* type (string) - Type of notification method * type (string) - Type of notification method
* address (string) - Address of notification method * address (string) - Address of notification method
* period (integer) - Period of notification method
#### Response Examples #### Response Examples
``` ```
@@ -1482,7 +1484,8 @@ Returns a JSON notification method object with the following fields:
], ],
"name":"Name of notification method", "name":"Name of notification method",
"type":"EMAIL", "type":"EMAIL",
"address":"john.doe@hp.com" "address":"john.doe@hp.com",
"period":0
} }
``` ```
___ ___
@@ -1530,6 +1533,7 @@ Returns a JSON object with a 'links' array of links and an 'elements' array of n
* name (string) - Name of notification method * name (string) - Name of notification method
* type (string) - Type of notification method * type (string) - Type of notification method
* address (string) - Address of notification method * address (string) - Address of notification method
* period (integer) - Period of notification method
#### Response Examples #### Response Examples
``` ```
@@ -1555,7 +1559,8 @@ Returns a JSON object with a 'links' array of links and an 'elements' array of n
], ],
"name": "Name of notification method", "name": "Name of notification method",
"type": "EMAIL", "type": "EMAIL",
"address": "john.doe@hp.com" "address": "john.doe@hp.com",
"period": 0
}, },
{ {
"id": "c60ec47e-5038-4bf1-9f95-4046c6e9a759", "id": "c60ec47e-5038-4bf1-9f95-4046c6e9a759",
@@ -1566,8 +1571,9 @@ Returns a JSON object with a 'links' array of links and an 'elements' array of n
} }
], ],
"name": "Name of notification method", "name": "Name of notification method",
"type": "EMAIL", "type": "WEBHOOK",
"address": "jane.doe@hp.com" "address": "http://localhost:3333",
"period": 1
} }
] ]
} }
@@ -1610,6 +1616,7 @@ Returns a JSON notification method object with the following fields:
* name (string) - Name of notification method * name (string) - Name of notification method
* type (string) - Type of notification method * type (string) - Type of notification method
* address (string) - Address of notification method * address (string) - Address of notification method
* period (integer) - Period of notification method
#### Response Examples #### Response Examples
``` ```
@@ -1623,7 +1630,8 @@ Returns a JSON notification method object with the following fields:
], ],
"name":"Name of notification method", "name":"Name of notification method",
"type":"EMAIL", "type":"EMAIL",
"address":"john.doe@hp.com" "address":"john.doe@hp.com",
"period": 0
} }
``` ```
___ ___
@@ -1648,6 +1656,7 @@ None.
* name (string(250), required) - A descriptive name of the notifcation method. * name (string(250), required) - A descriptive name of the notifcation method.
* type (string(100), required) - The type of notification method (`EMAIL`, `WEBHOOK`, or `PAGERDUTY` ). * type (string(100), required) - The type of notification method (`EMAIL`, `WEBHOOK`, or `PAGERDUTY` ).
* address (string(100), required) - The email/url address to notify. * address (string(100), required) - The email/url address to notify.
* period (integer, optional) - The interval in seconds to periodically send the notification. Only can be set as a non zero value for WEBHOOK methods. Allowed periods for Webhooks by default are 0, 60. You can change allow periods for webhooks in the api config. The notification will continue to be sent at the defined interval until the alarm it is associated with changes state.
#### Request Examples #### Request Examples
```` ````
@@ -1660,7 +1669,8 @@ Cache-Control: no-cache
{ {
"name":"New name of notification method", "name":"New name of notification method",
"type":"EMAIL", "type":"EMAIL",
"address":"jane.doe@hp.com" "address":"jane.doe@hp.com",
"period":0
} }
```` ````
@@ -1677,6 +1687,7 @@ Returns a JSON notification method object with the following fields:
* name (string) - Name of notification method * name (string) - Name of notification method
* type (string) - Type of notification method * type (string) - Type of notification method
* address (string) - Address of notification method * address (string) - Address of notification method
* period (integer) - Period of notification method
#### Response Examples #### Response Examples
```` ````
@@ -1690,7 +1701,8 @@ Returns a JSON notification method object with the following fields:
], ],
"name":"New name of notification method", "name":"New name of notification method",
"type":"EMAIL", "type":"EMAIL",
"address":"jane.doe@hp.com" "address":"jane.doe@hp.com",
"period":0
} }
```` ````
___ ___

View File

@@ -26,6 +26,8 @@ import io.dropwizard.db.DataSourceFactory;
import org.hibernate.validator.constraints.NotEmpty; import org.hibernate.validator.constraints.NotEmpty;
import java.util.List;
import javax.validation.Valid; import javax.validation.Valid;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
@@ -43,7 +45,8 @@ public class ApiConfig extends Configuration {
public int maxQueryLimit; public int maxQueryLimit;
@NotEmpty @NotEmpty
public String alarmStateTransitionsTopic = "alarm-state-transitions"; public String alarmStateTransitionsTopic = "alarm-state-transitions";
@NotEmpty
public List<Integer> validNotificationPeriods;
@Valid @Valid
@NotNull @NotNull
public DataSourceFactory mysql; public DataSourceFactory mysql;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014 Hewlett-Packard Development Company, L.P. * (C) Copyright 2014-2016 Hewlett Packard Enterprise Development Company LP
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at * in compliance with the License. You may obtain a copy of the License at
@@ -15,12 +15,12 @@ package monasca.api.app.command;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size; import javax.validation.constraints.Size;
import org.apache.commons.validator.routines.EmailValidator;
import org.apache.commons.validator.routines.UrlValidator;
import org.hibernate.validator.constraints.NotEmpty; import org.hibernate.validator.constraints.NotEmpty;
import java.util.List;
import monasca.api.app.validation.NotificationMethodValidation;
import monasca.api.domain.model.notificationmethod.NotificationMethodType; import monasca.api.domain.model.notificationmethod.NotificationMethodType;
import monasca.api.resource.exception.Exceptions;
public class CreateNotificationMethodCommand { public class CreateNotificationMethodCommand {
@NotEmpty @NotEmpty
@@ -31,13 +31,15 @@ public class CreateNotificationMethodCommand {
@NotEmpty @NotEmpty
@Size(min = 1, max = 512) @Size(min = 1, max = 512)
public String address; public String address;
public String period;
public CreateNotificationMethodCommand() {} public CreateNotificationMethodCommand() {this.period = "0";}
public CreateNotificationMethodCommand(String name, NotificationMethodType type, String address) { public CreateNotificationMethodCommand(String name, NotificationMethodType type, String address, String period) {
this.name = name; this.name = name;
this.type = type; this.type = type;
this.address = address; this.address = address;
this.period = period == null ? "0" : period;
} }
@Override @Override
@@ -59,26 +61,28 @@ public class CreateNotificationMethodCommand {
return false; return false;
} else if (!name.equals(other.name)) } else if (!name.equals(other.name))
return false; return false;
if (period == null) {
if (other.period != null)
return false;
} else if (!period.equals(other.period))
return false;
if (type != other.type) if (type != other.type)
return false; return false;
return true; return true;
} }
public void validate() { public void validate(List<Integer> validPeriods) {
switch (type) { NotificationMethodValidation.validate(type, address, period, validPeriods);
case EMAIL : { }
if (!EmailValidator.getInstance(true).isValid(address))
throw Exceptions.unprocessableEntity("Address %s is not of correct format", address); @Override
}; break; public int hashCode() {
case WEBHOOK : { final int prime = 31;
String[] schemes = {"http","https"}; int result = 1;
UrlValidator urlValidator = new UrlValidator(schemes, UrlValidator.ALLOW_LOCAL_URLS | UrlValidator.ALLOW_2_SLASHES); result = prime * result + ((name == null) ? 0 : name.hashCode());
if (!urlValidator.isValid(address)) result = prime * result + ((type == null) ? 0 : type.hashCode());
throw Exceptions.unprocessableEntity("Address %s is not of correct format", address); result = prime * result + ((address == null) ? 0 : address.hashCode());
}; break; result = prime * result + ((period == null) ? 0 : period.hashCode());
case PAGERDUTY : { return result;
// No known validation for PAGERDUTY type at this time
}; break;
}
} }
} }

View File

@@ -0,0 +1,89 @@
/*
* (C) Copyright 2016 Hewlett Packard Enterprise Development Company LP
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package monasca.api.app.command;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.NotEmpty;
import java.util.List;
import monasca.api.app.validation.NotificationMethodValidation;
import monasca.api.domain.model.notificationmethod.NotificationMethodType;
public class UpdateNotificationMethodCommand {
@NotEmpty
@Size(min = 1, max = 250)
public String name;
@NotNull
public NotificationMethodType type;
@NotEmpty
@Size(min = 1, max = 512)
public String address;
@NotNull
public String period;
public UpdateNotificationMethodCommand() {}
public UpdateNotificationMethodCommand(String name, NotificationMethodType type, String address, String period) {
this.name = name;
this.type = type;
this.address = address;
this.period = period;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
UpdateNotificationMethodCommand other = (UpdateNotificationMethodCommand) obj;
if (address == null) {
if (other.address != null)
return false;
} else if (!address.equals(other.address))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (period == null) {
if (other.period != null)
return false;
} else if (!period.equals(other.period))
return false;
if (type != other.type)
return false;
return true;
}
public void validate(List<Integer> validPeriods) {
NotificationMethodValidation.validate(type, address, period, validPeriods);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((type == null) ? 0 : type.hashCode());
result = prime * result + ((address == null) ? 0 : address.hashCode());
result = prime * result + ((period == null) ? 0 : period.hashCode());
return result;
}
}

View File

@@ -0,0 +1,51 @@
/*
* (C) Copyright 2016 Hewlett Packard Enterprise Development Company LP
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package monasca.api.app.validation;
import monasca.api.domain.model.notificationmethod.NotificationMethodType;
import monasca.api.resource.exception.Exceptions;
import org.apache.commons.validator.routines.EmailValidator;
import org.apache.commons.validator.routines.UrlValidator;
import java.util.List;
public class NotificationMethodValidation {
public static void validate(NotificationMethodType type, String address, String period,
List<Integer> validPeriods) {
int convertedPeriod = Validation.parseAndValidateNumber(period, "period");
switch (type) {
case EMAIL : {
if (!EmailValidator.getInstance(true).isValid(address))
throw Exceptions.unprocessableEntity("Address %s is not of correct format", address);
if (convertedPeriod != 0)
throw Exceptions.unprocessableEntity("Period can not be non zero for Email");
} break;
case WEBHOOK : {
String[] schemes = {"http","https"};
UrlValidator urlValidator = new UrlValidator(schemes, UrlValidator.ALLOW_LOCAL_URLS | UrlValidator.ALLOW_2_SLASHES);
if (!urlValidator.isValid(address))
throw Exceptions.unprocessableEntity("Address %s is not of correct format", address);
} break;
case PAGERDUTY : {
if (convertedPeriod != 0)
throw Exceptions.unprocessableEntity("Period can not be non zero for Pagerduty");
} break;
}
if (convertedPeriod != 0 && !validPeriods.contains(convertedPeriod)){
throw Exceptions.unprocessableEntity("%d is not a valid period", convertedPeriod);
}
}
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014 Hewlett-Packard Development Company, L.P. * (C) Copyright 2014-2016 Hewlett Packard Enterprise Development Company LP
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at * in compliance with the License. You may obtain a copy of the License at
@@ -24,14 +24,16 @@ public class NotificationMethod extends AbstractEntity implements Linked {
private String name; private String name;
private NotificationMethodType type; private NotificationMethodType type;
private String address; private String address;
private int period;
public NotificationMethod() {} public NotificationMethod() {}
public NotificationMethod(String id, String name, NotificationMethodType type, String address) { public NotificationMethod(String id, String name, NotificationMethodType type, String address, int period) {
this.id = id; this.id = id;
this.name = name; this.name = name;
this.type = type; this.type = type;
this.address = address; this.address = address;
this.period = period;
} }
@Override @Override
@@ -53,6 +55,8 @@ public class NotificationMethod extends AbstractEntity implements Linked {
return false; return false;
} else if (!name.equals(other.name)) } else if (!name.equals(other.name))
return false; return false;
if (period != other.period)
return false;
if (type != other.type) if (type != other.type)
return false; return false;
return true; return true;
@@ -78,6 +82,10 @@ public class NotificationMethod extends AbstractEntity implements Linked {
return type; return type;
} }
public int getPeriod() {
return period;
}
@Override @Override
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
@@ -85,6 +93,7 @@ public class NotificationMethod extends AbstractEntity implements Linked {
result = prime * result + ((address == null) ? 0 : address.hashCode()); result = prime * result + ((address == null) ? 0 : address.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((type == null) ? 0 : type.hashCode()); result = prime * result + ((type == null) ? 0 : type.hashCode());
result = prime * result + period;
return result; return result;
} }
@@ -107,4 +116,8 @@ public class NotificationMethod extends AbstractEntity implements Linked {
public void setType(NotificationMethodType type) { public void setType(NotificationMethodType type) {
this.type = type; this.type = type;
} }
public void setPeriod(int period) {
this.period = period;
}
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014 Hewlett-Packard Development Company, L.P. * (C) Copyright 2014-2016 Hewlett Packard Enterprise Development Company LP
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at * in compliance with the License. You may obtain a copy of the License at
@@ -22,7 +22,7 @@ import monasca.api.domain.exception.EntityNotFoundException;
*/ */
public interface NotificationMethodRepo { public interface NotificationMethodRepo {
NotificationMethod create(String tenantId, String name, NotificationMethodType type, NotificationMethod create(String tenantId, String name, NotificationMethodType type,
String address); String address, int period);
/** /**
* @throws EntityNotFoundException if a notification method cannot be found for the * @throws EntityNotFoundException if a notification method cannot be found for the
@@ -44,7 +44,7 @@ public interface NotificationMethodRepo {
* {@code notificationMethodId} * {@code notificationMethodId}
*/ */
NotificationMethod update(String tenantId, String notificationMethodId, String name, NotificationMethod update(String tenantId, String notificationMethodId, String name,
NotificationMethodType type, String address); NotificationMethodType type, String address, int period);
List<NotificationMethod> find(String tenantId, List<String> sortBy, String offset, int limit); List<NotificationMethod> find(String tenantId, List<String> sortBy, String offset, int limit);
} }

View File

@@ -1,5 +1,6 @@
/* /*
* Copyright 2015 FUJITSU LIMITED * Copyright 2015 FUJITSU LIMITED
* (C) Copyright 2016 Hewlett Packard Enterprise Development Company LP
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at * in compliance with the License. You may obtain a copy of the License at
@@ -53,7 +54,7 @@ public class NotificationMethodSqlRepoImpl
@Override @Override
public NotificationMethod create(String tenantId, String name, NotificationMethodType type, public NotificationMethod create(String tenantId, String name, NotificationMethodType type,
String address) { String address, int period) {
Transaction tx = null; Transaction tx = null;
Session session = null; Session session = null;
try { try {
@@ -73,6 +74,7 @@ public class NotificationMethodSqlRepoImpl
name, name,
AlarmNotificationMethodType.valueOf(type.name()), AlarmNotificationMethodType.valueOf(type.name()),
address, address,
period,
now, now,
now now
); );
@@ -158,7 +160,7 @@ public class NotificationMethodSqlRepoImpl
@Override @Override
public NotificationMethod update(String tenantId, String notificationMethodId, String name, public NotificationMethod update(String tenantId, String notificationMethodId, String name,
NotificationMethodType type, String address) { NotificationMethodType type, String address, int period) {
Session session = null; Session session = null;
Transaction tx = null; Transaction tx = null;
try { try {
@@ -180,6 +182,7 @@ public class NotificationMethodSqlRepoImpl
db.setName(name); db.setName(name);
db.setType(AlarmNotificationMethodType.valueOf(type.name())); db.setType(AlarmNotificationMethodType.valueOf(type.name()));
db.setAddress(address); db.setAddress(address);
db.setPeriod(period);
db.setUpdatedAt(this.getUTCNow()); db.setUpdatedAt(this.getUTCNow());
session.save(db); session.save(db);
@@ -270,7 +273,8 @@ public class NotificationMethodSqlRepoImpl
db.getId(), db.getId(),
db.getName(), db.getName(),
NotificationMethodType.valueOf(db.getType().name()), NotificationMethodType.valueOf(db.getType().name()),
db.getAddress() db.getAddress(),
db.getPeriod()
); );
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014 Hewlett-Packard Development Company, L.P. * (C) Copyright 2014-2016 Hewlett Packard Enterprise Development Company LP
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at * in compliance with the License. You may obtain a copy of the License at
@@ -54,7 +54,7 @@ public class NotificationMethodMySqlRepoImpl implements NotificationMethodRepo {
@Override @Override
public NotificationMethod create(String tenantId, String name, public NotificationMethod create(String tenantId, String name,
NotificationMethodType type, String address) { NotificationMethodType type, String address, int period) {
try (Handle h = db.open()) { try (Handle h = db.open()) {
h.begin(); h.begin();
if (getNotificationIdForTenantIdAndName(h,tenantId, name) != null) if (getNotificationIdForTenantIdAndName(h,tenantId, name) != null)
@@ -63,11 +63,11 @@ public class NotificationMethodMySqlRepoImpl implements NotificationMethodRepo {
String id = UUID.randomUUID().toString(); String id = UUID.randomUUID().toString();
h.insert( h.insert(
"insert into notification_method (id, tenant_id, name, type, address, created_at, updated_at) values (?, ?, ?, ?, ?, NOW(), NOW())", "insert into notification_method (id, tenant_id, name, type, address, period, created_at, updated_at) values (?, ?, ?, ?, ?, ?, NOW(), NOW())",
id, tenantId, name, type.toString(), address); id, tenantId, name, type.toString(), address, period);
LOG.debug("Creating notification method {} for {}", name, tenantId); LOG.debug("Creating notification method {} for {}", name, tenantId);
h.commit(); h.commit();
return new NotificationMethod(id, name, type, address); return new NotificationMethod(id, name, type, address, period);
} }
} }
@@ -112,7 +112,7 @@ public class NotificationMethodMySqlRepoImpl implements NotificationMethodRepo {
try (Handle h = db.open()) { try (Handle h = db.open()) {
String rawQuery = String rawQuery =
" SELECT nm.id, nm.tenant_id, nm.name, nm.type, nm.address, nm.created_at, nm.updated_at " " SELECT nm.id, nm.tenant_id, nm.name, nm.type, nm.address, nm.period, nm.created_at, nm.updated_at "
+ "FROM notification_method as nm " + "FROM notification_method as nm "
+ "WHERE tenant_id = :tenantId %1$s %2$s %3$s"; + "WHERE tenant_id = :tenantId %1$s %2$s %3$s";
@@ -174,7 +174,7 @@ public class NotificationMethodMySqlRepoImpl implements NotificationMethodRepo {
@Override @Override
public NotificationMethod update(String tenantId, String notificationMethodId, String name, public NotificationMethod update(String tenantId, String notificationMethodId, String name,
NotificationMethodType type, String address) { NotificationMethodType type, String address, int period) {
try (Handle h = db.open()) { try (Handle h = db.open()) {
h.begin(); h.begin();
String notificationID = getNotificationIdForTenantIdAndName(h,tenantId, name); String notificationID = getNotificationIdForTenantIdAndName(h,tenantId, name);
@@ -185,13 +185,13 @@ public class NotificationMethodMySqlRepoImpl implements NotificationMethodRepo {
if (h if (h
.update( .update(
"update notification_method set name = ?, type = ?, address = ?, updated_at = NOW() " "update notification_method set name = ?, type = ?, address = ?, period = ?, updated_at = NOW() "
+ "where tenant_id = ? and id = ?", + "where tenant_id = ? and id = ?",
name, type.name(), address, tenantId, notificationMethodId) == 0) name, type.name(), address, period, tenantId, notificationMethodId) == 0)
throw new EntityNotFoundException("No notification method exists for %s", throw new EntityNotFoundException("No notification method exists for %s",
notificationMethodId); notificationMethodId);
h.commit(); h.commit();
return new NotificationMethod(notificationMethodId, name, type, address); return new NotificationMethod(notificationMethodId, name, type, address, period);
} }
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014 Hewlett-Packard Development Company, L.P. * (C) Copyright 2014-2016 Hewlett Packard Enterprise Development Company LP
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at * in compliance with the License. You may obtain a copy of the License at
@@ -37,7 +37,9 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo; import javax.ws.rs.core.UriInfo;
import monasca.api.ApiConfig;
import monasca.api.app.command.CreateNotificationMethodCommand; import monasca.api.app.command.CreateNotificationMethodCommand;
import monasca.api.app.command.UpdateNotificationMethodCommand;
import monasca.api.app.validation.Validation; import monasca.api.app.validation.Validation;
import monasca.api.domain.model.notificationmethod.NotificationMethod; import monasca.api.domain.model.notificationmethod.NotificationMethod;
import monasca.api.domain.model.notificationmethod.NotificationMethodRepo; import monasca.api.domain.model.notificationmethod.NotificationMethodRepo;
@@ -53,11 +55,16 @@ public class NotificationMethodResource {
private final static List<String> ALLOWED_SORT_BY = Arrays.asList("id", "name", "type", private final static List<String> ALLOWED_SORT_BY = Arrays.asList("id", "name", "type",
"address", "updated_at", "address", "updated_at",
"created_at"); "created_at");
private final List<Integer> validPeriods;
@Inject @Inject
public NotificationMethodResource(NotificationMethodRepo repo, PersistUtils persistUtils) { public NotificationMethodResource(ApiConfig config, NotificationMethodRepo repo,
PersistUtils persistUtils) {
this.repo = repo; this.repo = repo;
this.persistUtils = persistUtils; this.persistUtils = persistUtils;
this.validPeriods = config.validNotificationPeriods == null ? Arrays.asList(0, 60):
config.validNotificationPeriods;
} }
@POST @POST
@@ -66,10 +73,12 @@ public class NotificationMethodResource {
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public Response create(@Context UriInfo uriInfo, @HeaderParam("X-Tenant-Id") String tenantId, public Response create(@Context UriInfo uriInfo, @HeaderParam("X-Tenant-Id") String tenantId,
@Valid CreateNotificationMethodCommand command) { @Valid CreateNotificationMethodCommand command) {
command.validate(); command.validate(this.validPeriods);
int period = Validation.parseAndValidateNumber(command.period, "period");
NotificationMethod notificationMethod = NotificationMethod notificationMethod =
Links.hydrate(repo.create(tenantId, command.name, command.type, command.address), uriInfo, Links.hydrate(repo.create(tenantId, command.name, command.type,
command.address, period), uriInfo,
false); false);
return Response.created(URI.create(notificationMethod.getId())).entity(notificationMethod) return Response.created(URI.create(notificationMethod.getId())).entity(notificationMethod)
.build(); .build();
@@ -112,11 +121,13 @@ public class NotificationMethodResource {
public NotificationMethod update(@Context UriInfo uriInfo, public NotificationMethod update(@Context UriInfo uriInfo,
@HeaderParam("X-Tenant-Id") String tenantId, @HeaderParam("X-Tenant-Id") String tenantId,
@PathParam("notification_method_id") String notificationMethodId, @PathParam("notification_method_id") String notificationMethodId,
@Valid CreateNotificationMethodCommand command) { @Valid UpdateNotificationMethodCommand command) {
command.validate(); command.validate(this.validPeriods);
int period = Validation.parseAndValidateNumber(command.period, "period");
return Links.hydrate( return Links.hydrate(
repo.update(tenantId, notificationMethodId, command.name, command.type, command.address), repo.update(tenantId, notificationMethodId, command.name, command.type,
command.address, period),
uriInfo, true); uriInfo, true);
} }

View File

@@ -14,6 +14,10 @@ eventsTopic: events
# If not set or set to any value less than or equal to 0, then defaults to 10,000. # If not set or set to any value less than or equal to 0, then defaults to 10,000.
maxQueryLimit: 10000 maxQueryLimit: 10000
# Valid periods for notification
validNotificationPeriods:
- 60
kafka: kafka:
brokerUris: brokerUris:
- 192.168.10.6:9092 - 192.168.10.6:9092

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014 Hewlett-Packard Development Company, L.P. * (C) Copyright 2014-2016 Hewlett Packard Enterprise Development Company LP
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at * in compliance with the License. You may obtain a copy of the License at
@@ -17,6 +17,8 @@ package monasca.api.app.command;
import static monasca.common.dropwizard.JsonHelpers.jsonFixture; import static monasca.common.dropwizard.JsonHelpers.jsonFixture;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import java.util.Arrays;
import java.util.List;
import java.util.Set; import java.util.Set;
import javax.validation.ConstraintViolation; import javax.validation.ConstraintViolation;
@@ -39,6 +41,7 @@ import monasca.api.domain.model.notificationmethod.NotificationMethodType;
public class CreateNotificationMethodTest extends AbstractModelTest { public class CreateNotificationMethodTest extends AbstractModelTest {
private static Validator validator; private static Validator validator;
private List<Integer> validPeriods = Arrays.asList(0, 60);
@BeforeClass @BeforeClass
public static void setUp() { public static void setUp() {
@@ -48,7 +51,7 @@ public class CreateNotificationMethodTest extends AbstractModelTest {
public void shouldDeserializeFromJson() throws Exception { public void shouldDeserializeFromJson() throws Exception {
CreateNotificationMethodCommand newNotificationMethod = CreateNotificationMethodCommand newNotificationMethod =
new CreateNotificationMethodCommand("MyEmail", NotificationMethodType.EMAIL, "a@b"); new CreateNotificationMethodCommand("MyEmail", NotificationMethodType.EMAIL, "a@b", "0");
String json = jsonFixture("fixtures/newNotificationMethod.json"); String json = jsonFixture("fixtures/newNotificationMethod.json");
CreateNotificationMethodCommand other = fromJson(json, CreateNotificationMethodCommand.class); CreateNotificationMethodCommand other = fromJson(json, CreateNotificationMethodCommand.class);
@@ -57,17 +60,26 @@ public class CreateNotificationMethodTest extends AbstractModelTest {
public void shouldDeserializeFromJsonLowerCaseEnum() throws Exception { public void shouldDeserializeFromJsonLowerCaseEnum() throws Exception {
CreateNotificationMethodCommand newNotificationMethod = CreateNotificationMethodCommand newNotificationMethod =
new CreateNotificationMethodCommand("MyEmail", NotificationMethodType.EMAIL, "a@b"); new CreateNotificationMethodCommand("MyEmail", NotificationMethodType.EMAIL, "a@b", "0");
String json = jsonFixture("fixtures/newNotificationMethodWithLowercaseEnum.json"); String json = jsonFixture("fixtures/newNotificationMethodWithLowercaseEnum.json");
CreateNotificationMethodCommand other = fromJson(json, CreateNotificationMethodCommand.class); CreateNotificationMethodCommand other = fromJson(json, CreateNotificationMethodCommand.class);
assertEquals(other, newNotificationMethod); assertEquals(other, newNotificationMethod);
} }
public void shouldDeserializeFromJsonDefinedPeriod() throws Exception {
CreateNotificationMethodCommand newNotificationMethod =
new CreateNotificationMethodCommand("MyWebhook", NotificationMethodType.WEBHOOK, "http://somedomain.com", "60");
String json = jsonFixture("fixtures/newNotificationMethodWithPeriod.json");
CreateNotificationMethodCommand other = fromJson(json, CreateNotificationMethodCommand.class);
assertEquals(other, newNotificationMethod);
}
@Test(expectedExceptions = JsonMappingException.class) @Test(expectedExceptions = JsonMappingException.class)
public void shouldDeserializeFromJsonEnumError() throws Exception { public void shouldDeserializeFromJsonEnumError() throws Exception {
CreateNotificationMethodCommand newNotificationMethod = CreateNotificationMethodCommand newNotificationMethod =
new CreateNotificationMethodCommand("MyEmail", NotificationMethodType.EMAIL, "a@b"); new CreateNotificationMethodCommand("MyEmail", NotificationMethodType.EMAIL, "a@b", "0");
String json = jsonFixture("fixtures/newNotificationMethodWithInvalidEnum.json"); String json = jsonFixture("fixtures/newNotificationMethodWithInvalidEnum.json");
CreateNotificationMethodCommand other = fromJson(json, CreateNotificationMethodCommand.class); CreateNotificationMethodCommand other = fromJson(json, CreateNotificationMethodCommand.class);
@@ -76,36 +88,54 @@ public class CreateNotificationMethodTest extends AbstractModelTest {
public void testValidationForEmail() { public void testValidationForEmail() {
CreateNotificationMethodCommand newNotificationMethod = CreateNotificationMethodCommand newNotificationMethod =
new CreateNotificationMethodCommand("MyEmail", NotificationMethodType.EMAIL, "name@domain.com"); new CreateNotificationMethodCommand("MyEmail", NotificationMethodType.EMAIL, "name@domain.com", "0");
newNotificationMethod.validate(); newNotificationMethod.validate(validPeriods);
} }
@Test(expectedExceptions = WebApplicationException.class) @Test(expectedExceptions = WebApplicationException.class)
public void testValidationExceptionForEmail() throws Exception { public void testValidationExceptionForEmail() throws Exception {
CreateNotificationMethodCommand newNotificationMethod = CreateNotificationMethodCommand newNotificationMethod =
new CreateNotificationMethodCommand("MyEmail", NotificationMethodType.EMAIL, "name@domain."); new CreateNotificationMethodCommand("MyEmail", NotificationMethodType.EMAIL, "name@domain.", "0");
newNotificationMethod.validate(validPeriods);
}
newNotificationMethod.validate(); @Test(expectedExceptions = WebApplicationException.class)
public void testValidationExceptionForNonZeroPeriodForEmail() {
CreateNotificationMethodCommand newNotificationMethod =
new CreateNotificationMethodCommand("MyEmail", NotificationMethodType.EMAIL, "name@domain.", "60");
newNotificationMethod.validate(validPeriods);
} }
public void testValidationForWebhook() { public void testValidationForWebhook() {
CreateNotificationMethodCommand newNotificationMethod = CreateNotificationMethodCommand newNotificationMethod =
new CreateNotificationMethodCommand("MyWebhook", NotificationMethodType.WEBHOOK, "http://somedomain.com"); new CreateNotificationMethodCommand("MyWebhook", NotificationMethodType.WEBHOOK, "http://somedomain.com", "0");
newNotificationMethod.validate(); newNotificationMethod.validate(validPeriods);
}
public void testValidationNonZeroPeriodForWebhook() {
CreateNotificationMethodCommand newNotificationMethod =
new CreateNotificationMethodCommand("MyWebhook", NotificationMethodType.WEBHOOK, "http://somedomain.com", "60");
newNotificationMethod.validate(validPeriods);
} }
@Test(expectedExceptions = WebApplicationException.class) @Test(expectedExceptions = WebApplicationException.class)
public void testValidationExceptionForWebhook() throws Exception { public void testValidationExceptionForWebhook() throws Exception {
CreateNotificationMethodCommand newNotificationMethod = CreateNotificationMethodCommand newNotificationMethod =
new CreateNotificationMethodCommand("MyWebhook", NotificationMethodType.WEBHOOK, "ftp://localhost"); new CreateNotificationMethodCommand("MyWebhook", NotificationMethodType.WEBHOOK, "ftp://localhost", "0");
newNotificationMethod.validate(validPeriods);
newNotificationMethod.validate();
} }
public void testValidationForPagerduty() { public void testValidationForPagerduty() {
CreateNotificationMethodCommand newNotificationMethod = CreateNotificationMethodCommand newNotificationMethod =
new CreateNotificationMethodCommand("MyPagerduty", NotificationMethodType.PAGERDUTY, "nzH2LVRdMzun11HNC2oD"); new CreateNotificationMethodCommand("MyPagerduty", NotificationMethodType.PAGERDUTY, "nzH2LVRdMzun11HNC2oD", "0");
newNotificationMethod.validate(); newNotificationMethod.validate(validPeriods);
}
@Test(expectedExceptions = WebApplicationException.class)
public void testValidationExceptionForNonZeroPeriodForPagerDuty() {
CreateNotificationMethodCommand newNotificationMethod =
new CreateNotificationMethodCommand("MyPagerduty", NotificationMethodType.PAGERDUTY, "nzH2LVRdMzun11HNC2oD", "60");
newNotificationMethod.validate(validPeriods);
} }
public void testValidationForMaxNameAddress() { public void testValidationForMaxNameAddress() {
@@ -114,7 +144,7 @@ public class CreateNotificationMethodTest extends AbstractModelTest {
String address = "http://" + StringUtils.repeat("A", 502) + ".io"; String address = "http://" + StringUtils.repeat("A", 502) + ".io";
assertEquals(address.length(), 512); assertEquals(address.length(), 512);
CreateNotificationMethodCommand newNotificationMethod = CreateNotificationMethodCommand newNotificationMethod =
new CreateNotificationMethodCommand(name, NotificationMethodType.WEBHOOK, address); new CreateNotificationMethodCommand(name, NotificationMethodType.WEBHOOK, address, "0");
Set<ConstraintViolation<CreateNotificationMethodCommand>> constraintViolations = Set<ConstraintViolation<CreateNotificationMethodCommand>> constraintViolations =
validator.validate(newNotificationMethod); validator.validate(newNotificationMethod);
@@ -125,7 +155,7 @@ public class CreateNotificationMethodTest extends AbstractModelTest {
String name = StringUtils.repeat("A", 251); String name = StringUtils.repeat("A", 251);
assertEquals(name.length(), 251); assertEquals(name.length(), 251);
CreateNotificationMethodCommand newNotificationMethod = CreateNotificationMethodCommand newNotificationMethod =
new CreateNotificationMethodCommand(name, NotificationMethodType.WEBHOOK, "http://somedomain.com"); new CreateNotificationMethodCommand(name, NotificationMethodType.WEBHOOK, "http://somedomain.com", "0");
Set<ConstraintViolation<CreateNotificationMethodCommand>> constraintViolations = Set<ConstraintViolation<CreateNotificationMethodCommand>> constraintViolations =
validator.validate(newNotificationMethod); validator.validate(newNotificationMethod);
@@ -138,7 +168,7 @@ public class CreateNotificationMethodTest extends AbstractModelTest {
String address = "http://" + StringUtils.repeat("A", 503) + ".io"; String address = "http://" + StringUtils.repeat("A", 503) + ".io";
assertEquals(address.length(), 513); assertEquals(address.length(), 513);
CreateNotificationMethodCommand newNotificationMethod = CreateNotificationMethodCommand newNotificationMethod =
new CreateNotificationMethodCommand("MyWebhook", NotificationMethodType.WEBHOOK, address); new CreateNotificationMethodCommand("MyWebhook", NotificationMethodType.WEBHOOK, address, "0");
Set<ConstraintViolation<CreateNotificationMethodCommand>> constraintViolations = Set<ConstraintViolation<CreateNotificationMethodCommand>> constraintViolations =
validator.validate(newNotificationMethod); validator.validate(newNotificationMethod);
@@ -146,4 +176,18 @@ public class CreateNotificationMethodTest extends AbstractModelTest {
assertEquals(constraintViolations.iterator().next().getMessage(), assertEquals(constraintViolations.iterator().next().getMessage(),
"size must be between 1 and 512"); "size must be between 1 and 512");
} }
@Test(expectedExceptions = WebApplicationException.class)
public void testValidationExceptionForNonIntPeriod() {
CreateNotificationMethodCommand newNotificationMethod =
new CreateNotificationMethodCommand("MyEmail", NotificationMethodType.EMAIL, "name@domain.com", "interval");
newNotificationMethod.validate(validPeriods);
}
@Test(expectedExceptions = WebApplicationException.class)
public void testValidationExceptionForInvalidPeriod() {
CreateNotificationMethodCommand newNotificationMethod =
new CreateNotificationMethodCommand("MyWebhook", NotificationMethodType.WEBHOOK, "http://somedomain.com", "10");
newNotificationMethod.validate(validPeriods);
}
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014 Hewlett-Packard Development Company, L.P. * (C) Copyright 2014-2016 Hewlett Packard Enterprise Development Company LP
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at * in compliance with the License. You may obtain a copy of the License at
@@ -31,7 +31,7 @@ public class NotificationMethodTest extends AbstractModelTest {
public NotificationMethodTest() { public NotificationMethodTest() {
notificationMethod = notificationMethod =
new NotificationMethod("123", "MyEmail", NotificationMethodType.EMAIL, "a@b"); new NotificationMethod("123", "MyEmail", NotificationMethodType.EMAIL, "a@b", 0);
notificationMethod.setLinks(Arrays.asList(new Link("self", notificationMethod.setLinks(Arrays.asList(new Link("self",
"https://cloudsvc.example.com/v1.0"))); "https://cloudsvc.example.com/v1.0")));
} }

View File

@@ -1,5 +1,6 @@
/* /*
* Copyright 2015 FUJITSU LIMITED * Copyright 2015 FUJITSU LIMITED
* (C) Copyright 2016 Hewlett Packard Enterprise Development Company LP
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at * in compliance with the License. You may obtain a copy of the License at
@@ -72,9 +73,9 @@ public class NotificationMethodSqlRepositoryImplTest {
session.beginTransaction(); session.beginTransaction();
NotificationMethodDb notificationMethodDb1 = NotificationMethodDb notificationMethodDb1 =
new NotificationMethodDb("123", "444", "MyEmail", AlarmNotificationMethodType.EMAIL, "a@b", new DateTime(), new DateTime()); new NotificationMethodDb("123", "444", "MyEmail", AlarmNotificationMethodType.EMAIL, "a@b", 0, new DateTime(), new DateTime());
NotificationMethodDb notificationMethodDb2 = NotificationMethodDb notificationMethodDb2 =
new NotificationMethodDb("124", "444", "OtherEmail", AlarmNotificationMethodType.EMAIL, "a@b", new DateTime(), new DateTime()); new NotificationMethodDb("124", "444", "OtherEmail", AlarmNotificationMethodType.EMAIL, "a@b", 0, new DateTime(), new DateTime());
session.save(notificationMethodDb1); session.save(notificationMethodDb1);
session.save(notificationMethodDb2); session.save(notificationMethodDb2);
@@ -90,7 +91,7 @@ public class NotificationMethodSqlRepositoryImplTest {
@Test(groups = "orm") @Test(groups = "orm")
public void shouldCreate() { public void shouldCreate() {
NotificationMethod nmA = repo.create("555", "MyEmail", NotificationMethodType.EMAIL, "a@b"); NotificationMethod nmA = repo.create("555", "MyEmail", NotificationMethodType.EMAIL, "a@b", 0);
NotificationMethod nmB = repo.findById("555", nmA.getId()); NotificationMethod nmB = repo.findById("555", nmA.getId());
assertEquals(nmA, nmB); assertEquals(nmA, nmB);
@@ -107,25 +108,25 @@ public class NotificationMethodSqlRepositoryImplTest {
public void shouldFind() { public void shouldFind() {
List<NotificationMethod> nms1 = repo.find("444", null, null, 1); List<NotificationMethod> nms1 = repo.find("444", null, null, 1);
assertEquals(nms1, Arrays.asList(new NotificationMethod("123", "MyEmail", NotificationMethodType.EMAIL, "a@b"), new NotificationMethod("124", assertEquals(nms1, Arrays.asList(new NotificationMethod("123", "MyEmail", NotificationMethodType.EMAIL, "a@b", 0), new NotificationMethod("124",
"OtherEmail", NotificationMethodType.EMAIL, "a@b"))); "OtherEmail", NotificationMethodType.EMAIL, "a@b", 0)));
List<NotificationMethod> nms2 = repo.find("444", null, "123", 1); List<NotificationMethod> nms2 = repo.find("444", null, "123", 1);
assertEquals(nms2, Collections.singletonList(new NotificationMethod("124", "OtherEmail", NotificationMethodType.EMAIL, "a@b"))); assertEquals(nms2, Collections.singletonList(new NotificationMethod("124", "OtherEmail", NotificationMethodType.EMAIL, "a@b", 0)));
} }
@Test(groups = "orm") @Test(groups = "orm")
public void shouldUpdate() { public void shouldUpdate() {
repo.update("444", "123", "Foo", NotificationMethodType.EMAIL, "abc"); repo.update("444", "123", "Foo", NotificationMethodType.EMAIL, "abc", 0);
NotificationMethod nm = repo.findById("444", "123"); NotificationMethod nm = repo.findById("444", "123");
assertEquals(nm, new NotificationMethod("123", "Foo", NotificationMethodType.EMAIL, "abc")); assertEquals(nm, new NotificationMethod("123", "Foo", NotificationMethodType.EMAIL, "abc", 0));
} }
@Test(groups = "orm") @Test(groups = "orm")
public void shouldUpdateReturnValue() { public void shouldUpdateReturnValue() {
NotificationMethod nm = repo.update("444", "123", "Foo", NotificationMethodType.EMAIL, "abc"); NotificationMethod nm = repo.update("444", "123", "Foo", NotificationMethodType.EMAIL, "abc", 0);
NotificationMethod foundNotificationMethod = repo.findById("444", "123"); NotificationMethod foundNotificationMethod = repo.findById("444", "123");
assertEquals(nm, foundNotificationMethod); assertEquals(nm, foundNotificationMethod);
@@ -144,16 +145,16 @@ public class NotificationMethodSqlRepositoryImplTest {
@Test(groups = "orm") @Test(groups = "orm")
public void shouldUpdateDuplicateWithSameValues() { public void shouldUpdateDuplicateWithSameValues() {
repo.update("444", "123", "Foo", NotificationMethodType.EMAIL, "abc"); repo.update("444", "123", "Foo", NotificationMethodType.EMAIL, "abc", 0);
NotificationMethod nm = repo.findById("444", "123"); NotificationMethod nm = repo.findById("444", "123");
assertEquals(nm, new NotificationMethod("123", "Foo", NotificationMethodType.EMAIL, "abc")); assertEquals(nm, new NotificationMethod("123", "Foo", NotificationMethodType.EMAIL, "abc", 0));
} }
@Test(groups = "orm", expectedExceptions = EntityExistsException.class) @Test(groups = "orm", expectedExceptions = EntityExistsException.class)
public void shouldNotUpdateDuplicateWithSameName() { public void shouldNotUpdateDuplicateWithSameName() {
repo.update("444", "124", "MyEmail", NotificationMethodType.EMAIL, "abc"); repo.update("444", "124", "MyEmail", NotificationMethodType.EMAIL, "abc", 0);
} }
@Test(groups = "orm", expectedExceptions = WebApplicationException.class) @Test(groups = "orm", expectedExceptions = WebApplicationException.class)

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014 Hewlett-Packard Development Company, L.P. * (C) Copyright 2014-2016 Hewlett Packard Enterprise Development Company LP
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at * in compliance with the License. You may obtain a copy of the License at
@@ -67,8 +67,15 @@ public class NotificationMethodMySqlRepositoryImplTest {
.execute("insert into notification_method (id, tenant_id, name, type, address, created_at, updated_at) values ('124', '444', 'OtherEmail', 'EMAIL', 'a@b', NOW(), NOW())"); .execute("insert into notification_method (id, tenant_id, name, type, address, created_at, updated_at) values ('124', '444', 'OtherEmail', 'EMAIL', 'a@b', NOW(), NOW())");
} }
public void shouldCreate() { public void shouldCreateEmail() {
NotificationMethod nmA = repo.create("555", "MyEmail", NotificationMethodType.EMAIL, "a@b"); NotificationMethod nmA = repo.create("555", "MyEmail", NotificationMethodType.EMAIL, "a@b", 0);
NotificationMethod nmB = repo.findById("555", nmA.getId());
assertEquals(nmA, nmB);
}
public void shouldCreateWebhookNonZeroPeriod() {
NotificationMethod nmA = repo.create("555", "MyWebhook", NotificationMethodType.WEBHOOK, "http://localhost:33", 60);
NotificationMethod nmB = repo.findById("555", nmA.getId()); NotificationMethod nmB = repo.findById("555", nmA.getId());
assertEquals(nmA, nmB); assertEquals(nmA, nmB);
@@ -92,15 +99,23 @@ public class NotificationMethodMySqlRepositoryImplTest {
List<NotificationMethod> nms = repo.find("444", null, null, 1); List<NotificationMethod> nms = repo.find("444", null, null, 1);
assertEquals(nms, Arrays.asList(new NotificationMethod("123", "MyEmail", assertEquals(nms, Arrays.asList(new NotificationMethod("123", "MyEmail",
NotificationMethodType.EMAIL, "a@b"),new NotificationMethod("124", "OtherEmail", NotificationMethodType.EMAIL, "a@b", 0),new NotificationMethod("124", "OtherEmail",
NotificationMethodType.EMAIL, "a@b"))); NotificationMethodType.EMAIL, "a@b", 0)));
} }
public void shouldUpdate() { public void shouldUpdate() {
repo.update("444", "123", "Foo", NotificationMethodType.EMAIL, "abc"); repo.update("444", "123", "Foo", NotificationMethodType.EMAIL, "abc", 0);
NotificationMethod nm = repo.findById("444", "123"); NotificationMethod nm = repo.findById("444", "123");
assertEquals(nm, new NotificationMethod("123", "Foo", NotificationMethodType.EMAIL, "abc")); assertEquals(nm, new NotificationMethod("123", "Foo", NotificationMethodType.EMAIL, "abc", 0));
}
public void shouldUpdateWebhookWithNonZeroPeriod() {
NotificationMethod nmOriginal = repo.create("555", "MyWebhook", NotificationMethodType.WEBHOOK, "http://localhost:33", 0);
repo.update("555", nmOriginal.getId(), "MyWebhook", NotificationMethodType.WEBHOOK, "http://localhost:33", 60);
NotificationMethod nmUpdated = repo.findById("555", nmOriginal.getId());
assertEquals(nmUpdated.getPeriod(), 60);
} }
public void shouldDeleteById() { public void shouldDeleteById() {
@@ -114,16 +129,16 @@ public class NotificationMethodMySqlRepositoryImplTest {
} }
public void shouldUpdateDuplicateWithSameValues() { public void shouldUpdateDuplicateWithSameValues() {
repo.update("444", "123", "Foo", NotificationMethodType.EMAIL, "abc"); repo.update("444", "123", "Foo", NotificationMethodType.EMAIL, "abc", 0);
NotificationMethod nm = repo.findById("444", "123"); NotificationMethod nm = repo.findById("444", "123");
assertEquals(nm, new NotificationMethod("123", "Foo", NotificationMethodType.EMAIL, "abc")); assertEquals(nm, new NotificationMethod("123", "Foo", NotificationMethodType.EMAIL, "abc", 0));
} }
@Test(expectedExceptions = EntityExistsException.class) @Test(expectedExceptions = EntityExistsException.class)
public void shouldNotUpdateDuplicateWithSameName() { public void shouldNotUpdateDuplicateWithSameName() {
repo.update("444", "124", "MyEmail", NotificationMethodType.EMAIL, "abc"); repo.update("444", "124", "MyEmail", NotificationMethodType.EMAIL, "abc", 0);
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014 Hewlett-Packard Development Company, L.P. * (C) Copyright 2014-2016 Hewlett Packard Enterprise Development Company LP
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at * in compliance with the License. You may obtain a copy of the License at
@@ -50,6 +50,7 @@ public class NotificationMethodIntegrationTest extends AbstractMonApiResourceTes
private DBI db; private DBI db;
private NotificationMethod notificationMethod; private NotificationMethod notificationMethod;
private NotificationMethodRepo repo; private NotificationMethodRepo repo;
private ApiConfig config;
@Override @Override
protected void setupResources() throws Exception { protected void setupResources() throws Exception {
@@ -59,9 +60,8 @@ public class NotificationMethodIntegrationTest extends AbstractMonApiResourceTes
handle handle
.execute("insert into notification_method (id, tenant_id, name, type, address, created_at, updated_at) values ('29387234', 'notification-method-test', 'MyEmaila', 'EMAIL', 'a@b', NOW(), NOW())"); .execute("insert into notification_method (id, tenant_id, name, type, address, created_at, updated_at) values ('29387234', 'notification-method-test', 'MyEmaila', 'EMAIL', 'a@b', NOW(), NOW())");
db.close(handle); db.close(handle);
repo = new NotificationMethodMySqlRepoImpl(db, new PersistUtils()); repo = new NotificationMethodMySqlRepoImpl(db, new PersistUtils());
addResources(new NotificationMethodResource(repo, new PersistUtils())); addResources(new NotificationMethodResource(config, repo, new PersistUtils()));
} }
@BeforeTest @BeforeTest
@@ -77,7 +77,7 @@ public class NotificationMethodIntegrationTest extends AbstractMonApiResourceTes
// Fixtures // Fixtures
notificationMethod = notificationMethod =
new NotificationMethod("123", "Joe's Email", NotificationMethodType.EMAIL, "a@b"); new NotificationMethod("123", "Joe's Email", NotificationMethodType.EMAIL, "a@b", 0);
} }
public void shouldCreate() throws Exception { public void shouldCreate() throws Exception {
@@ -89,7 +89,7 @@ public class NotificationMethodIntegrationTest extends AbstractMonApiResourceTes
.post( .post(
ClientResponse.class, ClientResponse.class,
new CreateNotificationMethodCommand(notificationMethod.getName(), new CreateNotificationMethodCommand(notificationMethod.getName(),
notificationMethod.getType(), notificationMethod.getAddress())); notificationMethod.getType(), notificationMethod.getAddress(), "0"));
NotificationMethod newNotificationMethod = response.getEntity(NotificationMethod.class); NotificationMethod newNotificationMethod = response.getEntity(NotificationMethod.class);
String location = response.getHeaders().get("Location").get(0); String location = response.getHeaders().get("Location").get(0);
@@ -107,7 +107,7 @@ public class NotificationMethodIntegrationTest extends AbstractMonApiResourceTes
.header("X-Tenant-Id", TENANT_ID) .header("X-Tenant-Id", TENANT_ID)
.type(MediaType.APPLICATION_JSON) .type(MediaType.APPLICATION_JSON)
.post(ClientResponse.class, .post(ClientResponse.class,
new CreateNotificationMethodCommand("MyEmail", NotificationMethodType.EMAIL, "a@b")); new CreateNotificationMethodCommand("MyEmail", NotificationMethodType.EMAIL, "a@b", "0"));
assertEquals(response.getStatus(), 409); assertEquals(response.getStatus(), 409);
} }
@@ -115,7 +115,7 @@ public class NotificationMethodIntegrationTest extends AbstractMonApiResourceTes
public void shouldDelete() { public void shouldDelete() {
NotificationMethod newMethod = NotificationMethod newMethod =
repo.create(TENANT_ID, notificationMethod.getName(), notificationMethod.getType(), repo.create(TENANT_ID, notificationMethod.getName(), notificationMethod.getType(),
notificationMethod.getAddress()); notificationMethod.getAddress(), 0);
assertNotNull(repo.findById(TENANT_ID, newMethod.getId())); assertNotNull(repo.findById(TENANT_ID, newMethod.getId()));
ClientResponse response = ClientResponse response =

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014 Hewlett-Packard Development Company, L.P. * (C) Copyright 2014-2016 Hewlett Packard Enterprise Development Company LP
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at * in compliance with the License. You may obtain a copy of the License at
@@ -16,6 +16,8 @@ package monasca.api.resource;
import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.GenericType; import com.sun.jersey.api.client.GenericType;
import monasca.api.ApiConfig;
import monasca.api.app.command.CreateNotificationMethodCommand; import monasca.api.app.command.CreateNotificationMethodCommand;
import monasca.api.domain.exception.EntityNotFoundException; import monasca.api.domain.exception.EntityNotFoundException;
import monasca.api.domain.model.common.Paged; import monasca.api.domain.model.common.Paged;
@@ -28,11 +30,13 @@ import monasca.api.resource.exception.ErrorMessages;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static org.mockito.Matchers.any; import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq; import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
@@ -42,29 +46,32 @@ import static org.testng.Assert.*;
public class NotificationMethodResourceTest extends AbstractMonApiResourceTest { public class NotificationMethodResourceTest extends AbstractMonApiResourceTest {
private NotificationMethod notificationMethod, notificationMethodWebhook, notificationMethodPagerduty; private NotificationMethod notificationMethod, notificationMethodWebhook, notificationMethodPagerduty;
private NotificationMethodRepo repo; private NotificationMethodRepo repo;
private ApiConfig config;
@Override @Override
protected void setupResources() throws Exception { protected void setupResources() throws Exception {
super.setupResources(); super.setupResources();
notificationMethod = notificationMethod =
new NotificationMethod("123", "Joe's Email", NotificationMethodType.EMAIL, "a@b"); new NotificationMethod("123", "Joe's Email", NotificationMethodType.EMAIL, "a@b", 0);
notificationMethodWebhook = notificationMethodWebhook =
new NotificationMethod("1234", "MyWh", NotificationMethodType.WEBHOOK, "http://localhost"); new NotificationMethod("1234", "MyWh", NotificationMethodType.WEBHOOK, "http://localhost", 60);
notificationMethodPagerduty = notificationMethodPagerduty =
new NotificationMethod("12345", "MyPd", NotificationMethodType.PAGERDUTY, "nzH2LVRdMzun11HNC2oD"); new NotificationMethod("12345", "MyPd", NotificationMethodType.PAGERDUTY, "nzH2LVRdMzun11HNC2oD", 0);
repo = mock(NotificationMethodRepo.class); repo = mock(NotificationMethodRepo.class);
when(repo.create(eq("abc"), eq("MyEmail"), eq(NotificationMethodType.EMAIL), anyString())) when(repo.create(eq("abc"), eq("MyEmail"), eq(NotificationMethodType.EMAIL), anyString(), eq(0)))
.thenReturn(notificationMethod); .thenReturn(notificationMethod);
when(repo.create(eq("abc"), eq("MyWh"), eq(NotificationMethodType.WEBHOOK), anyString())) when(repo.create(eq("abc"), eq("MyWh"), eq(NotificationMethodType.WEBHOOK), anyString(), anyInt()))
.thenReturn(notificationMethodWebhook); .thenReturn(notificationMethodWebhook);
when(repo.create(eq("abc"), eq("MyPd"), eq(NotificationMethodType.PAGERDUTY), anyString())) when(repo.create(eq("abc"), eq("MyPd"), eq(NotificationMethodType.PAGERDUTY), anyString(), eq(0)))
.thenReturn(notificationMethodPagerduty); .thenReturn(notificationMethodPagerduty);
when(repo.findById(eq("abc"), eq("123"))).thenReturn(notificationMethod); when(repo.findById(eq("abc"), eq("123"))).thenReturn(notificationMethod);
when(repo.find(eq("abc"), (List<String>) anyList(), anyString(), anyInt())) when(repo.find(eq("abc"), (List<String>) anyList(), anyString(), anyInt()))
.thenReturn(Arrays.asList(notificationMethod)); .thenReturn(Arrays.asList(notificationMethod));
addResources(new NotificationMethodResource(repo, new PersistUtils())); config = mock(ApiConfig.class);
config.validNotificationPeriods = Arrays.asList(0, 60);
addResources(new NotificationMethodResource(config, repo, new PersistUtils()));
} }
public void shouldCreate() { public void shouldCreate() {
@@ -74,31 +81,31 @@ public class NotificationMethodResourceTest extends AbstractMonApiResourceTest {
.header("X-Tenant-Id", "abc") .header("X-Tenant-Id", "abc")
.header("Content-Type", MediaType.APPLICATION_JSON) .header("Content-Type", MediaType.APPLICATION_JSON)
.post(ClientResponse.class, .post(ClientResponse.class,
new CreateNotificationMethodCommand("MyEmail", NotificationMethodType.EMAIL, "a@a.com")); new CreateNotificationMethodCommand("MyEmail", NotificationMethodType.EMAIL, "a@a.com", "0"));
NotificationMethod newNotificationMethod = response.getEntity(NotificationMethod.class); NotificationMethod newNotificationMethod = response.getEntity(NotificationMethod.class);
String location = response.getHeaders().get("Location").get(0); String location = response.getHeaders().get("Location").get(0);
assertEquals(response.getStatus(), 201); assertEquals(response.getStatus(), 201);
assertEquals(location, "/v2.0/notification-methods/" + newNotificationMethod.getId()); assertEquals(location, "/v2.0/notification-methods/" + newNotificationMethod.getId());
assertEquals(newNotificationMethod, notificationMethod); assertEquals(newNotificationMethod, notificationMethod);
verify(repo).create(eq("abc"), eq("MyEmail"), eq(NotificationMethodType.EMAIL), anyString()); verify(repo).create(eq("abc"), eq("MyEmail"), eq(NotificationMethodType.EMAIL), anyString(), eq(0));
} }
public void shouldUpdate() { public void shouldUpdate() {
when( when(
repo.update(eq("abc"), anyString(), anyString(), any(NotificationMethodType.class), repo.update(eq("abc"), anyString(), anyString(), any(NotificationMethodType.class),
anyString())).thenReturn(notificationMethod); anyString(), eq(0))).thenReturn(notificationMethod);
ClientResponse response = ClientResponse response =
client() client()
.resource("/v2.0/notification-methods/123") .resource("/v2.0/notification-methods/123")
.header("X-Tenant-Id", "abc") .header("X-Tenant-Id", "abc")
.header("Content-Type", MediaType.APPLICATION_JSON) .header("Content-Type", MediaType.APPLICATION_JSON)
.put(ClientResponse.class, .put(ClientResponse.class,
new CreateNotificationMethodCommand("Foo", NotificationMethodType.EMAIL, "a@a.com")); new CreateNotificationMethodCommand("Foo", NotificationMethodType.EMAIL, "a@a.com", "0"));
assertEquals(response.getStatus(), 200); assertEquals(response.getStatus(), 200);
verify(repo).update(eq("abc"), eq("123"), eq("Foo"), eq(NotificationMethodType.EMAIL), verify(repo).update(eq("abc"), eq("123"), eq("Foo"), eq(NotificationMethodType.EMAIL),
eq("a@a.com")); eq("a@a.com"), eq(0));
} }
public void should422OnBadEnum() { public void should422OnBadEnum() {
@@ -108,7 +115,7 @@ public class NotificationMethodResourceTest extends AbstractMonApiResourceTest {
.header("X-Tenant-Id", "abc") .header("X-Tenant-Id", "abc")
.header("Content-Type", MediaType.APPLICATION_JSON) .header("Content-Type", MediaType.APPLICATION_JSON)
.post(ClientResponse.class, .post(ClientResponse.class,
new CreateNotificationMethodCommand("MyEmail", null, "a@b")); new CreateNotificationMethodCommand("MyEmail", null, "a@b", "0"));
String e = response.getEntity(String.class); String e = response.getEntity(String.class);
ErrorMessages.assertThat(e).matches("unprocessable_entity", 422, ErrorMessages.assertThat(e).matches("unprocessable_entity", 422,
@@ -122,7 +129,7 @@ public class NotificationMethodResourceTest extends AbstractMonApiResourceTest {
.header("X-Tenant-Id", "abc") .header("X-Tenant-Id", "abc")
.header("Content-Type", MediaType.APPLICATION_JSON) .header("Content-Type", MediaType.APPLICATION_JSON)
.post(ClientResponse.class, .post(ClientResponse.class,
new CreateNotificationMethodCommand("MyEmail", NotificationMethodType.EMAIL, "a@")); new CreateNotificationMethodCommand("MyEmail", NotificationMethodType.EMAIL, "a@", "0"));
ErrorMessages.assertThat(response.getEntity(String.class)).matches("unprocessable_entity", 422, ErrorMessages.assertThat(response.getEntity(String.class)).matches("unprocessable_entity", 422,
"Address a@ is not of correct format"); "Address a@ is not of correct format");
@@ -135,7 +142,7 @@ public class NotificationMethodResourceTest extends AbstractMonApiResourceTest {
.header("X-Tenant-Id", "abc") .header("X-Tenant-Id", "abc")
.header("Content-Type", MediaType.APPLICATION_JSON) .header("Content-Type", MediaType.APPLICATION_JSON)
.post(ClientResponse.class, .post(ClientResponse.class,
new CreateNotificationMethodCommand("MyEmail", NotificationMethodType.EMAIL, "a@f ,")); new CreateNotificationMethodCommand("MyEmail", NotificationMethodType.EMAIL, "a@f ,", "0"));
ErrorMessages.assertThat(response.getEntity(String.class)).matches("unprocessable_entity", 422, ErrorMessages.assertThat(response.getEntity(String.class)).matches("unprocessable_entity", 422,
"Address a@f , is not of correct format"); "Address a@f , is not of correct format");
@@ -148,7 +155,7 @@ public class NotificationMethodResourceTest extends AbstractMonApiResourceTest {
.header("X-Tenant-Id", "abc") .header("X-Tenant-Id", "abc")
.header("Content-Type", MediaType.APPLICATION_JSON) .header("Content-Type", MediaType.APPLICATION_JSON)
.post(ClientResponse.class, .post(ClientResponse.class,
new CreateNotificationMethodCommand("MyEmail", NotificationMethodType.EMAIL, "")); new CreateNotificationMethodCommand("MyEmail", NotificationMethodType.EMAIL, "", "0"));
ErrorMessages.assertThat(response.getEntity(String.class)).matches("unprocessable_entity", 422, ErrorMessages.assertThat(response.getEntity(String.class)).matches("unprocessable_entity", 422,
"[address may not be empty (was )"); "[address may not be empty (was )");
@@ -166,7 +173,7 @@ public class NotificationMethodResourceTest extends AbstractMonApiResourceTest {
"01234567889012345678890123456788901234567889012345678890123456788901234567889012345678890123456788901234567889" "01234567889012345678890123456788901234567889012345678890123456788901234567889012345678890123456788901234567889"
+ "01234567889012345678890123456788901234567889012345678890123456788901234567889012345678890123456788901234567889" + "01234567889012345678890123456788901234567889012345678890123456788901234567889012345678890123456788901234567889"
+ "01234567889012345678890123456788901234567889012345678890123456788901234567889012345678890123456788901234567889", + "01234567889012345678890123456788901234567889012345678890123456788901234567889012345678890123456788901234567889",
NotificationMethodType.EMAIL, "a@b")); NotificationMethodType.EMAIL, "a@b", "0"));
ErrorMessages.assertThat(response.getEntity(String.class)).matches("unprocessable_entity", 422, ErrorMessages.assertThat(response.getEntity(String.class)).matches("unprocessable_entity", 422,
"[name size must be between 1 and 250"); "[name size must be between 1 and 250");
@@ -194,13 +201,69 @@ public class NotificationMethodResourceTest extends AbstractMonApiResourceTest {
+ "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890"
+ "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890"
+ "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890"
+ "123456789012345678901234567890")); + "123456789012345678901234567890", "0"));
String e = response.getEntity(String.class); String e = response.getEntity(String.class);
ErrorMessages.assertThat(e).matches("unprocessable_entity", 422, ErrorMessages.assertThat(e).matches("unprocessable_entity", 422,
"[address size must be between 1 and 512"); "[address size must be between 1 and 512");
} }
public void should422OnNonIntPeriod() {
ClientResponse response =
client()
.resource("/v2.0/notification-methods")
.header("X-Tenant-Id", "abc")
.header("Content-Type", MediaType.APPLICATION_JSON)
.post(ClientResponse.class,
new CreateNotificationMethodCommand("MyEmail", NotificationMethodType.EMAIL, "a@a.com", "not a int"));
String e = response.getEntity(String.class);
ErrorMessages.assertThat(e).matches("unprocessable_entity", 422,
"period (not a int) must be valid number");
}
public void should422OnNonZeroPeriodForEmail() {
ClientResponse response =
client()
.resource("/v2.0/notification-methods")
.header("X-Tenant-Id", "abc")
.header("Content-Type", MediaType.APPLICATION_JSON)
.post(ClientResponse.class,
new CreateNotificationMethodCommand("MyEmail", NotificationMethodType.EMAIL, "a@a.com", "60"));
String e = response.getEntity(String.class);
ErrorMessages.assertThat(e).matches("unprocessable_entity", 422,
"Period can not be non zero for Email");
}
public void should422OnNonZeroPeriodForPagerduty() {
ClientResponse response =
client().resource("/v2.0/notification-methods")
.header("X-Tenant-Id", "abc")
.header("Content-Type", MediaType.APPLICATION_JSON)
.post(ClientResponse.class,
new CreateNotificationMethodCommand("MyPd", NotificationMethodType.PAGERDUTY,
"http://localhost", "60"));
String e = response.getEntity(String.class);
ErrorMessages.assertThat(e).matches("unprocessable_entity", 422,
"Period can not be non zero for Pagerduty");
}
public void should422OnInvalidPeriodForWebhook() {
ClientResponse response =
client().resource("/v2.0/notification-methods")
.header("X-Tenant-Id", "abc")
.header("Content-Type", MediaType.APPLICATION_JSON)
.post(ClientResponse.class,
new CreateNotificationMethodCommand("MyWh", NotificationMethodType.WEBHOOK,
"http://localhost", "5"));
String e = response.getEntity(String.class);
ErrorMessages.assertThat(e).matches("unprocessable_entity", 422,
"5 is not a valid period");
}
public void shouldList() { public void shouldList() {
@@ -213,7 +276,7 @@ public class NotificationMethodResourceTest extends AbstractMonApiResourceTest {
nm = nm =
new NotificationMethod((String) lhm.get("id"), (String) lhm.get("name"), new NotificationMethod((String) lhm.get("id"), (String) lhm.get("name"),
NotificationMethodType.fromJson((String) lhm.get("type")), NotificationMethodType.fromJson((String) lhm.get("type")),
(String) lhm.get("address")); (String) lhm.get("address"), 0);
List<NotificationMethod> notificationMethods = Arrays.asList(nm); List<NotificationMethod> notificationMethods = Arrays.asList(nm);
assertEquals(notificationMethods, Arrays.asList(notificationMethod)); assertEquals(notificationMethods, Arrays.asList(notificationMethod));
@@ -278,7 +341,7 @@ public class NotificationMethodResourceTest extends AbstractMonApiResourceTest {
.header("X-Tenant-Id", "abc") .header("X-Tenant-Id", "abc")
.header("Content-Type", MediaType.APPLICATION_JSON) .header("Content-Type", MediaType.APPLICATION_JSON)
.post(NotificationMethod.class, .post(NotificationMethod.class,
new CreateNotificationMethodCommand(null, null, "8675309")); new CreateNotificationMethodCommand(null, null, "8675309", "0"));
fail(); fail();
} catch (Exception e) { } catch (Exception e) {
assertTrue(e.getMessage().contains("422")); assertTrue(e.getMessage().contains("422"));
@@ -301,7 +364,7 @@ public class NotificationMethodResourceTest extends AbstractMonApiResourceTest {
.header("Content-Type", MediaType.APPLICATION_JSON) .header("Content-Type", MediaType.APPLICATION_JSON)
.post(ClientResponse.class, .post(ClientResponse.class,
new CreateNotificationMethodCommand("MyWh", NotificationMethodType.WEBHOOK, new CreateNotificationMethodCommand("MyWh", NotificationMethodType.WEBHOOK,
"http://localhost")); "http://localhost", "0"));
NotificationMethod newNotificationMethod = response.getEntity(NotificationMethod.class); NotificationMethod newNotificationMethod = response.getEntity(NotificationMethod.class);
String location = response.getHeaders().get("Location").get(0); String location = response.getHeaders().get("Location").get(0);
@@ -309,7 +372,25 @@ public class NotificationMethodResourceTest extends AbstractMonApiResourceTest {
assertEquals(response.getStatus(), 201); assertEquals(response.getStatus(), 201);
assertEquals(location, "/v2.0/notification-methods/" + newNotificationMethod.getId()); assertEquals(location, "/v2.0/notification-methods/" + newNotificationMethod.getId());
assertEquals(newNotificationMethod, notificationMethodWebhook); assertEquals(newNotificationMethod, notificationMethodWebhook);
verify(repo).create(eq("abc"), eq("MyWh"), eq(NotificationMethodType.WEBHOOK), anyString()); verify(repo).create(eq("abc"), eq("MyWh"), eq(NotificationMethodType.WEBHOOK), anyString(), eq(0));
}
public void shouldCreateWebhookNotificationWithNonZeroPeriod() {
ClientResponse response =
client().resource("/v2.0/notification-methods")
.header("X-Tenant-Id", "abc")
.header("Content-Type", MediaType.APPLICATION_JSON)
.post(ClientResponse.class,
new CreateNotificationMethodCommand("MyWh", NotificationMethodType.WEBHOOK,
"http://localhost", "60"));
NotificationMethod newNotificationMethod = response.getEntity(NotificationMethod.class);
String location = response.getHeaders().get("Location").get(0);
assertEquals(response.getStatus(), 201);
assertEquals(location, "/v2.0/notification-methods/" + newNotificationMethod.getId());
assertEquals(newNotificationMethod, notificationMethodWebhook);
verify(repo).create(eq("abc"), eq("MyWh"), eq(NotificationMethodType.WEBHOOK), anyString(), eq(60));
} }
public void shouldCreatePagerdutyNotification() { public void shouldCreatePagerdutyNotification() {
@@ -319,7 +400,7 @@ public class NotificationMethodResourceTest extends AbstractMonApiResourceTest {
.header("Content-Type", MediaType.APPLICATION_JSON) .header("Content-Type", MediaType.APPLICATION_JSON)
.post(ClientResponse.class, .post(ClientResponse.class,
new CreateNotificationMethodCommand("MyPd", NotificationMethodType.PAGERDUTY, new CreateNotificationMethodCommand("MyPd", NotificationMethodType.PAGERDUTY,
"http://localhost")); "http://localhost", "0"));
NotificationMethod newNotificationMethod = response.getEntity(NotificationMethod.class); NotificationMethod newNotificationMethod = response.getEntity(NotificationMethod.class);
String location = response.getHeaders().get("Location").get(0); String location = response.getHeaders().get("Location").get(0);
@@ -327,6 +408,6 @@ public class NotificationMethodResourceTest extends AbstractMonApiResourceTest {
assertEquals(response.getStatus(), 201); assertEquals(response.getStatus(), 201);
assertEquals(location, "/v2.0/notification-methods/" + newNotificationMethod.getId()); assertEquals(location, "/v2.0/notification-methods/" + newNotificationMethod.getId());
assertEquals(newNotificationMethod, notificationMethodPagerduty); assertEquals(newNotificationMethod, notificationMethodPagerduty);
verify(repo).create(eq("abc"), eq("MyPd"), eq(NotificationMethodType.PAGERDUTY), anyString()); verify(repo).create(eq("abc"), eq("MyPd"), eq(NotificationMethodType.PAGERDUTY), anyString(), eq(0));
} }
} }

View File

@@ -0,0 +1 @@
{"name":"MyWebhook","type":"webhook","address":"http://somedomain.com","period":"60"}

View File

@@ -1 +1 @@
{"id":"123","links":[{"rel":"self","href":"https://cloudsvc.example.com/v1.0"}],"name":"MyEmail","type":"EMAIL","address":"a@b"} {"id":"123","links":[{"rel":"self","href":"https://cloudsvc.example.com/v1.0"}],"name":"MyEmail","type":"EMAIL","address":"a@b", "period":0}

View File

@@ -10,6 +10,9 @@ metricsTopic: metrics
# Topic for publishing domain events to # Topic for publishing domain events to
eventsTopic: events eventsTopic: events
validNotificationPeriods:
- 60
databaseConfiguration: databaseConfiguration:
# vertica | influxdb # vertica | influxdb
databaseType: influxdb databaseType: influxdb

View File

@@ -4,6 +4,7 @@ CREATE TABLE `notification_method` (
`name` varchar(250) NOT NULL DEFAULT '', `name` varchar(250) NOT NULL DEFAULT '',
`type` varchar(10) NOT NULL DEFAULT 'EMAIL' check type in ('EMAIL', 'WEBHOOK', 'PAGERDUTY'), `type` varchar(10) NOT NULL DEFAULT 'EMAIL' check type in ('EMAIL', 'WEBHOOK', 'PAGERDUTY'),
`address` varchar(100) NOT NULL DEFAULT '', `address` varchar(100) NOT NULL DEFAULT '',
`period` int NOT NULL DEFAULT 0,
`created_at` datetime NOT NULL, `created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL, `updated_at` datetime NOT NULL,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)

View File

@@ -1,4 +1,4 @@
# Copyright 2014 Hewlett-Packard # (C) Copyright 2014-2016 Hewlett Packard Enterprise Development Company LP
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may # Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain # not use this file except in compliance with the License. You may obtain
@@ -31,7 +31,7 @@ class NotificationsRepository(mysql_repository.MySQLRepository,
super(NotificationsRepository, self).__init__() super(NotificationsRepository, self).__init__()
def create_notification(self, tenant_id, name, def create_notification(self, tenant_id, name,
notification_type, address): notification_type, address, period):
cnxn, cursor = self._get_cnxn_cursor_tuple() cnxn, cursor = self._get_cnxn_cursor_tuple()
@@ -58,15 +58,17 @@ class NotificationsRepository(mysql_repository.MySQLRepository,
name, name,
type, type,
address, address,
period,
created_at, created_at,
updated_at updated_at
) values (%s, %s, %s, % s, %s, %s, %s)""" ) values (%s, %s, %s, %s, %s, %s, %s, %s)"""
parms = [notification_id, parms = [notification_id,
tenant_id, tenant_id,
name.encode('utf8'), name.encode('utf8'),
notification_type.encode('utf8'), notification_type.encode('utf8'),
address.encode('utf8'), address.encode('utf8'),
period,
now, now,
now] now]
@@ -166,7 +168,7 @@ class NotificationsRepository(mysql_repository.MySQLRepository,
@mysql_repository.mysql_try_catch_block @mysql_repository.mysql_try_catch_block
def update_notification( def update_notification(
self, id, tenant_id, name, type, address): self, id, tenant_id, name, type, address, period):
cnxn, cursor = self._get_cnxn_cursor_tuple() cnxn, cursor = self._get_cnxn_cursor_tuple()
@@ -178,11 +180,12 @@ class NotificationsRepository(mysql_repository.MySQLRepository,
set name = %s, set name = %s,
type = %s, type = %s,
address = %s, address = %s,
period = %s,
updated_at = %s updated_at = %s
where tenant_id = %s and id = %s""" where tenant_id = %s and id = %s"""
parms = [name.encode('utf8'), type.encode('utf8'), address.encode( parms = [name.encode('utf8'), type.encode('utf8'), address.encode(
'utf8'), now, tenant_id, id] 'utf8'), period, now, tenant_id, id]
cursor.execute(query, parms) cursor.execute(query, parms)

View File

@@ -1,4 +1,4 @@
# Copyright 2014 Hewlett-Packard # (C) Copyright 2014-2016 Hewlett Packard Enterprise Development Company LP
# Copyright 2016 FUJITSU LIMITED # Copyright 2016 FUJITSU LIMITED
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may # Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -23,7 +23,7 @@ class NotificationsRepository(object):
@abc.abstractmethod @abc.abstractmethod
def create_notification(self, tenant_id, name, notification_type, def create_notification(self, tenant_id, name, notification_type,
address): address, period):
return return
@abc.abstractmethod @abc.abstractmethod
@@ -40,5 +40,5 @@ class NotificationsRepository(object):
@abc.abstractmethod @abc.abstractmethod
def update_notification(self, notification_id, tenant_id, name, notification_type, def update_notification(self, notification_id, tenant_id, name, notification_type,
address): address, period):
return return

View File

@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2015 Robin Hood # Copyright 2015 Robin Hood
# Copyright 2016 FUJITSU LIMITED # Copyright 2016 FUJITSU LIMITED
# (C) Copyright 2016 Hewlett Packard Enterprise Development Company LP
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@@ -74,6 +75,7 @@ def create_nm_model(metadata=None):
Column('name', String(250)), Column('name', String(250)),
Column('type', String(20)), Column('type', String(20)),
Column('address', String(512)), Column('address', String(512)),
Column('period', Integer),
Column('created_at', DateTime), Column('created_at', DateTime),
Column('updated_at', DateTime)) Column('updated_at', DateTime))

View File

@@ -1,4 +1,4 @@
# Copyright 2014 Hewlett-Packard # (C) Copyright 2014,2016 Hewlett Packard Enterprise Development Company LP
# Copyright 2016 FUJITSU LIMITED # Copyright 2016 FUJITSU LIMITED
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may # Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -58,6 +58,7 @@ class NotificationsRepository(sql_repository.SQLRepository,
name=bindparam('b_name'), name=bindparam('b_name'),
type=bindparam('b_type'), type=bindparam('b_type'),
address=bindparam('b_address'), address=bindparam('b_address'),
period=bindparam('b_period'),
created_at=bindparam('b_created_at'), created_at=bindparam('b_created_at'),
updated_at=bindparam('b_updated_at'))) updated_at=bindparam('b_updated_at')))
@@ -72,6 +73,7 @@ class NotificationsRepository(sql_repository.SQLRepository,
name=bindparam('b_name'), name=bindparam('b_name'),
type=bindparam('b_type'), type=bindparam('b_type'),
address=bindparam('b_address'), address=bindparam('b_address'),
period=bindparam('b_period'),
updated_at=bindparam('b_updated_at'))) updated_at=bindparam('b_updated_at')))
self._select_nm_id_query = (select([nm]) self._select_nm_id_query = (select([nm])
@@ -85,7 +87,7 @@ class NotificationsRepository(sql_repository.SQLRepository,
nm.c.name == bindparam('b_name')))) nm.c.name == bindparam('b_name'))))
def create_notification(self, tenant_id, name, def create_notification(self, tenant_id, name,
notification_type, address): notification_type, address, period):
with self._db_engine.connect() as conn: with self._db_engine.connect() as conn:
row = conn.execute(self._select_nm_count_name_query, row = conn.execute(self._select_nm_count_name_query,
@@ -105,6 +107,7 @@ class NotificationsRepository(sql_repository.SQLRepository,
b_name=name.encode('utf8'), b_name=name.encode('utf8'),
b_type=notification_type.encode('utf8'), b_type=notification_type.encode('utf8'),
b_address=address.encode('utf8'), b_address=address.encode('utf8'),
b_period=period,
b_created_at=now, b_created_at=now,
b_updated_at=now) b_updated_at=now)
@@ -186,7 +189,7 @@ class NotificationsRepository(sql_repository.SQLRepository,
b_name=name.encode('utf8')).fetchone() b_name=name.encode('utf8')).fetchone()
@sql_repository.sql_try_catch_block @sql_repository.sql_try_catch_block
def update_notification(self, notification_id, tenant_id, name, notification_type, address): def update_notification(self, notification_id, tenant_id, name, notification_type, address, period):
with self._db_engine.connect() as conn: with self._db_engine.connect() as conn:
now = datetime.datetime.utcnow() now = datetime.datetime.utcnow()
@@ -196,6 +199,7 @@ class NotificationsRepository(sql_repository.SQLRepository,
b_name=name.encode('utf8'), b_name=name.encode('utf8'),
b_type=notification_type.encode('utf8'), b_type=notification_type.encode('utf8'),
b_address=address.encode('utf8'), b_address=address.encode('utf8'),
b_period=period,
b_updated_at=now) b_updated_at=now)
if cursor.rowcount < 1: if cursor.rowcount < 1:

View File

@@ -19,6 +19,7 @@ CREATE TABLE `notification_method` (
`name` varchar(250) DEFAULT NULL, `name` varchar(250) DEFAULT NULL,
`type` varchar(20) NOT NULL, `type` varchar(20) NOT NULL,
`address` varchar(512) DEFAULT NULL, `address` varchar(512) DEFAULT NULL,
`period` int NOT NULL DEFAULT 0,
`created_at` datetime NOT NULL, `created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL, `updated_at` datetime NOT NULL,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)

View File

@@ -1,5 +1,6 @@
# Copyright 2015 Cray # Copyright 2015 Cray
# Copyright 2016 FUJITSU LIMITED # Copyright 2016 FUJITSU LIMITED
# (C) Copyright 2016 Hewlett Packard Enterprise Development Company LP
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may # Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain # not use this file except in compliance with the License. You may obtain
@@ -57,6 +58,7 @@ class TestNotificationMethodRepoDB(testtools.TestCase, fixtures.TestWithFixtures
name=bindparam('name'), name=bindparam('name'),
type=bindparam('type'), type=bindparam('type'),
address=bindparam('address'), address=bindparam('address'),
period=bindparam('period'),
created_at=bindparam('created_at'), created_at=bindparam('created_at'),
updated_at=bindparam('updated_at'))) updated_at=bindparam('updated_at')))
@@ -80,6 +82,7 @@ class TestNotificationMethodRepoDB(testtools.TestCase, fixtures.TestWithFixtures
'name': 'MyEmail', 'name': 'MyEmail',
'type': 'EMAIL', 'type': 'EMAIL',
'address': 'a@b', 'address': 'a@b',
'period': 0,
'created_at': datetime.datetime.now(), 'created_at': datetime.datetime.now(),
'updated_at': datetime.datetime.now()}, 'updated_at': datetime.datetime.now()},
{'id': '124', {'id': '124',
@@ -87,6 +90,7 @@ class TestNotificationMethodRepoDB(testtools.TestCase, fixtures.TestWithFixtures
'name': 'OtherEmail', 'name': 'OtherEmail',
'type': 'EMAIL', 'type': 'EMAIL',
'address': 'a@b', 'address': 'a@b',
'period': 0,
'created_at': datetime.datetime.now(), 'created_at': datetime.datetime.now(),
'updated_at': datetime.datetime.now()}] 'updated_at': datetime.datetime.now()}]
@@ -125,7 +129,8 @@ class TestNotificationMethodRepoDB(testtools.TestCase, fixtures.TestWithFixtures
nmA = self.repo.create_notification('555', nmA = self.repo.create_notification('555',
'MyEmail', 'MyEmail',
'EMAIL', 'EMAIL',
'a@b') 'a@b',
0)
nmB = self.repo.list_notification('555', nmA) nmB = self.repo.list_notification('555', nmA)
self.assertEqual(nmA, nmB['id']) self.assertEqual(nmA, nmB['id'])
@@ -135,7 +140,8 @@ class TestNotificationMethodRepoDB(testtools.TestCase, fixtures.TestWithFixtures
'555', '555',
'MyEmail', 'MyEmail',
'EMAIL', 'EMAIL',
'a@b') 'a@b',
0)
def test_should_exists(self): def test_should_exists(self):
from monasca_api.common.repositories import exceptions from monasca_api.common.repositories import exceptions
@@ -159,7 +165,7 @@ class TestNotificationMethodRepoDB(testtools.TestCase, fixtures.TestWithFixtures
def test_update(self): def test_update(self):
import copy import copy
self.repo.update_notification('123', '444', 'Foo', 'EMAIL', 'abc') self.repo.update_notification('123', '444', 'Foo', 'EMAIL', 'abc', 0)
nm = self.repo.list_notification('444', '123') nm = self.repo.list_notification('444', '123')
new_nm = copy.deepcopy(self.default_nms[0]) new_nm = copy.deepcopy(self.default_nms[0])
new_nm['name'] = 'Foo' new_nm['name'] = 'Foo'
@@ -175,7 +181,8 @@ class TestNotificationMethodRepoDB(testtools.TestCase, fixtures.TestWithFixtures
'no really tenant', 'no really tenant',
'', '',
'', '',
'') '',
0)
def test_should_delete(self): def test_should_delete(self):
from monasca_api.common.repositories import exceptions from monasca_api.common.repositories import exceptions
@@ -187,8 +194,8 @@ class TestNotificationMethodRepoDB(testtools.TestCase, fixtures.TestWithFixtures
def test_should_update_duplicate_with_same_values(self): def test_should_update_duplicate_with_same_values(self):
import copy import copy
self.repo.update_notification('123', '444', 'Foo', 'EMAIL', 'abc') self.repo.update_notification('123', '444', 'Foo', 'EMAIL', 'abc', 0)
self.repo.update_notification('123', '444', 'Foo', 'EMAIL', 'abc') self.repo.update_notification('123', '444', 'Foo', 'EMAIL', 'abc', 0)
nm = self.repo.list_notification('444', '123') nm = self.repo.list_notification('444', '123')
new_nm = copy.deepcopy(self.default_nms[0]) new_nm = copy.deepcopy(self.default_nms[0])
new_nm['name'] = 'Foo' new_nm['name'] = 'Foo'

View File

@@ -245,59 +245,92 @@ class TestConvertTimeString(unittest.TestCase):
ValueError, ValueError,
helpers._convert_time_string, date_time_string) helpers._convert_time_string, date_time_string)
valid_periods = [0, 60]
class TestNotificationValidation(unittest.TestCase): class TestNotificationValidation(unittest.TestCase):
def test_validation_for_email(self): def test_validation_for_email(self):
notification = {"name": "MyEmail", "type": "EMAIL", "address": "name@domain.com"} notification = {"name": "MyEmail", "type": "EMAIL", "address": "name@domain.com"}
try: try:
schemas_notifications.validate(notification) schemas_notifications.parse_and_validate(notification, valid_periods)
except schemas_exceptions.ValidationException: except schemas_exceptions.ValidationException:
self.fail("shouldn't happen") self.fail("shouldn't happen")
def test_validation_exception_for_email(self): def test_validation_exception_for_invalid_email_address(self):
notification = {"name": "MyEmail", "type": "EMAIL", "address": "name@domain."} notification = {"name": "MyEmail", "type": "EMAIL", "address": "name@domain."}
with self.assertRaises(schemas_exceptions.ValidationException) as ve: with self.assertRaises(schemas_exceptions.ValidationException) as ve:
schemas_notifications.validate(notification) schemas_notifications.parse_and_validate(notification, valid_periods)
ex = ve.exception ex = ve.exception
self.assertEqual("Address name@domain. is not of correct format", ex.message) self.assertEqual("Address name@domain. is not of correct format", ex.message)
def test_validation_exception_for_invalid_period_for_email(self):
notification = {"name": "MyEmail", "type": "EMAIL", "address": "name@domain.com", "period": "60"}
with self.assertRaises(schemas_exceptions.ValidationException) as ve:
schemas_notifications.parse_and_validate(notification, valid_periods)
ex = ve.exception
self.assertEqual("Period can only be set with webhooks", ex.message)
def test_validation_for_webhook(self): def test_validation_for_webhook(self):
notification = {"name": "MyWebhook", "type": "WEBHOOK", "address": "http://somedomain.com"} notification = {"name": "MyWebhook", "type": "WEBHOOK", "address": "http://somedomain.com"}
try: try:
schemas_notifications.validate(notification) schemas_notifications.parse_and_validate(notification, valid_periods)
except schemas_exceptions.ValidationException:
self.fail("shouldn't happen")
def test_validation_for_webhook_non_zero_period(self):
notification = {"name": "MyWebhook", "type": "WEBHOOK", "address": "http://somedomain.com",
"period": 60}
try:
schemas_notifications.parse_and_validate(notification, valid_periods)
except schemas_exceptions.ValidationException: except schemas_exceptions.ValidationException:
self.fail("shouldn't happen") self.fail("shouldn't happen")
def test_validation_exception_for_webhook_no_scheme(self): def test_validation_exception_for_webhook_no_scheme(self):
notification = {"name": "MyWebhook", "type": "WEBHOOK", "address": "//somedomain.com"} notification = {"name": "MyWebhook", "type": "WEBHOOK", "address": "//somedomain.com"}
with self.assertRaises(schemas_exceptions.ValidationException) as ve: with self.assertRaises(schemas_exceptions.ValidationException) as ve:
schemas_notifications.validate(notification) schemas_notifications.parse_and_validate(notification, valid_periods)
ex = ve.exception ex = ve.exception
self.assertEqual("Address //somedomain.com does not have URL scheme", ex.message) self.assertEqual("Address //somedomain.com does not have URL scheme", ex.message)
def test_validation_exception_for_webhook_no_netloc(self): def test_validation_exception_for_webhook_no_netloc(self):
notification = {"name": "MyWebhook", "type": "WEBHOOK", "address": "http://"} notification = {"name": "MyWebhook", "type": "WEBHOOK", "address": "http://"}
with self.assertRaises(schemas_exceptions.ValidationException) as ve: with self.assertRaises(schemas_exceptions.ValidationException) as ve:
schemas_notifications.validate(notification) schemas_notifications.parse_and_validate(notification, valid_periods)
ex = ve.exception ex = ve.exception
self.assertEqual("Address http:// does not have network location", ex.message) self.assertEqual("Address http:// does not have network location", ex.message)
def test_validation_exception_for_webhook_invalid_scheme(self): def test_validation_exception_for_webhook_invalid_scheme(self):
notification = {"name": "MyWebhook", "type": "WEBHOOK", "address": "ftp://somedomain.com"} notification = {"name": "MyWebhook", "type": "WEBHOOK", "address": "ftp://somedomain.com"}
with self.assertRaises(schemas_exceptions.ValidationException) as ve: with self.assertRaises(schemas_exceptions.ValidationException) as ve:
schemas_notifications.validate(notification) schemas_notifications.parse_and_validate(notification, valid_periods)
ex = ve.exception ex = ve.exception
self.assertEqual("Address ftp://somedomain.com scheme is not in ['http', 'https']", ex.message) self.assertEqual("Address ftp://somedomain.com scheme is not in ['http', 'https']", ex.message)
def test_validation_exception_for_webhook_invalid_period(self):
notification = {"name": "MyWebhook", "type": "WEBHOOK", "address": "//somedomain.com",
"period": "10"}
with self.assertRaises(schemas_exceptions.ValidationException) as ve:
schemas_notifications.parse_and_validate(notification, valid_periods)
ex = ve.exception
self.assertEqual("10 is not a valid period", ex.message)
def test_validation_for_pagerduty(self): def test_validation_for_pagerduty(self):
notification = {"name": "MyPagerduty", "type": "PAGERDUTY", notification = {"name": "MyPagerduty", "type": "PAGERDUTY",
"address": "nzH2LVRdMzun11HNC2oD"} "address": "nzH2LVRdMzun11HNC2oD"}
try: try:
schemas_notifications.validate(notification) schemas_notifications.parse_and_validate(notification, valid_periods)
except schemas_exceptions.ValidationException: except schemas_exceptions.ValidationException:
self.fail("shouldn't happen") self.fail("shouldn't happen")
def test_validation_exception_for_invalid_period_for_pagerduty(self):
notification = {"name": "MyPagerduty", "type": "PAGERDUTY",
"address": "nzH2LVRdMzun11HNC2oD", "period": 60}
with self.assertRaises(schemas_exceptions.ValidationException) as ve:
schemas_notifications.parse_and_validate(notification, valid_periods)
ex = ve.exception
self.assertEqual("Period can only be set with webhooks", ex.message)
def test_validation_for_max_name_address(self): def test_validation_for_max_name_address(self):
name = "A" * 250 name = "A" * 250
self.assertEqual(250, len(name)) self.assertEqual(250, len(name))
@@ -305,7 +338,7 @@ class TestNotificationValidation(unittest.TestCase):
self.assertEqual(512, len(address)) self.assertEqual(512, len(address))
notification = {"name": name, "type": "WEBHOOK", "address": address} notification = {"name": name, "type": "WEBHOOK", "address": address}
try: try:
schemas_notifications.validate(notification) schemas_notifications.parse_and_validate(notification, valid_periods)
except schemas_exceptions.ValidationException: except schemas_exceptions.ValidationException:
self.fail("shouldn't happen") self.fail("shouldn't happen")
@@ -315,7 +348,7 @@ class TestNotificationValidation(unittest.TestCase):
notification = {"name": name, "type": "WEBHOOK", "address": "http://somedomain.com"} notification = {"name": name, "type": "WEBHOOK", "address": "http://somedomain.com"}
self.assertRaises( self.assertRaises(
schemas_exceptions.ValidationException, schemas_exceptions.ValidationException,
schemas_notifications.validate, notification) schemas_notifications.parse_and_validate, notification, valid_periods)
def test_validation_exception_for_exceeded_address_length(self): def test_validation_exception_for_exceeded_address_length(self):
address = "http://" + "A" * 503 + ".io" address = "http://" + "A" * 503 + ".io"
@@ -323,4 +356,27 @@ class TestNotificationValidation(unittest.TestCase):
notification = {"name": "MyWebhook", "type": "WEBHOOK", "address": address} notification = {"name": "MyWebhook", "type": "WEBHOOK", "address": address}
self.assertRaises( self.assertRaises(
schemas_exceptions.ValidationException, schemas_exceptions.ValidationException,
schemas_notifications.validate, notification) schemas_notifications.parse_and_validate, notification, valid_periods)
def test_validation_exception_for_invalid_period_float(self):
notification = {"name": "MyWebhook", "type": "WEBHOOK", "address": "//somedomain.com",
"period": 1.2}
with self.assertRaises(schemas_exceptions.ValidationException) as ve:
schemas_notifications.parse_and_validate(notification, valid_periods)
ex = ve.exception
self.assertEqual("expected int for dictionary value @ data['period']", ex.message)
def test_validation_exception_for_invalid_period_non_int(self):
notification = {"name": "MyWebhook", "type": "WEBHOOK", "address": "//somedomain.com",
"period": "zero"}
with self.assertRaises(schemas_exceptions.ValidationException) as ve:
schemas_notifications.parse_and_validate(notification, valid_periods)
ex = ve.exception
self.assertEqual("Period zero must be a valid integer", ex.message)
def test_validation_exception_for_missing_period(self):
notification = {"name": "MyEmail", "type": "EMAIL", "address": "name@domain."}
with self.assertRaises(schemas_exceptions.ValidationException) as ve:
schemas_notifications.parse_and_validate(notification, valid_periods, require_all=True)
ex = ve.exception
self.assertEqual("Period is required", ex.message)

View File

@@ -1,4 +1,4 @@
# Copyright 2014 Hewlett-Packard # (C) Copyright 2014-2016 Hewlett Packard Enterprise Development Company LP
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may # Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain # not use this file except in compliance with the License. You may obtain
@@ -15,7 +15,12 @@
from oslo_log import log from oslo_log import log
import six.moves.urllib.parse as urlparse import six.moves.urllib.parse as urlparse
from validate_email import validate_email from validate_email import validate_email
import voluptuous from voluptuous import All
from voluptuous import Any
from voluptuous import Length
from voluptuous import Marker
from voluptuous import Required
from voluptuous import Schema
from monasca_api.v2.common.schemas import exceptions from monasca_api.v2.common.schemas import exceptions
@@ -24,32 +29,39 @@ LOG = log.getLogger(__name__)
schemes = ['http', 'https'] schemes = ['http', 'https']
notification_schema = { notification_schema = {
voluptuous.Required('name'): voluptuous.Schema( Required('name'): Schema(All(Any(str, unicode), Length(max=250))),
voluptuous.All(voluptuous.Any(str, unicode), Required('type'): Schema(Any("EMAIL", "email", "WEBHOOK", "webhook", "PAGERDUTY", "pagerduty")),
voluptuous.Length(max=250))), Required('address'): Schema(All(Any(str, unicode), Length(max=512))),
voluptuous.Required('type'): voluptuous.Schema( Marker('period'): All(Any(int, str))}
voluptuous.Any("EMAIL", "email", "WEBHOOK", "webhook",
"PAGERDUTY", "pagerduty")),
voluptuous.Required('address'): voluptuous.Schema(
voluptuous.All(voluptuous.Any(str, unicode),
voluptuous.Length(max=512)))}
request_body_schema = voluptuous.Schema(voluptuous.Any(notification_schema)) request_body_schema = Schema(Any(notification_schema))
def validate(msg): def parse_and_validate(msg, valid_periods, require_all=False):
try: try:
request_body_schema(msg) request_body_schema(msg)
except Exception as ex: except Exception as ex:
LOG.debug(ex) LOG.debug(ex)
raise exceptions.ValidationException(str(ex)) raise exceptions.ValidationException(str(ex))
if 'period' not in msg:
if require_all:
raise exceptions.ValidationException("Period is required")
else:
msg['period'] = 0
else:
msg['period'] = _parse_and_validate_period(msg['period'], valid_periods)
notification_type = str(msg['type']).upper() notification_type = str(msg['type']).upper()
if notification_type == 'EMAIL': if notification_type == 'EMAIL':
_validate_email(msg['address']) _validate_email(msg['address'])
elif notification_type == 'WEBHOOK': elif notification_type == 'WEBHOOK':
_validate_url(msg['address']) _validate_url(msg['address'])
if notification_type != 'WEBHOOK' and msg['period'] != 0:
raise exceptions.ValidationException("Period can only be set with webhooks")
def _validate_email(address): def _validate_email(address):
if not validate_email(address): if not validate_email(address):
@@ -70,3 +82,13 @@ def _validate_url(address):
if parsed.scheme not in schemes: if parsed.scheme not in schemes:
raise exceptions.ValidationException("Address {} scheme is not in {}" raise exceptions.ValidationException("Address {} scheme is not in {}"
.format(address, schemes)) .format(address, schemes))
def _parse_and_validate_period(period, valid_periods):
try:
period = int(period)
except Exception:
raise exceptions.ValidationException("Period {} must be a valid integer".format(period))
if period != 0 and period not in valid_periods:
raise exceptions.ValidationException("{} is not a valid period".format(period))
return period

View File

@@ -1,5 +1,6 @@
# Copyright 2014 IBM Corp. # Copyright 2014 IBM Corp.
# Copyright 2016 FUJITSU LIMITED # Copyright 2016 FUJITSU LIMITED
# (C) Copyright 2016 Hewlett Packard Enterprise Development Company LP
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may # Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain # not use this file except in compliance with the License. You may obtain
@@ -28,11 +29,12 @@ used in kafka_publisher, but the original settings were at the api/server.py
which I think is at the wrong place. I move these settings here for now, we which I think is at the wrong place. I move these settings here for now, we
need to have a bit more re-engineering to get it right. need to have a bit more re-engineering to get it right.
""" """
global_opts = [cfg.StrOpt('region', help='Region that API is running in')] global_opts = [cfg.StrOpt('region', help='Region that API is running in'),
cfg.ListOpt('valid_notification_periods', default=[0, 60],
help='Valid periods for notification methods')]
cfg.CONF.register_opts(global_opts) cfg.CONF.register_opts(global_opts)
security_opts = [cfg.ListOpt('default_authorized_roles', default=['admin'], security_opts = [cfg.ListOpt('default_authorized_roles', default=['admin'],
help='Roles that are allowed full access to the ' help='Roles that are allowed full access to the '
'API'), 'API'),

View File

@@ -1,4 +1,4 @@
# Copyright 2014 Hewlett-Packard # (C) Copyright 2014-2016 Hewlett Packard Enterprise Development Company LP
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may # Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain # not use this file except in compliance with the License. You may obtain
@@ -39,15 +39,16 @@ class Notifications(notifications_api_v2.NotificationsV2API):
cfg.CONF.security.default_authorized_roles) cfg.CONF.security.default_authorized_roles)
self._notifications_repo = simport.load( self._notifications_repo = simport.load(
cfg.CONF.repositories.notifications_driver)() cfg.CONF.repositories.notifications_driver)()
self.valid_periods = cfg.CONF.valid_notification_periods
def _validate_notification(self, notification): def _parse_and_validate_notification(self, notification, require_all=False):
"""Validates the notification """Validates the notification
:param notification: An event object. :param notification: An event object.
:raises falcon.HTTPBadRequest :raises falcon.HTTPBadRequest
""" """
try: try:
schemas_notifications.validate(notification) schemas_notifications.parse_and_validate(notification, self.valid_periods, require_all=require_all)
except schemas_exceptions.ValidationException as ex: except schemas_exceptions.ValidationException as ex:
LOG.debug(ex) LOG.debug(ex)
raise falcon.HTTPBadRequest('Bad Request', ex.message) raise falcon.HTTPBadRequest('Bad Request', ex.message)
@@ -75,6 +76,7 @@ class Notifications(notifications_api_v2.NotificationsV2API):
name = notification['name'] name = notification['name']
notification_type = notification['type'].upper() notification_type = notification['type'].upper()
address = notification['address'] address = notification['address']
period = notification['period']
self._validate_name_not_conflicting(tenant_id, name) self._validate_name_not_conflicting(tenant_id, name)
@@ -82,12 +84,14 @@ class Notifications(notifications_api_v2.NotificationsV2API):
tenant_id, tenant_id,
name, name,
notification_type, notification_type,
address) address,
period)
return self._create_notification_response(notification_id, return self._create_notification_response(notification_id,
name, name,
notification_type, notification_type,
address, address,
period,
uri) uri)
@resource.resource_try_catch_block @resource.resource_try_catch_block
@@ -96,27 +100,31 @@ class Notifications(notifications_api_v2.NotificationsV2API):
name = notification['name'] name = notification['name']
notification_type = notification['type'].upper() notification_type = notification['type'].upper()
address = notification['address'] address = notification['address']
period = notification['period']
self._validate_name_not_conflicting(tenant_id, name, expected_id=notification_id) self._validate_name_not_conflicting(tenant_id, name, expected_id=notification_id)
self._notifications_repo.update_notification(notification_id, tenant_id, name, self._notifications_repo.update_notification(notification_id, tenant_id, name,
notification_type, notification_type,
address) address,
period)
return self._create_notification_response(notification_id, return self._create_notification_response(notification_id,
name, name,
notification_type, notification_type,
address, address,
period,
uri) uri)
def _create_notification_response(self, id, name, type, def _create_notification_response(self, id, name, type,
address, uri): address, period, uri):
response = { response = {
'id': id, 'id': id,
'name': name, 'name': name,
'type': type, 'type': type,
'address': address 'address': address,
'period': period
} }
return helpers.add_links_to_resource(response, uri) return helpers.add_links_to_resource(response, uri)
@@ -147,7 +155,8 @@ class Notifications(notifications_api_v2.NotificationsV2API):
u'id': notification_row['id'], u'id': notification_row['id'],
u'name': notification_row['name'], u'name': notification_row['name'],
u'type': notification_row['type'], u'type': notification_row['type'],
u'address': notification_row['address'] u'address': notification_row['address'],
u'period': notification_row['period']
} }
helpers.add_links_to_resource(result, uri) helpers.add_links_to_resource(result, uri)
@@ -164,7 +173,7 @@ class Notifications(notifications_api_v2.NotificationsV2API):
helpers.validate_json_content_type(req) helpers.validate_json_content_type(req)
helpers.validate_authorization(req, self._default_authorized_roles) helpers.validate_authorization(req, self._default_authorized_roles)
notification = helpers.read_http_resource(req) notification = helpers.read_http_resource(req)
self._validate_notification(notification) self._parse_and_validate_notification(notification)
tenant_id = helpers.get_tenant_id(req) tenant_id = helpers.get_tenant_id(req)
result = self._create_notification(tenant_id, notification, req.uri) result = self._create_notification(tenant_id, notification, req.uri)
res.body = helpers.dumpit_utf8(result) res.body = helpers.dumpit_utf8(result)
@@ -210,7 +219,7 @@ class Notifications(notifications_api_v2.NotificationsV2API):
helpers.validate_json_content_type(req) helpers.validate_json_content_type(req)
helpers.validate_authorization(req, self._default_authorized_roles) helpers.validate_authorization(req, self._default_authorized_roles)
notification = helpers.read_http_resource(req) notification = helpers.read_http_resource(req)
self._validate_notification(notification) self._parse_and_validate_notification(notification, require_all=True)
tenant_id = helpers.get_tenant_id(req) tenant_id = helpers.get_tenant_id(req)
result = self._update_notification(notification_method_id, tenant_id, result = self._update_notification(notification_method_id, tenant_id,
notification, req.uri) notification, req.uri)

View File

@@ -75,7 +75,8 @@ class MonascaClient(rest_client.RestClient):
def create_notification_method(self, def create_notification_method(self,
name=None, name=None,
type=None, type=None,
address=None): address=None,
period=None):
uri = 'notification-methods' uri = 'notification-methods'
request_body = {} request_body = {}
if name is not None: if name is not None:
@@ -84,6 +85,8 @@ class MonascaClient(rest_client.RestClient):
request_body['type'] = type request_body['type'] = type
if address is not None: if address is not None:
request_body['address'] = address request_body['address'] = address
if period is not None:
request_body['period'] = period
resp, response_body = self.post(uri, json.dumps(request_body)) resp, response_body = self.post(uri, json.dumps(request_body))
return resp, json.loads(response_body) return resp, json.loads(response_body)
@@ -108,7 +111,8 @@ class MonascaClient(rest_client.RestClient):
id, id,
name=None, name=None,
type=None, type=None,
address=None): address=None,
period=None):
uri = 'notification-methods/' + id uri = 'notification-methods/' + id
request_body = {} request_body = {}
if name is not None: if name is not None:
@@ -117,6 +121,8 @@ class MonascaClient(rest_client.RestClient):
request_body['type'] = type request_body['type'] = type
if address is not None: if address is not None:
request_body['address'] = address request_body['address'] = address
if period is not None:
request_body['period'] = period
resp, response_body = self.put(uri, json.dumps(request_body)) resp, response_body = self.put(uri, json.dumps(request_body))
return resp, json.loads(response_body) return resp, json.loads(response_body)

View File

@@ -52,7 +52,8 @@ def create_metric(name='name-1',
def create_notification(name=data_utils.rand_name('notification-'), def create_notification(name=data_utils.rand_name('notification-'),
type='EMAIL', type='EMAIL',
address='john.doe@domain.com'): address='john.doe@domain.com',
period=0):
notification = {} notification = {}
if name is not None: if name is not None:
notification['name'] = name notification['name'] = name
@@ -60,6 +61,8 @@ def create_notification(name=data_utils.rand_name('notification-'),
notification['type'] = type notification['type'] = type
if address is not None: if address is not None:
notification['address'] = address notification['address'] = address
if period is not None:
notification['period'] = period
return notification return notification

View File

@@ -48,11 +48,39 @@ class TestNotificationMethods(base.BaseMonascaTest):
delete_notification_method(id) delete_notification_method(id)
self.assertEqual(204, resp.status) self.assertEqual(204, resp.status)
@test.attr(type="gate")
def test_create_notification_method_period_not_defined(self):
notification = helpers.create_notification(period=None)
resp, response_body = self.monasca_client.create_notifications(
notification)
self.assertEqual(201, resp.status)
id = response_body['id']
resp, response_body = self.monasca_client.\
delete_notification_method(id)
self.assertEqual(204, resp.status)
@test.attr(type="gate")
def test_create_webhook_notification_method_with_non_zero_period(self):
name = data_utils.rand_name('notification-')
notification = helpers.create_notification(name=name,
type='WEBHOOK',
address='http://localhost/test01',
period=60)
resp, response_body = self.monasca_client.create_notifications(
notification)
self.assertEqual(201, resp.status)
id = response_body['id']
resp, response_body = self.monasca_client.\
delete_notification_method(id)
self.assertEqual(204, resp.status)
@test.attr(type="gate") @test.attr(type="gate")
@test.attr(type=['negative']) @test.attr(type=['negative'])
def test_create_notification_method_with_no_name(self): def test_create_notification_method_with_no_name(self):
notification = helpers.create_notification(name=None) notification = helpers.create_notification(name=None)
self.assertRaises((exceptions.BadRequest,exceptions.UnprocessableEntity), self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity),
self.monasca_client.create_notifications, self.monasca_client.create_notifications,
notification) notification)
@@ -60,7 +88,7 @@ class TestNotificationMethods(base.BaseMonascaTest):
@test.attr(type=['negative']) @test.attr(type=['negative'])
def test_create_notification_method_with_no_type(self): def test_create_notification_method_with_no_type(self):
notification = helpers.create_notification(type=None) notification = helpers.create_notification(type=None)
self.assertRaises((exceptions.BadRequest,exceptions.UnprocessableEntity), self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity),
self.monasca_client.create_notifications, self.monasca_client.create_notifications,
notification) notification)
@@ -68,7 +96,7 @@ class TestNotificationMethods(base.BaseMonascaTest):
@test.attr(type=['negative']) @test.attr(type=['negative'])
def test_create_notification_method_with_no_address(self): def test_create_notification_method_with_no_address(self):
notification = helpers.create_notification(address=None) notification = helpers.create_notification(address=None)
self.assertRaises((exceptions.BadRequest,exceptions.UnprocessableEntity), self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity),
self.monasca_client.create_notifications, self.monasca_client.create_notifications,
notification) notification)
@@ -99,6 +127,50 @@ class TestNotificationMethods(base.BaseMonascaTest):
self.monasca_client.create_notifications, self.monasca_client.create_notifications,
notification) notification)
@test.attr(type="gate")
@test.attr(type=['negative'])
def test_create_notification_method_with_invalid_float_period(self):
notification = helpers.create_notification(period=1.2)
self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity),
self.monasca_client.create_notifications,
notification)
@test.attr(type="gate")
@test.attr(type=['negative'])
def test_create_notification_method_with_invalid_string_period(self):
notification = helpers.create_notification(period='random')
self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity),
self.monasca_client.create_notifications,
notification)
@test.attr(type="gate")
@test.attr(type=['negative'])
def test_create_email_notification_method_with_invalid_non_zero_period(self):
notification = helpers.create_notification(period=60)
self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity),
self.monasca_client.create_notifications,
notification)
@test.attr(type="gate")
@test.attr(type=['negative'])
def test_create_pagerduty_notification_method_with_invalid_non_zero_period(self):
notification = helpers.create_notification(type='PAGERDUTY',
address='test03@localhost',
period=60)
self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity),
self.monasca_client.create_notifications,
notification)
@test.attr(type="gate")
@test.attr(type=['negative'])
def test_create_webhook_notification_method_with_invalid_period(self):
notification = helpers.create_notification(type='WEBHOOK',
address='http://localhost/test01',
period=10)
self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity),
self.monasca_client.create_notifications,
notification)
@test.attr(type="gate") @test.attr(type="gate")
def test_list_notification_methods(self): def test_list_notification_methods(self):
notification = helpers.create_notification() notification = helpers.create_notification()
@@ -112,7 +184,7 @@ class TestNotificationMethods(base.BaseMonascaTest):
self.assertTrue(set(['links', 'elements']) == set(response_body)) self.assertTrue(set(['links', 'elements']) == set(response_body))
elements = response_body['elements'] elements = response_body['elements']
element = elements[0] element = elements[0]
self.assertTrue(set(['id', 'links', 'name', 'type', 'address']) == self.assertTrue(set(['id', 'links', 'name', 'type', 'address', 'period']) ==
set(element)) set(element))
self.assertTrue(type(element['id']) is unicode) self.assertTrue(type(element['id']) is unicode)
self.assertTrue(type(element['links']) is list) self.assertTrue(type(element['links']) is list)
@@ -359,7 +431,8 @@ class TestNotificationMethods(base.BaseMonascaTest):
resp, response_body = self.monasca_client.\ resp, response_body = self.monasca_client.\
update_notification_method(id, new_name, update_notification_method(id, new_name,
type=response_body['type'], type=response_body['type'],
address=response_body['address']) address=response_body['address'],
period=response_body['period'])
self.assertEqual(200, resp.status) self.assertEqual(200, resp.status)
self.assertEqual(new_name, response_body['name']) self.assertEqual(new_name, response_body['name'])
resp, response_body = self.monasca_client.\ resp, response_body = self.monasca_client.\
@@ -380,7 +453,8 @@ class TestNotificationMethods(base.BaseMonascaTest):
self.monasca_client.\ self.monasca_client.\
update_notification_method(id, name=response_body['name'], update_notification_method(id, name=response_body['name'],
type=new_type, type=new_type,
address=response_body['address']) address=response_body['address'],
period=response_body['period'])
self.assertEqual(200, resp.status) self.assertEqual(200, resp.status)
self.assertEqual(new_type, response_body['type']) self.assertEqual(new_type, response_body['type'])
resp, response_body = self.monasca_client.\ resp, response_body = self.monasca_client.\
@@ -401,7 +475,8 @@ class TestNotificationMethods(base.BaseMonascaTest):
update_notification_method(id, update_notification_method(id,
name=response_body['name'], name=response_body['name'],
type=response_body['type'], type=response_body['type'],
address=new_address) address=new_address,
period=0)
self.assertEqual(200, resp.status) self.assertEqual(200, resp.status)
self.assertEqual(new_address, response_body['address']) self.assertEqual(new_address, response_body['address'])
resp, response_body = \ resp, response_body = \
@@ -422,7 +497,7 @@ class TestNotificationMethods(base.BaseMonascaTest):
self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity), self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity),
self.monasca_client.update_notification_method, id, self.monasca_client.update_notification_method, id,
name=new_name_long, type=response_body['type'], name=new_name_long, type=response_body['type'],
address=response_body['address']) address=response_body['address'], period=response_body['period'])
resp, response_body = \ resp, response_body = \
self.monasca_client.delete_notification_method(id) self.monasca_client.delete_notification_method(id)
self.assertEqual(204, resp.status) self.assertEqual(204, resp.status)
@@ -439,7 +514,7 @@ class TestNotificationMethods(base.BaseMonascaTest):
self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity), self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity),
self.monasca_client.update_notification_method, id, self.monasca_client.update_notification_method, id,
name=response_body['name'], type='random', name=response_body['name'], type='random',
address=response_body['address']) address=response_body['address'], period=0)
resp, response_body = \ resp, response_body = \
self.monasca_client.delete_notification_method(id) self.monasca_client.delete_notification_method(id)
self.assertEqual(204, resp.status) self.assertEqual(204, resp.status)
@@ -458,7 +533,7 @@ class TestNotificationMethods(base.BaseMonascaTest):
self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity), self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity),
self.monasca_client.update_notification_method, id, self.monasca_client.update_notification_method, id,
name=response_body['name'], type=response_body['type'], name=response_body['name'], type=response_body['type'],
address=new_address_long) address=new_address_long, period=response_body['period'])
resp, response_body = \ resp, response_body = \
self.monasca_client.delete_notification_method(id) self.monasca_client.delete_notification_method(id)
self.assertEqual(204, resp.status) self.assertEqual(204, resp.status)
@@ -489,3 +564,97 @@ class TestNotificationMethods(base.BaseMonascaTest):
resp, response_body = self.monasca_client.\ resp, response_body = self.monasca_client.\
delete_notification_method(response_body['id']) delete_notification_method(response_body['id'])
self.assertEqual(204, resp.status) self.assertEqual(204, resp.status)
@test.attr(type="gate")
@test.attr(type=['negative'])
def test_update_email_notification_method_with_nonzero_period(self):
name = data_utils.rand_name('notification-')
notification = helpers.create_notification(name=name)
resp, response_body = self.monasca_client.create_notifications(
notification)
id = response_body['id']
self.assertEqual(201, resp.status)
self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity),
self.monasca_client.update_notification_method, id,
name=response_body['name'], type=response_body['type'],
address=response_body['address'], period=60)
resp, response_body = \
self.monasca_client.delete_notification_method(id)
self.assertEqual(204, resp.status)
@test.attr(type="gate")
@test.attr(type=['negative'])
def test_update_webhook_notification_method_to_email_with_nonzero_period(self):
name = data_utils.rand_name('notification-')
notification = helpers.create_notification(name=name,
type='WEBHOOK',
address='http://localhost/test01',
period=60)
resp, response_body = self.monasca_client.create_notifications(
notification)
id = response_body['id']
self.assertEqual(201, resp.status)
self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity),
self.monasca_client.update_notification_method, id,
name=response_body['name'], type='EMAIL',
address='test@localhost', period=response_body['period'])
resp, response_body = \
self.monasca_client.delete_notification_method(id)
self.assertEqual(204, resp.status)
@test.attr(type="gate")
@test.attr(type=['negative'])
def test_update_webhook_notification_method_to_pagerduty_with_nonzero_period(self):
name = data_utils.rand_name('notification-')
notification = helpers.create_notification(name=name,
type='WEBHOOK',
address='http://localhost/test01',
period=60)
resp, response_body = self.monasca_client.create_notifications(
notification)
id = response_body['id']
self.assertEqual(201, resp.status)
self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity),
self.monasca_client.update_notification_method, id,
name=response_body['name'], type='PAGERDUTY',
address='test@localhost', period=response_body['period'])
resp, response_body = \
self.monasca_client.delete_notification_method(id)
self.assertEqual(204, resp.status)
@test.attr(type="gate")
@test.attr(type=['negative'])
def test_update_notification_method_with_non_int_period(self):
name = data_utils.rand_name('notification-')
notification = helpers.create_notification(name=name)
resp, response_body = self.monasca_client.create_notifications(
notification)
id = response_body['id']
self.assertEqual(201, resp.status)
self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity),
self.monasca_client.update_notification_method, id,
name=response_body['name'], type=response_body['type'],
address=response_body['name'], period='zero')
resp, response_body = \
self.monasca_client.delete_notification_method(id)
self.assertEqual(204, resp.status)
@test.attr(type="gate")
@test.attr(type=['negative'])
def test_update_webhook_notification_method_with_invalid_period(self):
name = data_utils.rand_name('notification-')
notification = helpers.create_notification(name=name,
type='WEBHOOK',
address='http://localhost/test01',
period=60)
resp, response_body = self.monasca_client.create_notifications(
notification)
id = response_body['id']
self.assertEqual(201, resp.status)
self.assertRaises((exceptions.BadRequest, exceptions.UnprocessableEntity),
self.monasca_client.update_notification_method, id,
name=response_body['name'], type=response_body['type'],
address=response_body['address'], period=5)
resp, response_body = \
self.monasca_client.delete_notification_method(id)
self.assertEqual(204, resp.status)