Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/files/engine/PhabricatorS3FileStorageEngine.php
12241 views
1
<?php
2
3
/**
4
* Amazon S3 file storage engine. This engine scales well but is relatively
5
* high-latency since data has to be pulled off S3.
6
*
7
* @task internal Internals
8
*/
9
final class PhabricatorS3FileStorageEngine
10
extends PhabricatorFileStorageEngine {
11
12
13
/* -( Engine Metadata )---------------------------------------------------- */
14
15
16
/**
17
* This engine identifies as `amazon-s3`.
18
*/
19
public function getEngineIdentifier() {
20
return 'amazon-s3';
21
}
22
23
public function getEnginePriority() {
24
return 100;
25
}
26
27
public function canWriteFiles() {
28
$bucket = PhabricatorEnv::getEnvConfig('storage.s3.bucket');
29
$access_key = PhabricatorEnv::getEnvConfig('amazon-s3.access-key');
30
$secret_key = PhabricatorEnv::getEnvConfig('amazon-s3.secret-key');
31
$endpoint = PhabricatorEnv::getEnvConfig('amazon-s3.endpoint');
32
$region = PhabricatorEnv::getEnvConfig('amazon-s3.region');
33
34
return ($bucket !== null && strlen($bucket) &&
35
$access_key !== null && strlen($access_key) &&
36
$secret_key !== null && strlen($secret_key) &&
37
$endpoint !== null && strlen($endpoint) &&
38
$region !== null && strlen($region));
39
}
40
41
42
/* -( Managing File Data )------------------------------------------------- */
43
44
45
/**
46
* Writes file data into Amazon S3.
47
*/
48
public function writeFile($data, array $params) {
49
$s3 = $this->newS3API();
50
51
// Generate a random name for this file. We add some directories to it
52
// (e.g. 'abcdef123456' becomes 'ab/cd/ef123456') to make large numbers of
53
// files more browsable with web/debugging tools like the S3 administration
54
// tool.
55
$seed = Filesystem::readRandomCharacters(20);
56
$parts = array();
57
$parts[] = 'phabricator';
58
59
$instance_name = PhabricatorEnv::getEnvConfig('cluster.instance');
60
if ($instance_name !== null && strlen($instance_name)) {
61
$parts[] = $instance_name;
62
}
63
64
$parts[] = substr($seed, 0, 2);
65
$parts[] = substr($seed, 2, 2);
66
$parts[] = substr($seed, 4);
67
68
$name = implode('/', $parts);
69
70
AphrontWriteGuard::willWrite();
71
$profiler = PhutilServiceProfiler::getInstance();
72
$call_id = $profiler->beginServiceCall(
73
array(
74
'type' => 's3',
75
'method' => 'putObject',
76
));
77
78
$s3
79
->setParametersForPutObject($name, $data)
80
->resolve();
81
82
$profiler->endServiceCall($call_id, array());
83
84
return $name;
85
}
86
87
88
/**
89
* Load a stored blob from Amazon S3.
90
*/
91
public function readFile($handle) {
92
$s3 = $this->newS3API();
93
94
$profiler = PhutilServiceProfiler::getInstance();
95
$call_id = $profiler->beginServiceCall(
96
array(
97
'type' => 's3',
98
'method' => 'getObject',
99
));
100
101
$result = $s3
102
->setParametersForGetObject($handle)
103
->resolve();
104
105
$profiler->endServiceCall($call_id, array());
106
107
return $result;
108
}
109
110
111
/**
112
* Delete a blob from Amazon S3.
113
*/
114
public function deleteFile($handle) {
115
$s3 = $this->newS3API();
116
117
AphrontWriteGuard::willWrite();
118
$profiler = PhutilServiceProfiler::getInstance();
119
$call_id = $profiler->beginServiceCall(
120
array(
121
'type' => 's3',
122
'method' => 'deleteObject',
123
));
124
125
$s3
126
->setParametersForDeleteObject($handle)
127
->resolve();
128
129
$profiler->endServiceCall($call_id, array());
130
}
131
132
133
/* -( Internals )---------------------------------------------------------- */
134
135
136
/**
137
* Retrieve the S3 bucket name.
138
*
139
* @task internal
140
*/
141
private function getBucketName() {
142
$bucket = PhabricatorEnv::getEnvConfig('storage.s3.bucket');
143
if (!$bucket) {
144
throw new PhabricatorFileStorageConfigurationException(
145
pht(
146
"No '%s' specified!",
147
'storage.s3.bucket'));
148
}
149
return $bucket;
150
}
151
152
/**
153
* Create a new S3 API object.
154
*
155
* @task internal
156
*/
157
private function newS3API() {
158
$access_key = PhabricatorEnv::getEnvConfig('amazon-s3.access-key');
159
$secret_key = PhabricatorEnv::getEnvConfig('amazon-s3.secret-key');
160
$region = PhabricatorEnv::getEnvConfig('amazon-s3.region');
161
$endpoint = PhabricatorEnv::getEnvConfig('amazon-s3.endpoint');
162
163
return id(new PhutilAWSS3Future())
164
->setAccessKey($access_key)
165
->setSecretKey(new PhutilOpaqueEnvelope($secret_key))
166
->setRegion($region)
167
->setEndpoint($endpoint)
168
->setBucket($this->getBucketName());
169
}
170
171
}
172
173