From 9be1b62406c56e395bf62312b06011913e091fcc Mon Sep 17 00:00:00 2001 From: Takashi Matsuo Date: Mon, 9 Nov 2015 15:37:35 -0800 Subject: [PATCH] Adding GCE metadata lib. Fixes #8 --- src/Compute/Metadata.php | 98 +++++++++++++++++++ src/Compute/Metadata/Readers/StreamReader.php | 85 ++++++++++++++++ tests/ComputeMetadataTest.php | 74 ++++++++++++++ 3 files changed, 257 insertions(+) create mode 100644 src/Compute/Metadata.php create mode 100644 src/Compute/Metadata/Readers/StreamReader.php create mode 100644 tests/ComputeMetadataTest.php diff --git a/src/Compute/Metadata.php b/src/Compute/Metadata.php new file mode 100644 index 000000000000..11c135117ac7 --- /dev/null +++ b/src/Compute/Metadata.php @@ -0,0 +1,98 @@ +getProjectId(); + * + * $val = $metadata->getProjectMetadata($key); + */ +class Metadata +{ + /** + * The metadata reader. + */ + private $reader; + + /** + * The project id. + */ + private $projectId; + + /** + * We use StreamReader for the default implementation for fetching the URL. + */ + public function __construct() + { + $this->reader = new StreamReader(); + } + + /** + * A method to replace the reader implementation. + */ + public function setReader($reader) + { + $this->reader = $reader; + } + + /** + * This method retrieves a single metadata value for a given path. + */ + public function get($path) + { + return $this->reader->read($path); + } + + /** + * This method detects the project id and returns it. + */ + public function getProjectId() + { + if (! isset($this->projectId)) { + $this->projectId = $this->reader->read('project/project-id'); + } + return $this->projectId; + } + + /** + * This method fetches the project custom metadta and returns it. + */ + public function getProjectMetadata($key) + { + $path = 'project/attributes/'.$key; + return $this->get($path); + } + + /** + * This method fetches the instance custom metadta and returns it. + */ + public function getInstanceMetadata($key) + { + $path = 'instance/attributes/'.$key; + return $this->get($path); + } +} diff --git a/src/Compute/Metadata/Readers/StreamReader.php b/src/Compute/Metadata/Readers/StreamReader.php new file mode 100644 index 000000000000..9e47d7dcb1a0 --- /dev/null +++ b/src/Compute/Metadata/Readers/StreamReader.php @@ -0,0 +1,85 @@ + array( + 'method' => 'GET', + 'header' => self::FLAVOR_HEADER, + ), + ); + $this->context = stream_context_create($options); + } + + /** + * A method to read the metadata value for a given path. + */ + public function read($path) + { + $url = self::BASE_URL.$path; + return file_get_contents($url, false, $this->context); + } + + /** + * A method to detect whether it's running on Compute Engine or not. + */ + public function onGCE() + { + // We use the hostname for failing faster on non-gce environment. + $url = 'http://'.self::HOST; + $result = file_get_contents($url, false, $this->context); + if ($result != false + && array_key_exists('Metadata-Flavor', $http_response_header) + && $http_response_header['Metadata-Flavor'] == 'Google') { + return true; + } + return false; + } +} diff --git a/tests/ComputeMetadataTest.php b/tests/ComputeMetadataTest.php new file mode 100644 index 000000000000..138a3f94bf28 --- /dev/null +++ b/tests/ComputeMetadataTest.php @@ -0,0 +1,74 @@ +metadata = new Metadata(); + $this->mock = $this->getMockBuilder( + '\Google\Cloud\Compute\Metadata\Readers\StreamReader') + ->setMethods(array('read')) + ->getmock(); + $this->metadata->setReader($this->mock); + } + + public function testProjectMetadata() + { + $expected_path = 'project/attributes/mykey'; + $expected_val = 'myval'; + $this->mock->expects($this->once()) + ->method('read') + ->with($this->equalTo($expected_path)) + ->willReturn($expected_val); + $val = $this->metadata->getProjectMetadata('mykey'); + $this->assertEquals($expected_val, $val); + } + + public function testInstanceMetadata() + { + $expected_path = 'instance/attributes/mykey'; + $expected_val = 'myval'; + $this->mock->expects($this->once()) + ->method('read') + ->with($this->equalTo($expected_path)) + ->willReturn($expected_val); + $val = $this->metadata->getInstanceMetadata('mykey'); + $this->assertEquals($expected_val, $val); + } + + public function testGetProjectIdCached() + { + $expected_path = 'project/project-id'; + $expected_val = 'my-project'; + $this->mock->expects($this->once()) + ->method('read') + ->with($this->equalTo($expected_path)) + ->willReturn($expected_val); + $project_id = $this->metadata->getProjectId(); + $this->assertEquals($expected_val, $project_id); + // Ensure this value is cached thus we `read` only once. + $project_id = $this->metadata->getProjectId(); + } +}