Skip to content

Commit a5d3e1b

Browse files
authored
B2 -> GCS fallback, log to datadog (#127)
* configure datadog logging endpoint * log to datadog when packages are served from fallback * configure B2 auth * configure, but do not put into service the S3 Archive backend * serve from b2, fallback to gcs
1 parent 2b101c5 commit a5d3e1b

File tree

5 files changed

+84
-9
lines changed

5 files changed

+84
-9
lines changed

terraform/config.tf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ variable "test_pypi_warehouse_token" {
3838
type = string
3939
sensitive = true
4040
}
41+
variable "datadog_token" {
42+
type = string
43+
sensitive = true
44+
}
4145

4246
terraform {
4347
cloud {

terraform/file-hosting/fastly-service.tf

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,32 @@ resource "fastly_service_vcl" "files" {
7575
error_threshold = 5
7676
}
7777

78+
backend {
79+
name = "B2"
80+
auto_loadbalance = false
81+
shield = "iad-va-us"
82+
83+
request_condition = "Package File"
84+
healthcheck = "B2 Health"
85+
86+
address = "${var.files_bucket}.s3.us-east-005.backblazeb2.com"
87+
port = 443
88+
use_ssl = true
89+
ssl_cert_hostname = "${var.files_bucket}.s3.us-east-005.backblazeb2.com"
90+
ssl_sni_hostname = "${var.files_bucket}.s3.us-east-005.backblazeb2.com"
91+
92+
connect_timeout = 5000
93+
first_byte_timeout = 60000
94+
between_bytes_timeout = 15000
95+
error_threshold = 5
96+
}
97+
7898
backend {
7999
name = "GCS"
80100
auto_loadbalance = false
81101
shield = "bfi-wa-us"
82102

83-
request_condition = "Package File"
103+
request_condition = "NeverReq"
84104
healthcheck = "GCS Health"
85105

86106
address = "${var.files_bucket}.storage.googleapis.com"
@@ -96,11 +116,31 @@ resource "fastly_service_vcl" "files" {
96116
}
97117

98118
backend {
99-
name = "S3"
119+
name = "S3_Archive"
100120
auto_loadbalance = false
121+
shield = "bfi-wa-us"
122+
101123
request_condition = "NeverReq"
124+
healthcheck = "S3 Health"
125+
126+
address = "${var.files_bucket}-archive.s3.amazonaws.com"
127+
port = 443
128+
use_ssl = true
129+
ssl_cert_hostname = "${var.files_bucket}-archive.s3.amazonaws.com"
130+
ssl_sni_hostname = "${var.files_bucket}-archive.s3.amazonaws.com"
131+
132+
connect_timeout = 5000
133+
first_byte_timeout = 60000
134+
between_bytes_timeout = 15000
135+
error_threshold = 5
136+
}
137+
138+
backend {
139+
name = "S3"
140+
auto_loadbalance = false
102141
shield = "bfi-wa-us"
103142

143+
request_condition = "NeverReq"
104144
healthcheck = "S3 Health"
105145

106146
address = "${var.files_bucket}.s3.amazonaws.com"
@@ -201,6 +241,12 @@ resource "fastly_service_vcl" "files" {
201241
response_condition = "Never"
202242
}
203243

244+
logging_datadog {
245+
name = "DataDog Log"
246+
token = var.datadog_token
247+
response_condition = "Package Served From Fallback"
248+
}
249+
204250
logging_s3 {
205251
name = "S3 Error Logs"
206252

@@ -250,6 +296,12 @@ resource "fastly_service_vcl" "files" {
250296
type = "RESPONSE"
251297
statement = "req.http.Fastly-Client-IP == \"127.0.0.1\" && req.http.Fastly-Client-IP != \"127.0.0.1\""
252298
}
299+
300+
condition {
301+
name = "Package Served From Fallback"
302+
type = "RESPONSE"
303+
statement = "req.restarts == 0 && req.backend == S3 && req.url ~ \"^/packages/[a-f0-9]{2}/[a-f0-9]{2}/[a-f0-9]{60}/\" && http_status_matches(beresp.status, \"200\")"
304+
}
253305
}
254306

255307
resource "aws_route53_record" "files" {

terraform/file-hosting/main.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ variable "aws_access_key_id" { type = string }
1111
variable "aws_secret_access_key" { type = string }
1212
variable "gcs_access_key_id" { type = string }
1313
variable "gcs_secret_access_key" { type = string }
14+
variable "datadog_token" { type = string }
1415

1516
variable "fastly_endpoints" { type = map(any) }
1617
variable "domain_map" { type = map(any) }

terraform/file-hosting/vcl/files.vcl

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,28 @@ sub vcl_recv {
7575
# Change our backend to S3 to look for the file there, re-enable clustering and continue
7676
# https://www.slideshare.net/Fastly/advanced-vcl-how-to-use-restart
7777
if (req.restarts > 0 && req.url ~ "^/packages/[a-f0-9]{2}/[a-f0-9]{2}/[a-f0-9]{60}/") {
78-
set req.backend = F_S3;
78+
set req.backend = F_GCS;
7979
set req.http.Fastly-Force-Shield = "1";
8080
}
8181

82-
# Requests that are for an *actual* file get disaptched to Amazon S3 instead of
83-
# to our typical backends. We need to setup the request to correctly access
84-
# S3 and to authorize ourselves to S3.
82+
# Requests that are for an *actual* file get disaptched to object storage instead of
83+
# to our typical backends.
84+
85+
# If our file request is being dispatched to B2, we need to setup the request to correctly
86+
# access B2 and to authorize ourselves to B2 with S3 compatible auth.
87+
if (req.backend == F_B2 && req.url ~ "^/packages/[a-f0-9]{2}/[a-f0-9]{2}/[a-f0-9]{60}/") {
88+
# Setup our environment to better match what S3 expects/needs
89+
set req.http.Host = var.B2-Bucket-Name "s3.us-east-005.backblazeb2.com";
90+
set req.http.Date = now;
91+
set req.url = regsuball(req.url, "\+", urlencode("+"));
92+
93+
# Compute the Authorization header that B2 requires to be able to
94+
# access the files stored there.
95+
set req.http.Authorization = "AWS " var.B2-Application-Key-ID":" digest.hmac_sha1_base64(var.B2-Application-Key, "GET" LF LF LF req.http.Date LF "/" var.S3-Bucket-Name req.url.path);
96+
}
97+
98+
# If our file request is being dispatched to S3, we need to setup the request to correctly
99+
# access S3 and to authorize ourselves to S3.
85100
if (req.backend == F_S3 && req.url ~ "^/packages/[a-f0-9]{2}/[a-f0-9]{2}/[a-f0-9]{60}/") {
86101
# Setup our environment to better match what S3 expects/needs
87102
set req.http.Host = var.S3-Bucket-Name ".s3.amazonaws.com";
@@ -92,6 +107,7 @@ sub vcl_recv {
92107
# access the files stored there.
93108
set req.http.Authorization = "AWS " var.AWS-Access-Key-ID ":" digest.hmac_sha1_base64(var.AWS-Secret-Access-Key, "GET" LF LF LF req.http.Date LF "/" var.S3-Bucket-Name req.url.path);
94109
}
110+
95111
# If our file request is being dispatched to GCS, setup the request to correctly
96112
# access GCS and authorize ourselves with GCS interoperability credentials.
97113
if (req.backend == GCS && req.url ~ "^/packages/[a-f0-9]{2}/[a-f0-9]{2}/[a-f0-9]{60}/") {
@@ -126,9 +142,9 @@ sub vcl_fetch {
126142
set beresp.cacheable = true;
127143
}
128144

129-
# If we successfully got a 404 response from GCS for a Package URL restart
130-
# to check S3 for the file!
131-
if (req.restarts == 0 && req.backend == GCS && req.url ~ "^/packages/[a-f0-9]{2}/[a-f0-9]{2}/[a-f0-9]{60}/" && http_status_matches(beresp.status, "404")) {
145+
# If we successfully got a 404 response from B2 for a Package URL restart
146+
# to check GCS for the file!
147+
if (req.restarts == 0 && req.backend == B2 && req.url ~ "^/packages/[a-f0-9]{2}/[a-f0-9]{2}/[a-f0-9]{60}/" && http_status_matches(beresp.status, "404")) {
132148
restart;
133149
}
134150

terraform/main.tf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ module "file-hosting" {
149149
files_bucket = "pypi-files"
150150
mirror = "mirror.dub1.pypi.io"
151151
s3_logging_keys = var.fastly_s3_logging
152+
datadog_token = var.datadog_token
152153

153154
aws_access_key_id = var.aws_access_key_id
154155
aws_secret_access_key = var.aws_secret_access_key
@@ -177,6 +178,7 @@ module "test-file-hosting" {
177178
files_bucket = "pypi-files-staging"
178179
mirror = "test-mirror.dub1.pypi.io"
179180
s3_logging_keys = var.fastly_s3_logging
181+
datadog_token = var.datadog_token
180182

181183
aws_access_key_id = var.aws_access_key_id
182184
aws_secret_access_key = var.aws_secret_access_key

0 commit comments

Comments
 (0)