diff --git a/src/Compute/Metadata/GCEMetadataStream.php b/src/Compute/Metadata/GCEMetadataStream.php new file mode 100644 index 000000000000..50f773a92b61 --- /dev/null +++ b/src/Compute/Metadata/GCEMetadataStream.php @@ -0,0 +1,173 @@ +reader = new StreamReader(); + } + + /** + * A method to replace the reader implementation. + */ + public function setReader($reader) + { + $this->reader = $reader; + } + + // @codingStandardsIgnoreStart + + // These methods are mandatory for implementing stream wrappers, + // so marking them with ignore tag. + // + // TODO: Find a way to just suppress certain types of errors with + // phpcs. + public function stream_open($path, $mode, $options, &$opened_path) + { + $url = parse_url($path); + if ($url['host'] != 'project' and $url['host'] != 'instance') { + return false; + } + $metadata_url = self::METADATA_BASE_URL.$url['host'].'/attributes' + .$url['path']; + $this->val = $this->reader->read($metadata_url); + $this->position = 0; + + return true; + } + + public function stream_stat() + { + return array(); + } + + public function stream_read($count) + { + $ret = substr($this->val, $this->position, $count); + $this->position += strlen($ret); + + return $ret; + } + + public function stream_write($data) + { + trigger_error('stream_write is not implemented.', E_WARNING); + } + + public function stream_tell() + { + return $this->position; + } + + public function stream_eof() + { + return $this->position >= strlen($this->val); + } + + public function stream_seek($offset, $whence) + { + switch ($whence) { + case SEEK_SET: + if ($offset < strlen($this->val) && $offset >= 0) { + $this->position = $offset; + + return true; + } else { + return false; + } + break; + + case SEEK_CUR: + if ($offset >= 0) { + $this->position += $offset; + + return true; + } else { + return false; + } + break; + + case SEEK_END: + if (strlen($this->val) + $offset >= 0) { + $this->position = strlen($this->val) + $offset; + + return true; + } else { + return false; + } + break; + + default: + return false; + } + } + + public function stream_metadata($path, $option, $var) + { + return false; + } + // @codingStandardsIgnoreEnd +} diff --git a/src/Compute/Metadata/Readers/StreamReader.php b/src/Compute/Metadata/Readers/StreamReader.php new file mode 100644 index 000000000000..dabe97f64043 --- /dev/null +++ b/src/Compute/Metadata/Readers/StreamReader.php @@ -0,0 +1,44 @@ + array( + 'method' => 'GET', + 'header' => self::FLAVOR_HEADER.": Google\r\n", + ), + ); + $context = stream_context_create($options); + + return file_get_contents($url, false, $context); + } +} diff --git a/tests/ComputeMetadataTest.php b/tests/ComputeMetadataTest.php new file mode 100644 index 000000000000..0f1157508f28 --- /dev/null +++ b/tests/ComputeMetadataTest.php @@ -0,0 +1,80 @@ +stream = new GCEMetadataStream(); + $this->mock = $this->getMockBuilder( + '\Google\Cloud\Compute\Metadata\StreamReader') + ->setMethods(array('read')) + ->getmock(); + $this->stream->setReader($this->mock); + } + + public function testProjectMetadata() + { + $expected_url = 'http://metadata.google.internal/computeMetadata/v1/' + .'project/attributes/mykey'; + $expected_val = 'myval'; + $this->mock->expects($this->once()) + ->method('read') + ->with($this->equalTo($expected_url)) + ->willReturn($expected_val); + $dummy = ''; + $this->stream->stream_open('gce-metadata://project/mykey', null, null, + $dummy); + $val = $this->stream->stream_read(10); + $this->assertEquals($expected_val, $val); + } + + public function testInstanceMetadata() + { + $expected_url = 'http://metadata.google.internal/computeMetadata/v1/' + .'instance/attributes/mykey'; + $expected_val = 'myval'; + $this->mock->expects($this->once()) + ->method('read') + ->with($this->equalTo($expected_url)) + ->willReturn($expected_val); + $dummy = ''; + $this->stream->stream_open('gce-metadata://instance/mykey', null, null, + $dummy); + $val = $this->stream->stream_read(10); + $this->assertEquals($expected_val, $val); + } + + public function testBogusMetadata() + { + $expected_val = false; + $this->mock->expects($this->never()) + ->method('read') + ->with($this->anything()); + $dummy = ''; + $this->stream->stream_open('gce-metadata://bogus/mykey', null, null, + $dummy); + $val = $this->stream->stream_read(10); + $this->assertEquals($expected_val, $val); + } +}