Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Evaluate when running 'nixops send-keys' to make sure keys are updated.
Move evaluation for send_keys to Deployment class. Revert "Move evaluation for send_keys to Deployment class." This reverts commit f727d25. Evaluate when running 'nixops send-keys' to make sure keys are updated. Move evaluation for send_keys to Deployment class. Revert "Move evaluation for send_keys to Deployment class." This reverts commit f727d25. Revert "Evaluate when running 'nixops send-keys' to make sure keys are updated." This reverts commit 7e14c4d. adding AWS SNS resource better naming storing the subscribers fixing descriptions adding AWS sns to the manual make sure to subscribe only if the subscriber doesn't exist already exposing the arn, as it can be used in other deployment configs i.e an sns publish timer Add support for provisioning Elastic File Systems nixops info: Show IP address of EFS mount targets Evaluate when running 'nixops send-keys' to make sure keys are updated. Move evaluation for send_keys to Deployment class. Revert "Move evaluation for send_keys to Deployment class." This reverts commit f727d25. Revert "Evaluate when running 'nixops send-keys' to make sure keys are updated." This reverts commit 7e14c4d. oops, screwed up during rebase Typo adding the ability to delete a subscription add example of SNS topic oops remove copy paste doh storing the sns topics subscriptions as json in the statefile
- Loading branch information
1 parent
e8c315a
commit 88bb0e3
Showing
6 changed files
with
276 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
{ account | ||
, region ? "us-east-1" | ||
, description ? "SNS topic example" | ||
, ... | ||
}: | ||
{ | ||
network.description = description; | ||
|
||
resources.snsTopics.example-topic = { | ||
name="sns-topic"; | ||
displayName="Nixops SNS topic"; | ||
accessKeyId = account; | ||
subscriptions = [ | ||
{ | ||
protocol = "email"; | ||
endpoint = "amine@chikhaoui.tn"; | ||
} | ||
]; | ||
inherit region; }; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
{ config, lib, uuid, name, ... }: | ||
|
||
with lib; | ||
|
||
{ | ||
|
||
options = { | ||
|
||
name = mkOption { | ||
default = "charon-${uuid}-${name}"; | ||
type = types.str; | ||
description = "Name of the SNS topic."; | ||
}; | ||
|
||
region = mkOption { | ||
type = types.str; | ||
description = "AWS region."; | ||
}; | ||
|
||
accessKeyId = mkOption { | ||
type = types.str; | ||
description = "The AWS Access Key ID."; | ||
}; | ||
|
||
displayName = mkOption { | ||
default = null; | ||
type = types.nullOr (types.str); | ||
description = "Display name of the topic"; | ||
}; | ||
|
||
policy = mkOption { | ||
default = ""; | ||
type = types.str; | ||
description = "Policy to apply to the SNS topic."; | ||
}; | ||
|
||
subscriptions = mkOption { | ||
type = types.listOf types.optionSet; | ||
description = "List of subscriptions to apply to the topic."; | ||
default = []; | ||
options = { | ||
protocol = mkOption { | ||
default = null; | ||
description = "The protocol to use."; | ||
type = types.str; | ||
}; | ||
endpoint = mkOption { | ||
default = null; | ||
description = "The endpoint to send data to."; | ||
type = types.str; | ||
}; | ||
}; | ||
}; | ||
|
||
arn = mkOption { | ||
default = ""; | ||
type = types.str; | ||
description = "Amazon Resource Name (ARN) of the SNS topic. This is set by NixOps."; | ||
}; | ||
|
||
}; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
# Automatic provisioning of AWS SNS topics. | ||
|
||
import boto | ||
import boto.sns | ||
import nixops.util | ||
import nixops.resources | ||
import nixops.ec2_utils | ||
from xml.etree import ElementTree | ||
|
||
class SNSTopicDefinition(nixops.resources.ResourceDefinition): | ||
"""Definition of an SNS topic.""" | ||
|
||
@classmethod | ||
def get_type(cls): | ||
return "sns-topic" | ||
|
||
@classmethod | ||
def get_resource_type(cls): | ||
return "snsTopics" | ||
|
||
def __init__(self, xml): | ||
nixops.resources.ResourceDefinition.__init__(self, xml) | ||
self.topic_name = xml.find("attrs/attr[@name='name']/string").get("value") | ||
self.access_key_id = xml.find("attrs/attr[@name='accessKeyId']/string").get("value") | ||
self.region = xml.find("attrs/attr[@name='region']/string").get("value") | ||
dn = xml.find("attrs/attr[@name='displayName']/string") | ||
self.display_name = dn.get("value") if dn != None else None | ||
self.policy = xml.find("attrs/attr[@name='policy']/string").get("value") | ||
self.subscriptions = [] | ||
subscriptions = xml.findall("attrs/attr[@name='subscriptions']/list/attrs") | ||
for subscription in subscriptions: | ||
subscriber = {} | ||
subscriber['protocol'] = subscription.find("attr[@name='protocol']/string").get("value") | ||
subscriber['endpoint'] = subscription.find("attr[@name='endpoint']/string").get("value") | ||
self.subscriptions.append(subscriber) | ||
|
||
def show_type(self): | ||
return "{0}".format(self.get_type()) | ||
|
||
|
||
class SNSTopicState(nixops.resources.ResourceState): | ||
"""State of an SNS topic.""" | ||
|
||
state = nixops.util.attr_property("state", nixops.resources.ResourceState.MISSING, int) | ||
topic_name = nixops.util.attr_property("ec2.topicName", None) | ||
access_key_id = nixops.util.attr_property("ec2.accessKeyId", None) | ||
display_name = nixops.util.attr_property("ec2.topicDisplayName", None) | ||
region = nixops.util.attr_property("ec2.region", None) | ||
policy = nixops.util.attr_property("ec2.topicPolicy", None) | ||
arn = nixops.util.attr_property("ec2.topicARN", None) | ||
subscriptions = nixops.util.attr_property("ec2.topicSubscriptions", [],'json') | ||
|
||
@classmethod | ||
def get_type(cls): | ||
return "sns-topic" | ||
|
||
|
||
def __init__(self, depl, name, id): | ||
nixops.resources.ResourceState.__init__(self, depl, name, id) | ||
self._conn = None | ||
|
||
|
||
def show_type(self): | ||
s = super(SNSTopicState, self).show_type() | ||
if self.region: s = "{0} [{1}]".format(s, self.region) | ||
return s | ||
|
||
|
||
@property | ||
def resource_id(self): | ||
return self.topic_name | ||
|
||
def prefix_definition(self, attr): | ||
return {('resources', 'snsTopics'): attr} | ||
|
||
def get_physical_spec(self): | ||
return {'arn': self.arn} | ||
|
||
def get_definition_prefix(self): | ||
return "resources.snsTopics." | ||
|
||
|
||
def connect(self): | ||
if self._conn: return | ||
assert self.region | ||
(access_key_id, secret_access_key) = nixops.ec2_utils.fetch_aws_secret_key(self.access_key_id) | ||
self._conn = boto.sns.connect_to_region( | ||
region_name=self.region, aws_access_key_id=access_key_id, aws_secret_access_key=secret_access_key) | ||
|
||
|
||
def _destroy(self): | ||
if self.state != self.UP: return | ||
self.connect() | ||
self.log("destroying SNS topic ‘{0}’...".format(self.topic_name)) | ||
self._conn.delete_topic(self.arn) | ||
with self.depl._db: | ||
self.state = self.MISSING | ||
self.topic_name = None | ||
self.region = None | ||
self.policy = None | ||
self.arn = None | ||
|
||
def topic_exists(self,arn): | ||
return True | ||
|
||
|
||
def create(self, defn, check, allow_reboot, allow_recreate): | ||
self.access_key_id = defn.access_key_id or nixops.ec2_utils.get_access_key_id() | ||
if not self.access_key_id: | ||
raise Exception("please set ‘accessKeyId’, $EC2_ACCESS_KEY or $AWS_ACCESS_KEY_ID") | ||
|
||
arn = self.arn | ||
if self.state == self.UP and (self.topic_name != defn.topic_name or self.region != defn.region): | ||
self.log("topic definition changed, recreating...") | ||
self._destroy() | ||
self._conn = None | ||
|
||
self.region = defn.region | ||
self.connect() | ||
|
||
if self.arn == None: | ||
self.log("creating SNS topic ‘{0}’...".format(defn.topic_name)) | ||
topic = self._conn.create_topic(defn.topic_name) | ||
arn = topic.get('CreateTopicResponse').get('CreateTopicResult')['TopicArn'] | ||
|
||
if defn.display_name != None: | ||
self._conn.set_topic_attributes(topic=arn,attr_name="DisplayName",attr_value=defn.display_name) | ||
|
||
if defn.policy != "": | ||
policy = self._conn.set_topic_attributes(topic=arn,attr_name="Policy",attr_value=defn.policy) | ||
|
||
current_subscribers, current_subscriptions_arns = self.get_current_subscribers(arn=arn) | ||
|
||
if len(defn.subscriptions) > 0: | ||
for subscriber in defn.subscriptions: | ||
protocol = subscriber['protocol'] | ||
endpoint = subscriber['endpoint'] | ||
if endpoint not in current_subscribers: | ||
self.log("adding SNS subscriber with endpoint '{0}'...".format(endpoint)) | ||
self._conn.subscribe(topic=arn,protocol=protocol,endpoint=endpoint) | ||
|
||
defn_endpoints = self.get_defn_endpoints(defn) | ||
if len(defn_endpoints) > 0: | ||
for subscriber_endpoint, subscriber_arn in current_subscriptions_arns.items(): | ||
if subscriber_endpoint not in defn_endpoints: | ||
self.log("removing SNS subscriber with endpoint '{0}'...".format(subscriber_endpoint)) | ||
self._conn.unsubscribe(subscription=subscriber_arn) | ||
|
||
with self.depl._db: | ||
self.state = self.UP | ||
self.topic_name = defn.topic_name | ||
self.display_name = defn.display_name | ||
self.policy = defn.policy | ||
self.arn = arn | ||
self.subscriptions = defn.subscriptions | ||
|
||
|
||
def get_current_subscribers(self,arn): | ||
response = self._conn.get_all_subscriptions_by_topic(topic=arn) | ||
current_subscribers = response['ListSubscriptionsByTopicResponse']['ListSubscriptionsByTopicResult']['Subscriptions'] | ||
current_endpoints = [] | ||
current_subscriptions_arns = {} | ||
if len(current_subscribers) > 0: | ||
for subscriber in current_subscribers: | ||
current_endpoints.append(subscriber['Endpoint']) | ||
current_subscriptions_arns[subscriber['Endpoint']]=subscriber['SubscriptionArn'] | ||
return current_endpoints,current_subscriptions_arns | ||
|
||
def get_defn_endpoints(self,defn): | ||
defn_endpoints = [] | ||
if len(defn.subscriptions) > 0: | ||
for subscriber in defn.subscriptions: | ||
defn_endpoints.append(subscriber['endpoint']) | ||
return defn_endpoints | ||
|
||
|
||
def destroy(self, wipe=False): | ||
self._destroy() | ||
return True |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters