Skip to content

Commit 09f0849

Browse files
authored
Merge pull request #1 from outcompute/add-azure-gcp
Add support for Azure, GCP & templated responses.
2 parents ae3b99f + bf4a443 commit 09f0849

21 files changed

+548
-391
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
/vendor
2+
.DS_Store

LICENSE

Lines changed: 21 additions & 339 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# CloudMetaData
22
A simple PHP library to fetch instance meta data from the link local address of http://169.254.169.254 from within an instance.
3-
- Supports [AWS][awsmetadata] & [DigitalOcean][dometadata].
3+
- Supports [AWS][awsmetadata], [Azure][azuremetadata], [DigitalOcean][dometadata] & [Google Cloud][gcpmetadata].
44
- Results can be cached in a file.
55
- Always refreshes metadata after a restart.
66

@@ -10,12 +10,31 @@ The 169.254.169.254 is a link-local address and you can read up more about them
1010
### Installation
1111
Add this line to your composer.json file,
1212
```json
13-
"outcompute/cloudmetadata": "1.4.0"
13+
"outcompute/cloudmetadata": "1.5.0"
1414
```
1515
and run.
1616
```sh
1717
$ composer update
1818
```
19+
In case you don't want to use composer, you'll have to include all the files, something like this:
20+
```php
21+
include_once('src/Cache/AbstractCache.php');
22+
include_once('src/Cache/File.php');
23+
include_once('src/CacheFactory.php');
24+
include_once('src/Provider/AbstractProvider.php');
25+
include_once('src/Provider/AWS.php');
26+
include_once('src/Provider/Azure.php');
27+
include_once('src/Provider/DigitalOcean.php');
28+
include_once('src/Provider/GCP.php');
29+
include_once('src/ProviderFactory.php');
30+
include_once('src/TemplateParser/Base.php');
31+
include_once('src/TemplateParser/AWS.php');
32+
include_once('src/TemplateParser/Azure.php');
33+
include_once('src/TemplateParser/DigitalOcean.php');
34+
include_once('src/TemplateParser/GCP.php');
35+
include_once('src/TemplateParserFactory.php');
36+
include_once('src/MetaData.php');
37+
```
1938

2039

2140
### How to use
@@ -38,24 +57,44 @@ include_once('vendor/autoload.php');
3857
$cache = OutCompute\CloudMetaData\CacheFactory::factory('File');
3958
$cache->directory = dirname(__FILE__);
4059
$metaObject = new OutCompute\CloudMetaData\MetaData($cache);
41-
$metaData = $metaObject->get();
60+
$metaData = $metaObject->get('json');
61+
var_export($metaData);
62+
?>
63+
```
64+
65+
### Templated Responses
66+
If you've cross cloud deployments and use the metadata in any way, then it'd help to have the metadata in a consistent manner.
67+
Support has been added for templates which allows you to specify templates and tokens. A few sample tokens have been provided.
68+
Common and provider agnostic tokens are processed in `src/TemplateParser/Base.php` whereas provider specific tokens are parsed in their specific handlers present in `src/TemplateParser`.
69+
70+
The templates have to be stored in the templates directory, and the file name provided as the second argument to `OutCompute\CloudMetaData\MetaData()::get()`.
71+
```php
72+
<?php
73+
include_once('vendor/autoload.php');
74+
75+
$metaObject = new OutCompute\CloudMetaData\MetaData();
76+
$metaData = $metaObject->get('json', 'basic.json');
4277
var_export($metaData);
4378
?>
4479
```
80+
The tokens don't have to follow the heirarchy from the templates they are included in and can be any string as long as they are handled in any parser. The initial set of supported tokens seem to follow the heirarchy in basic.json with a dot(.) as a separator, but that is not a strict requirement.
4581

82+
However, if you're contributing to the repository then it'd be great if the tokens followed some structure.
4683

4784
### TODO
4885

49-
- Add other cloud providers, eg: Google Cloud, Microsoft Azure, Linode, etc.
86+
- Add other cloud providers, eg: Linode, etc.
5087
- Add test cases
5188
- General improvements
52-
89+
- Supporting templates in varied configurations and extending the set of supported tokens
5390

5491
License
5592
----
5693

57-
GPL v2
94+
MIT
5895

5996
[awsmetadata]: <http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html>
97+
[azuremetadata]: <https://docs.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service>
6098
[dometadata]: <https://developers.digitalocean.com/documentation/metadata/>
99+
[gcpmetadata]: <https://cloud.google.com/compute/docs/storing-retrieving-metadata>
61100
[wikilinklocal]: <https://en.wikipedia.org/wiki/Link-local_address>

composer.json

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,20 @@
22
"name": "outcompute/cloudmetadata",
33
"description": "Get metadata JSON within an instance from 169.254.169.254 across providers.",
44
"type": "library",
5-
"license": "GPL-2.0",
5+
"license": "MIT",
66
"authors": [
77
{
8-
"name": "outcompute",
9-
"email": "gkumarrahul@gmail.com"
8+
"name": "outcompute",
9+
"email": "gkumarrahul@gmail.com"
1010
}
1111
],
1212
"require": {},
1313
"autoload": {
14-
"psr-4": {
15-
"OutCompute\\CloudMetaData\\": "src",
16-
"OutCompute\\CloudMetaData\\Cache\\": "src/Cache",
17-
"OutCompute\\CloudMetaData\\Provider\\": "src/Provider"
18-
}
19-
}
14+
"psr-4": {
15+
"OutCompute\\CloudMetaData\\": "src",
16+
"OutCompute\\CloudMetaData\\Cache\\": "src/Cache",
17+
"OutCompute\\CloudMetaData\\Provider\\": "src/Provider",
18+
"OutCompute\\CloudMetaData\\TemplateParser\\": "src/TemplateParser"
19+
}
20+
}
2021
}

src/Cache/AbstractCache.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
<?php
2+
/**
3+
* The AbstractCache class file.
4+
*
5+
* @author outcompute
6+
*/
7+
28
namespace OutCompute\CloudMetaData\Cache;
39

410
abstract class AbstractCache
511
{
6-
abstract public function get($key);
7-
abstract public function set($key, $data);
12+
abstract public function get($key);
13+
abstract public function set($key, $data);
814
}
915
?>

src/Cache/File.php

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33
* The File cache class file.
44
*
55
* @author outcompute
6-
* @license https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt GPL v2
7-
* @version 1.0.0
8-
* @since File available since Release 1.0.0
96
*/
107

118
namespace OutCompute\CloudMetaData\Cache;

src/CacheFactory.php

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33
* The CacheFactory class file.
44
*
55
* @author outcompute
6-
* @license https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt GPL v2
7-
* @version 1.0.0
8-
* @since File available since Release 1.0.0
96
*/
107

118
namespace OutCompute\CloudMetaData;

src/MetaData.php

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@
77
* in case interface addresses or any other property has been re-assigned.
88
*
99
* @author outcompute
10-
* @license https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt GPL v2
11-
* @version 1.0.0
12-
* @since File available since Release 1.0.0
1310
*/
1411

1512
namespace OutCompute\CloudMetaData;
@@ -22,15 +19,15 @@ class MetaData
2219
private $_data;
2320
private $_provider;
2421

25-
public function __construct($cache = null, $providerFilter = null) {
26-
$this->_data = null;
27-
$this->_provider = null;
22+
public function __construct($cache = NULL, $providerFilter = NULL) {
23+
$this->_data = NULL;
24+
$this->_provider = NULL;
2825
$cacheKey = 'cloudmetadata';
2926

3027
# List of supported providers to try against
31-
$providers = array('AWS', 'DigitalOcean');
28+
$providers = array('AWS', 'Azure', 'DigitalOcean', 'GCP');
3229

33-
if($cache != null) {
30+
if($cache != NULL) {
3431
$metadata = $cache->get($cacheKey);
3532
if($metadata != NULL) {
3633
$uptime = floatval(@file_get_contents('/proc/uptime'));
@@ -46,16 +43,16 @@ public function __construct($cache = null, $providerFilter = null) {
4643
}
4744
}
4845

49-
if($this->_data == null) {
50-
if($providerFilter != null && is_array($providerFilter))
46+
if($this->_data == NULL) {
47+
if($providerFilter != NULL && is_array($providerFilter))
5148
$providers = array_intersect($providers, $providerFilter);
5249

5350
foreach($providers as $provider) {
5451
$this->_data = call_user_func(array(ProviderFactory::factory($provider), 'get'));
5552

56-
if($this->_data != null) {
53+
if($this->_data != NULL) {
5754
# The first match has been found, and return after saving to cache, if cache object is set
58-
if($cache != null)
55+
if($cache != NULL)
5956
$cache->set($cacheKey, array('created' => time(), 'provider' => $provider, 'data' => $this->_data));
6057
$this->_provider = $provider;
6158
break;
@@ -64,9 +61,22 @@ public function __construct($cache = null, $providerFilter = null) {
6461
}
6562
}
6663

67-
public function get($format = 'array')
68-
{
64+
public function get($format = 'array', $templateName = NULL) {
6965
$response = array('provider' => $this->_provider, 'metadata' => $this->_data);
66+
$templatedResponse = NULL;
67+
68+
if($templateName != NULL) {
69+
$parsedResponseObject = NULL;
70+
$templatePath = rtrim(__DIR__, '/').'/../templates/'.basename($templateName);
71+
if(file_exists($templatePath))
72+
$templateObject = json_decode(file_get_contents($templatePath), true);
73+
if($templateObject != NULL) {
74+
$parserObject = TemplateParserFactory::factory($response['provider'], $response['metadata']);
75+
$parsedResponseObject = $this->_parseTemplate($templateObject, $parserObject);
76+
}
77+
$response = $parsedResponseObject;
78+
}
79+
7080
switch($format) {
7181
case 'json':
7282
return json_encode($response, JSON_PRETTY_PRINT);
@@ -76,5 +86,23 @@ public function get($format = 'array')
7686
break;
7787
}
7888
}
89+
90+
private function _parseTemplate($templateObject, $parserObject) {
91+
foreach($templateObject as $k => $v) {
92+
switch(gettype($v)) {
93+
case "string":
94+
$templateObject[$k] = $parserObject->get($v);
95+
break;
96+
case "array":
97+
case "object":
98+
$templateObject[$k] = $this->_parseTemplate($v, $parserObject);
99+
break;
100+
default:
101+
$templateObject[$k] = $v;
102+
break;
103+
}
104+
}
105+
return $templateObject;
106+
}
79107
}
80108
?>

src/Provider/AWS.php

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@
55
* This fetches the metadata from the Amazon meta data service
66
*
77
* @author outcompute
8-
* @license https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt GPL v2
9-
* @version 1.0.0
10-
* @since File available since Release 1.0.0
118
*/
129

1310
namespace OutCompute\CloudMetaData\Provider;
@@ -26,10 +23,15 @@ public function get() {
2623
# Furthermore we need to segregate them because although AWS documentation does mention that all keys ending in '/'
2724
# have expansions, the keys reported at http://169.254.169.254/latest/ don't end in '/'
2825
$keys = array('dynamic/', 'meta-data/', 'user-data/');
29-
foreach($keys as $key)
30-
$response[trim($key, '/')] = $this->_recurse(self::BASE, $key);
26+
$allValuesNull = true;
27+
foreach($keys as $key) {
28+
$value = $this->_recurse(self::BASE, $key);
29+
$response[trim($key, '/')] = $value;
30+
if($value != NULL)
31+
$allValuesNull = false;
32+
}
3133

32-
return $response;
34+
return $allValuesNull == true ? NULL : $response;
3335
}
3436

3537
private function _recurse($url, $key) {

src/Provider/AbstractProvider.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33
* The AbstractProvider class file.
44
*
55
* @author outcompute
6-
* @license https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt GPL v2
7-
* @version 1.0.0
8-
* @since File available since Release 1.0.0
96
*/
107

118
namespace OutCompute\CloudMetaData\Provider;
@@ -20,13 +17,17 @@ public function connect($url, $options = array())
2017
if(function_exists('curl_init')) {
2118
$curl = curl_init($url);
2219
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
20+
foreach($options as $opt)
21+
curl_setopt($curl, $opt['option'], $opt['value']);
2322
$result = curl_exec($curl);
2423
$info = curl_getinfo($curl);
2524
$errorStr = curl_error($curl);
2625
curl_close($curl);
2726

2827
if($info['http_code'] == 200)
2928
return $result;
29+
else
30+
return NULL;
3031
} else {
3132
throw new \Exception("OutCompute\CloudMetaData\Provider\AbstractProvider : curl not installed. Failed to connect to $url");
3233
}

0 commit comments

Comments
 (0)