-
Notifications
You must be signed in to change notification settings - Fork 3
Conversation
06593b1
to
f1a823d
Compare
@@ -0,0 +1,55 @@ | |||
provider "aws" {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't required because it is supplied as part of common variables
I think currently the way the Rakefile deploys stuff is to copy everything from resource directories with the *.tf filename extension into a temporary directory and then deploy, so this may miss out the zip/py files, so we'll need to tweak that. I think it's also worth discussing whether we want "extra" files within the resource/ dir. Currently if an environment isn't defined within the resources/ dir then it'll assume that you want it deployed to all environments. |
The file paths that use |
This depends on #47 being merged. |
@@ -0,0 +1,32 @@ | |||
{ | |||
"Version": "2012-10-17", | |||
"Id": "Policy1460992104238", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could give this a proper ID I think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in ca7c3c1. Seems that using a uuid
is the way to go although I haven't used an ID
at all in the other policies. I'm not sure if there's any benefit to using them. As it happens this policy confuses terraform apply
into thinking it has changed every time it is run which I hoped the change you suggested might fix but didn't unfortunately. I think it's line 27 not being specific enough but haven't been able to work out a more 'fully qualified' version that works.
In terms of the lambda build I've been looking at something like this rather than building the zip manually.
Would you be willing to give this a go on this PR? |
We're going to add some code that works with the additional files, but the structure needs to be rejigged:
The README can stay in the project root. If you remove the references to the |
f1a823d
to
fb5a63b
Compare
471f392
to
c0d54f2
Compare
role = "${aws_iam_role.lambda_execute_and_write_to_email_alert_bucket.arn}" | ||
handler = "rename_email_files_with_request_id.lambda_handler" | ||
runtime = "python2.7" | ||
source_code_hash = "${base64sha256(file("files/rename_email_files_with_request_id.py"))}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI: source_code_hash
expects a hash of the ZIP file, so you'll keep getting unnecessary diffs in plan
with the current approach as the hash will never match with what the API returns.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your comment. I was using the zip file path originally but in an effort to try and avoid having zipped files in the repo I've moved its creation into a null_resource
. As a result the base64sha256
function raises a no such file
error if I use the zip file. Is there a better way that I can trigger this resource to be updated when the .py source changes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a better way that I can trigger this resource to be updated when the .py source changes?
Before Terraform gets to plan/apply
stage, it (by default) performs refresh
(effectively Read
from CRUD for each resource in all *.tf
files) so it can figure out what may have changed and how does it affect plan/apply
. After refresh is done for all resources, it performs plan/apply
.
As a result the base64sha256 function raises a no such file error if I use the zip file.
The base64sha256()
function is executed at the time of refresh
since it has static value (static path to zip file) hence Terraform won't mark it as "computed". All provisioners are always executed at the time of apply
, not during refresh
. That's why you're hitting this.
To mark it as "computed" you would probably need to have a 1st class support for "zipping" in terraform which would be returning the shasum that you would reference in aws_lambda_function. source_code_hash
. There are some (good) reasons why Terraform doesn't support this (yet):
hashicorp/terraform#3858
The only way to get around this would be possibly executing terraform twice (+ removing any unnecessary triggers
& depends_on
):
terraform apply -target=null_resource.build_rename_email_files_with_request_id
terraform plan/apply
that way terraform won't perform any validation/checks on any resources except the targeted one.
Obviously the null_resource
's provisioner would be executed twice (in the second run too), but Terraform would at least get a chance to prepare the right plan
and apply
it correctly.
Also keep in mind that any local-exec
provisioner makes your Terraform files platform-specific - i.e. the requirement suddenly isn't just terraform binary, but also platform-specific zip
utility having the same interface (e.g. supporting -j
flag). This is also why I think that building ZIP files via CI is a better solution.
@surminus I've reorganised the files as you suggested. I think it will need a slight change to #47 as per my comments there @deanwilson I've used that |
I'm not entirely sure how you do deal with other artefacts, like ruby gems in GDS, but my friendly recommendation would be to treat the ZIP files for Lambda functions the same way as other artefacts - i.e. have their own repo with CI (Jenkins/Travis/Circle) that is running tests (if you have any) and most importantly generating ZIP file and uploading it into a versioned S3 bucket. That build in your CI can spit out an S3 Then you can just bump the There is also a separate thread about proper versioning of Lambda Functions, which isn't well supported in Terraform yet. |
* An S3 event configured to execute the lambda (`rename_email_files_with_request_id`) | ||
on the `ObjectCreated` `Put` event for the bucket | ||
|
||
Terraform v0.6.14 doesn't support S3 event sources but support is in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
0.6.15
was released just a few hours ago 😉
https://www.terraform.io/downloads.html
Thanks for all your comments @radeksimko . Really helpful. |
There is an ongoing effort to release Terraform 0.7 soon which will contain something that might help you to make the workflow cleaner/more automated - Data Sources. Effectively you'd be able to do something like this: data "aws_s3_object" "lambda_zip_file" {
bucket = "my-lambda-functions"
path = "lambda.zip"
}
...
resource "aws_lambda_function" "rename_email_files_with_request_id" {
s3_object_version = "${data.aws_s3_object.lambda_zip_file.latest_version}" That way you wouldn't need that extra step of bumping Version ID manually, but you'd just let Terraform to pull down the latest from S3 at the time of The syntax and actual implementation is WIP though - this is just to give you an idea. |
c0d54f2
to
6e33128
Compare
56d65e1
to
85f3756
Compare
I've updated the directory structure and reverted the |
@gpeng as suggested in #47 (comment) I think what I stated above was incorrect. |
Thanks... I've laid it out as per #47 so I think it should be good to go now. Just need to update to pull the lambda zip from s3 once that is setup. |
We have the config in for buckets to store the lambda zips from (#50) although not sure if they're deployed yet (easy to do). I guess the next thing to do is https://trello.com/c/eukUJfOU/84-write-jenkins-deployment-job-for-lambda-apps |
@gpeng, we've just had a chat about this. To deploy this the process would be:
We are prioritising steps 2 & 3 along with setting up the email endpoints. |
Ok... Sounds good. So would we have a convention for where zipped lambdas live within a typical app and Jenkins would upload any that it finds in the 'standard' location |
That sounds like a good plan. |
Would that mean that we'd have to have a separate update/install lambda Terraform job? |
I think this is fine as it is for the time-being and don't think we should have a separate job. This is dependent on #47 which I think @deanwilson has thoughts on, though I am happy with it in this way and don't really mind either way. I think this terraform project looks fine to run on each deployment (though if you want to do the work to split it up feel free). For this part, will the source change as the |
Yes... the lambda source needs to change there. I think we'll have to keep the lambda source within this repo too now as I think about it as we need to be able to get the hash of it here unless we upload the source and the zip as part of the Jenkins job that pulls the lambdas in. That might be a better idea. I think we also need to add support for the 3 environments too don't we for both the lambda source and the bucket where the emails land? Might need some pointers on that... |
This configures PUT events to the s3 bucket to invoke the lambda. NB this is only supported in terraform v0.6.15
This commit moves the lambda source code out of this repo and now pulls it from S3 (`govuk-lambda-applications-<environment>`) The lambda zip file version needs to be passed in as an environment variable `TF_VAR_rename_email_files_with_request_id_version`
85f3756
to
2d35845
Compare
@surminus I've updated this to get the lambda from S3 now as discussed. We need to pass in the S3 object version as per the last commit message. I think this should be pretty much good to go now. Just need to work out which repo to put the lambda source in. |
I'm going to write the deployment job today. The last thing to decide as you suggest is where the source goes, I'd suggest either a new repo (govuk-lambda-app-deployment?) or the govuk-app-deployment repo? We could put it in this repo but ideally I think this should be separate from Terraform code. Either way it should be easy enough to update the deployment job. |
default = "govuk-email-alert-notifications" | ||
} | ||
|
||
variable "environment"{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't required because it's set by default.
@@ -1,6 +1,7 @@ | |||
require 'fileutils' | |||
require 'rspec/core/rake_task' | |||
require 'tmpdir' | |||
require 'aws-sdk-resources' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this need to go in the Gemfile
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The dependency is pulled in by awspec
so I don't think it also needs to be included in the Gemfile.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep sorry, you're right!
There was a requirement to be able to pull in the latest VersionID of a specific object in a bucket, with a prerequisite that it was triggered by a Jenkins deployment job. This changes seeks to add that functionality by allowing the addition of an environmental variable in the deploy job named "TF_VAR_LAMBDA_FILENAME". I updated this in the project it's used so it could be used more generically in the future. There might be a bit of extra work if we wish to override the VersionID for whatever reason.
Terraform only works with stuff when it is quoted from the relative directory. Our rake task pushes everything into a temporary directory and then feeds that in during the plan/apply system call. In the Terraform code we specified a relative path, so to fix this I have created a new templates directory with the project name underneath it. Another solution would be to pass in the "tmpdir" variable in the Rake task as env var, but I thought this was not as tidy as just having a separate directory especially for templates.
a143e95
to
48ad577
Compare
I'm not sure I understand the template change in 48ad577. I think it's duplicating the templates but I'm not sure why we can't use a relative path of |
@alexmuller you're right, we could just have a full relative path in the Terraform code. I thought it was easier to read in it's own directory, but I don't really mind either way! |
And update paths. This keeps everything together in the same directory.
Maybe something like 1cfb375, is that ok? I think that's what @deanwilson had in mind with the directory structure but I might be wrong. |
Fine with me! |
I know hardly anything about how this SES/Lambda interaction works but the code seems like it probably makes sense. Let's run it in integration and see what happens. |
@alexmuller 👋 I know these things. Shout if I can help. |
There's a bit of a loop here where this Terraform code creates an S3 bucket but the Rakefile relies on that bucket existing. |
@boffbowsh: Thanks! |
I didn't think the Rakefile should rely on the bucket existing that the Terraform code creates? It relies upon a different bucket where we upload the Lambda app, then creates a new bucket for a different function (I think). |
@surminus: Ah yep sorry, you're right. I have no idea how any of this works. |
This work is part of the ongoing efforts to improve travel advice alert email monitoring and will allow us to reconcile a 'received' email with a published edition in Travel Advice Publisher (where we'll add checks that can be run by Jenkins -> Icinga)
This project sets up an S3 bucket and a lambda function that parses files and renames them with a prefix (currently only
travel-advice-alerts
) and thegovuk_request_id
parsed from the email body.An SES domain and RuleSet and an S3 event source are also required but can't currently be configured via Terraform. (details in the README)
I've not been able to test this via the
rake
tasks from the repo root as I've not got access to the state files, environments etc so I'm not sure that the paths work from there.The lambda code is deployed from a zip file which I've checked in and included in this PR. I'm not sure this is the best approach as it's 'unreviewable'. I'd welcome any better ideas. Zipping the file as part of the rake task to apply maybe?
Apologies for the one big commit. Code was moved from a local repo. Happy to break up if it will help with reviews.
UPDATE: Added an
aws_s3_bucket_notification
to trigger the lambda. This is only supported in Terraform 0.6.15