s3_website_monadic 0.0.14 → 0.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 68d01d8499eba5c41c9b42d0d6ead9ea5386590a
|
4
|
+
data.tar.gz: 5a6381dfa127b1f824c1ded97efe0cb390b179ec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1e35433d2fb1ad9ce6f737dcfaba2e0b49ca02ab57ae1092e7370ede5e5b50292e19b50236dff44cf5d8ceb76460ccb25a5c1fd15b78e886954616f037ebdafc
|
7
|
+
data.tar.gz: 9bcc6e4226a57017089ddd4e65918a53eee9f3fd3bf3b2c7a2d93542de249fdb4e0c51b762875d2615168721cbcbb847aac31126d23605afe8e46ee7bedca72d
|
data/s3_website.gemspec
CHANGED
@@ -61,7 +61,7 @@ object CloudFront {
|
|
61
61
|
type CloudFrontClientProvider = (Config) => AmazonCloudFront
|
62
62
|
|
63
63
|
case class SuccessfulInvalidation(invalidatedItemsCount: Int) extends SuccessReport {
|
64
|
-
def reportMessage = s"Invalidated ${
|
64
|
+
def reportMessage = s"Invalidated ${invalidatedItemsCount ofType "item"} on CloudFront"
|
65
65
|
}
|
66
66
|
|
67
67
|
case class FailedInvalidation(error: Throwable) extends FailureReport {
|
@@ -71,18 +71,36 @@ object CloudFront {
|
|
71
71
|
def awsCloudFrontClient(config: Config) =
|
72
72
|
new AmazonCloudFrontClient(new BasicAWSCredentials(config.s3_id, config.s3_secret))
|
73
73
|
|
74
|
-
def toInvalidationBatches(pushSuccessReports: Seq[PushSuccessReport])(implicit config: Config): Seq[InvalidationBatch] =
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
74
|
+
def toInvalidationBatches(pushSuccessReports: Seq[PushSuccessReport])(implicit config: Config): Seq[InvalidationBatch] = {
|
75
|
+
val invalidationPaths: Seq[String] = {
|
76
|
+
def withDefaultPathIfNeeded(paths: Seq[String]) = {
|
77
|
+
// This is how we support the Default Root Object @ CloudFront (http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/DefaultRootObject.html)
|
78
|
+
// We do this more accurately by fetching the distribution config (http://docs.aws.amazon.com/AmazonCloudFront/latest/APIReference/GetConfig.html)
|
79
|
+
// and reading the Default Root Object from there.
|
80
|
+
val containsPotentialDefaultRootObject = paths
|
81
|
+
.exists(
|
82
|
+
_
|
83
|
+
.replaceFirst("^/", "") // S3 keys do not begin with a slash
|
84
|
+
.contains("/") == false // See if the S3 key is a top-level key (i.e., it is not within a directory)
|
85
|
+
)
|
86
|
+
if (containsPotentialDefaultRootObject) paths :+ "/" else paths
|
87
|
+
}
|
88
|
+
val paths = pushSuccessReports
|
89
|
+
.filter(needsInvalidation) // Assume that redirect objects are never cached.
|
90
|
+
.map(toInvalidationPath)
|
91
|
+
.map (applyInvalidateRootSetting)
|
92
|
+
withDefaultPathIfNeeded(paths)
|
93
|
+
}
|
94
|
+
|
95
|
+
invalidationPaths
|
79
96
|
.grouped(1000) // CloudFront supports max 1000 invalidations in one request (http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Invalidation.html#InvalidationLimits)
|
80
97
|
.map { batchKeys =>
|
81
98
|
new InvalidationBatch() withPaths
|
82
99
|
(new Paths() withItems batchKeys withQuantity batchKeys.size) withCallerReference
|
83
|
-
|
100
|
+
s"s3_website gem ${System.currentTimeMillis()}"
|
84
101
|
}
|
85
102
|
.toSeq
|
103
|
+
}
|
86
104
|
|
87
105
|
def applyInvalidateRootSetting(path: String)(implicit config: Config) =
|
88
106
|
if (config.cloudfront_invalidate_root.exists(_ == true))
|
@@ -156,11 +156,11 @@ object Push {
|
|
156
156
|
"There was nothing to push."
|
157
157
|
case PushCounts(updates, newFiles, failures, redirects, deletes) =>
|
158
158
|
val reportClauses: scala.collection.mutable.ArrayBuffer[String] = ArrayBuffer()
|
159
|
-
if (updates > 0) reportClauses += s"Updated ${
|
160
|
-
if (newFiles > 0) reportClauses += s"Created ${
|
161
|
-
if (failures > 0) reportClauses += s"${
|
162
|
-
if (redirects > 0) reportClauses += s"Applied ${
|
163
|
-
if (deletes > 0) reportClauses += s"Deleted ${
|
159
|
+
if (updates > 0) reportClauses += s"Updated ${updates ofType "file"}."
|
160
|
+
if (newFiles > 0) reportClauses += s"Created ${newFiles ofType "file"}."
|
161
|
+
if (failures > 0) reportClauses += s"${failures ofType "operation"} failed." // This includes both failed uploads and deletes.
|
162
|
+
if (redirects > 0) reportClauses += s"Applied ${redirects ofType "redirect"}."
|
163
|
+
if (deletes > 0) reportClauses += s"Deleted ${deletes ofType "file"}."
|
164
164
|
reportClauses.mkString(" ")
|
165
165
|
}
|
166
166
|
|
@@ -51,8 +51,12 @@ package object website {
|
|
51
51
|
httpStatusCode.exists(c => c >= 400 && c < 500)
|
52
52
|
}
|
53
53
|
|
54
|
-
|
55
|
-
def
|
56
|
-
|
54
|
+
implicit class NumReport(val num: Int) extends AnyVal {
|
55
|
+
def ofType(itemType: String) = countToString(num, itemType)
|
56
|
+
|
57
|
+
private def countToString(count: Int, singular: String) = {
|
58
|
+
def plural = s"${singular}s"
|
59
|
+
s"$count ${if (count > 1) plural else singular}"
|
60
|
+
}
|
57
61
|
}
|
58
62
|
}
|
@@ -136,11 +136,11 @@ class S3WebsiteSpec extends Specification {
|
|
136
136
|
"invalidate the updated CloudFront items" in new SiteDirectory with MockAWS {
|
137
137
|
implicit val site = siteWithFiles(
|
138
138
|
config = defaultConfig.copy(cloudfront_distribution_id = Some("EGM1J2JJX9Z")),
|
139
|
-
localFiles = "test.css" :: "articles/index.html" :: Nil
|
139
|
+
localFiles = "css/test.css" :: "articles/index.html" :: Nil
|
140
140
|
)
|
141
|
-
setOutdatedS3Keys("test.css", "articles/index.html")
|
141
|
+
setOutdatedS3Keys("css/test.css", "articles/index.html")
|
142
142
|
Push.pushSite
|
143
|
-
sentInvalidationRequest.getInvalidationBatch.getPaths.getItems.toSeq.sorted must equalTo(("/test.css" :: "/articles/index.html" :: Nil).sorted)
|
143
|
+
sentInvalidationRequest.getInvalidationBatch.getPaths.getItems.toSeq.sorted must equalTo(("/css/test.css" :: "/articles/index.html" :: Nil).sorted)
|
144
144
|
}
|
145
145
|
|
146
146
|
"not send CloudFront invalidation requests on new objects" in new SiteDirectory with MockAWS {
|
@@ -191,23 +191,37 @@ class S3WebsiteSpec extends Specification {
|
|
191
191
|
Push.pushSite
|
192
192
|
sentInvalidationRequest.getInvalidationBatch.getPaths.getItems.toSeq.sorted must equalTo(("/articles/arnold's%20file.html" :: Nil).sorted)
|
193
193
|
}
|
194
|
+
|
195
|
+
/*
|
196
|
+
* Because CloudFront supports Default Root Objects (http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/DefaultRootObject.html),
|
197
|
+
* we have to guess
|
198
|
+
*/
|
199
|
+
"invalidate the root object '/' if a top-level object is updated or deleted" in new SiteDirectory with MockAWS {
|
200
|
+
implicit val site = siteWithFiles(
|
201
|
+
config = defaultConfig.copy(cloudfront_distribution_id = Some("EGM1J2JJX9Z")),
|
202
|
+
localFiles = "maybe-index.html" :: Nil
|
203
|
+
)
|
204
|
+
setOutdatedS3Keys("maybe-index.html")
|
205
|
+
Push.pushSite
|
206
|
+
sentInvalidationRequest.getInvalidationBatch.getPaths.getItems.toSeq.sorted must equalTo(("/" :: "/maybe-index.html" :: Nil).sorted)
|
207
|
+
}
|
194
208
|
}
|
195
209
|
|
196
210
|
"cloudfront_invalidate_root: true" should {
|
197
211
|
"convert CloudFront invalidation paths with the '/index.html' suffix into '/'" in new SiteDirectory with MockAWS {
|
198
212
|
implicit val site = siteWithFiles(
|
199
213
|
config = defaultConfig.copy(cloudfront_distribution_id = Some("EGM1J2JJX9Z"), cloudfront_invalidate_root = Some(true)),
|
200
|
-
localFiles = "
|
214
|
+
localFiles = "articles/index.html" :: Nil
|
201
215
|
)
|
202
|
-
setOutdatedS3Keys("
|
216
|
+
setOutdatedS3Keys("articles/index.html")
|
203
217
|
Push.pushSite
|
204
|
-
sentInvalidationRequest.getInvalidationBatch.getPaths.getItems.toSeq.sorted must equalTo(("/
|
218
|
+
sentInvalidationRequest.getInvalidationBatch.getPaths.getItems.toSeq.sorted must equalTo(("/articles/" :: Nil).sorted)
|
205
219
|
}
|
206
220
|
}
|
207
221
|
|
208
222
|
"a site with over 1000 items" should {
|
209
223
|
"split the CloudFront invalidation requests into batches of 1000 items" in new SiteDirectory with MockAWS {
|
210
|
-
val files = (1 to 1002).map { i => s"file-$i"}
|
224
|
+
val files = (1 to 1002).map { i => s"lots-of-files/file-$i"}
|
211
225
|
implicit val site = siteWithFiles(
|
212
226
|
config = defaultConfig.copy(cloudfront_distribution_id = Some("EGM1J2JJX9Z")),
|
213
227
|
localFiles = files
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: s3_website_monadic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lauri Lehmijoki
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-05-
|
11
|
+
date: 2014-05-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk
|