Listing buckets in cloud storage project using PHP API - php

I'm trying to list out all (some, even) of the buckets in my storage project. If I know the name of a bucket, the "bucket" function will get the bucket. But I can't use "buckets" to list the buckets in my project:
$client = new StorageClient(
[
'projectId' => <my project id>,
'keyFile' => json_decode(file_get_contents(<my json file>))
]
);
$bucket_name = 'idx-mls-info-gs-ihouseprd.com';
$one_bucket = $client->bucket( $bucket_name );
print "GOT BUCKET: " . $one_bucket->name() . "\n";
// NOTE: this works
$prefix = 'idx-';
print "Getting buckets (prefix: $prefix)\n";
$buckets = $client->buckets( ['prefix' => $prefix] );
foreach ( $buckets as $bucket )
{
printf('Bucket: %s' . PHP_EOL, $bucket->name());
}
print "done with buckets"
// THIS DOES NOTHING
My service account has the "Storage Admin" role. I am perplexed.
NOTE: I am using PHP 5.6, in case that matters. Composer didn't have a problem installing the GCS library, so I assumed that was ok.
Ok, so I must be missing something. Using my test case of getting a single bucket, I have then used $one_bucket->object(), and successfully gotten an object. But if I try $one_bucket->objects(), I again get nothing. So the multiple case for entities in the GCS is not working for me, whether buckets or objects. Perhaps that's a clue.
Further information:
There is an exception when hitting the iterator (foreach $buckets as $bucket):
exception 'Exception' with message 'exception 'Google\Cloud\Core\Exception\ServiceException' with message '4096:Argument 2 passed to Google\Auth\CredentialsLoader::makeCredentials() must be of the type array, object given, called in /home/httpd/idxv3/vendor/google/cloud-core/src/RequestWrapperTrait.php on line 158 and defined in /home/httpd/idxv3/vendor/google/auth/src/CredentialsLoader.php on line 135' in /home/httpd/idxv3/vendor/google/cloud-core/src/RequestWrapper.php:362
Not sure why the authentication is causing problems.

I've found a link for your first question and I hope this helps guide you. It describes how to list the buckets in your project.

Ok, I found out what the problem was/is. It is in the creation of the storage client. My call the json_decode was missing a parameter. As in my original code, what gets passed into the constructor is a stdClass Object, which is not liked down in the depths of the code. Adding ", true" to the call to json_decode, what gets passed in is then an array, which is desired:
$client = new StorageClient(
[
'projectId' => <my project id>,
'keyFile' => json_decode(file_get_contents(<my json file>), true)
]
);
This fixes the problems I was having. Not sure why I didn't get errors earlier on, like in the constructor.

Related

Test error handling of the PHP S3Client uploadAsync method

Method uploadAsync automatically decides and uploads object in single or multiple chunks. And we can expect 2 different kind of expectations S3Exception and S3MultipartUploadException in our $result['reason']. I'm trying to mock part of the S3 client to throw the exception, I have done this by MockHandler:
$s3->getHandlerList()->setHandler(new MockHandler([$result], null, null));
And the $result is:
new S3Exception("", new Command("mockCommand"), [
'code' => 'mockCode',
'response' => new Response(401)
])
Or either this:
new S3MultipartUploadException(new UploadState(['testid']))
Since the S3MultipartUploadException is not instance of AwsException I got this exception:
InvalidArgumentException: Expected an Aws\ResultInterface or Aws\Exception\AwsException.
How can I handle such scenario?
I have asked this on the project repo and they confirmed this is a bug https://github.com/aws/aws-sdk-php/issues/2143.

PHP SDK Cannot get AWS Credentials on EC2 Instance with IAM Role attached

Simple question. But cannot get it to work.
I created an IAM Role for EC2 with full access to CloudWatch.
I launched a new EC2 instance with this IAM Role attached.
I wrote a simple PHP application on this EC2 instance which tries to publish metrics to CloudWatch.
I am getting this error in nginx logs:
2017/08/23 11:44:06 [error] 32142#32142: *5 FastCGI sent in stderr:
"PHP message: PHP Fatal error:
Uncaught Aws\Exception\CredentialsException:
Cannot read credentials from /var/www/.aws/credentials
in /var/www/app/vendor/aws/aws-sdk-php/src/Credentials/CredentialProvider.php:394
From that same EC2 instance, the command:
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/<role-attached-to-ec2-instance>
returns 200 OK with the Access Key and Secret in the response.
This is my PHP code that tries to write CloudWatch metrics:
<?php
require 'vendor/autoload.php';
use Aws\CloudWatch\CloudWatchClient;
use Aws\Exception\AwsException;
$count = $_GET["count"];
publishMetric($count);
function publishMetric($count) {
$client = new CloudWatchClient([
'profile' => 'default',
'region' => 'us-east-1',
'version' => '2010-08-01'
]);
try {
$result = $client->putMetricData(array(
'Namespace' => 'com.mynamespace',
'MetricData' => array(
array(
'MetricName' => 'Count',
//Timestamp : mixed type: string (date format)|int (unix timestamp)|\DateTime
'Timestamp' => time(),
'Value' => $count,
'Unit' => 'Number'
)
)
));
var_dump($result);
echo 'Done publishing metrics';
} catch (AwsException $e) {
// output error message if fails
error_log($e->getMessage());
echo 'Failure to publish metrics';
}
}
?>
Any idea what is missing in this setup?
I know this is late. I had the same issue and resolved it by removing profile => default line while initializing the client. If you do not provide credentials and profile, SDK will try to retrieve instance profile creds from metadata server.
Authentication of EC2 instance while accessing other AWS Services can be done in multiple ways:
Assigning a role to EC2 instance. Used when u have to give some "EC2 instance" a permission.
Do not assign a role; but use access-key which has all required permissions. Used when you give permission to a "User"
Both these are independent authentication mechanism. If you have already assigned role to your server; you do not have to write any code in your application (CredentialProvider.php) to authenticate.
Your current code can also be worked by creating a file /var/www/.aws/credentials which will look something like this:
accessKey=AKIAIB6FA52IMGLREIIB
secretKey=NQjJWKT+WZOUOrQ2Pr/WcRey3PnQFaGMJ8nRoaVU

How to create a spreadsheet with google api and set a proper permissions with PHP?

I have this
define('CLIENT_SECRET_PATH', __DIR__ . '/config_api.json');
define('ACCESS_TOKEN', '0b502651********c52b3');
I can create a spreadsheet with this and get the id and url.
$requestBody = new Google_Service_Sheets_Spreadsheet();
$response = $service->spreadsheets->create($requestBody);
print_r($response);
$new_spr_id = $response['spreadsheetId'];
But this spreadsheet does not appears in the google sheets list as it is "protected" or something.
I am trying to set the permissions with this but get an error: Fatal error: Call to undefined method Google_Service_Drive_Permission::setValue()
insertPermission($service, $new_spr_id, '**#gmail.com' , 'user', 'owner');
function insertPermission($service, $fileId, $value, $type, $role) {
$newPermission = new Google_Service_Drive_Permission();
$newPermission->setValue($value);
$newPermission->setType($type);
$newPermission->setRole($role);
try {
return $service->permissions->insert($fileId, $newPermission);
} catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
}
return NULL;
}
I need an example of creating a new spreadsheet and setting the proper permissions to it so I can modify this spreadsheet from my account etc.
Many many thanks!
Your code is not able to locate class and unable to create instance of Google_Service_Drive_Permission(). I would suggest, don't use individual function to create object of Google_Service_Drive_Permission(). Place all your code to set permissions within the code part, where you are creating file. Also if you are using multiple files, check if your files are loading properly and are located by PHP parser. Because Fatal Error for undefined method call is not due to implementation of API methods, its due to calling for methods that does not exist or you PHP parser is unable to locate.
For reference this might be helpful
http://hotexamples.com/examples/-/Google_Service_Drive_Permission/setValue/php-google_service_drive_permission-setvalue-method-examples.html
I had the same problem and wasn't able to figure it out using Google API PHP Client methods designed specifically for altering permissions. However, there is a possibility to retrieve a Guzzle instance with the authentication info from PHP Client. Therefore, we can simply call the desired API endpoint to send the request. The code below is a complete workaround for changing file owner/permission on Google Drive:
//if you're using Service Account, otherwise follow your normal authorization
putenv('GOOGLE_APPLICATION_CREDENTIALS=/path/to/json');
$client = new Google_Client();
$client->setScopes(Google_Service_Drive::DRIVE);
$client->useApplicationDefaultCredentials();
//Now the main code to change the file permission begins
$httpClient = $client->authorize(); //It returns a Guzzle instance with proper Headers
$result = $httpClient->request('POST', 'https://www.googleapis.com/drive/v3/files/[FILE_ID]/permissions?transferOwnership=true', [
'json' => [
'role' => 'owner',
'type' => 'user',
'emailAddress' => 'email#example.com'
]
]);
And the sample response of $result->getBody()->getContents() is:
{
"kind": "drive#permission",
"id": "14...",
"type": "user",
"role": "owner"
}
I think you're on the wrong API. Setting permission for files are found in Drive API permissions.
But to answer your question, here's how to create a new spreadsheet using spreadsheets.create from the Sheets API:
<?php
/*
* BEFORE RUNNING:
* ---------------
* 1. If not already done, enable the Google Sheets API
* and check the quota for your project at
* https://console.developers.google.com/apis/api/sheets
* 2. Install the PHP client library with Composer. Check installation
* instructions at https://github.com/google/google-api-php-client.
*/
// Autoload Composer.
require_once __DIR__ . '/vendor/autoload.php';
$client = getClient();
$service = new Google_Service_Sheets($client);
// TODO: Assign values to desired properties of `requestBody`:
$requestBody = new Google_Service_Sheets_Spreadsheet();
$response = $service->spreadsheets->create($requestBody);
// TODO: Change code below to process the `response` object:
echo '<pre>', var_export($response, true), '</pre>', "\n";
function getClient() {
// TODO: Change placeholder below to generate authentication credentials. See
// https://developers.google.com/sheets/quickstart/php#step_3_set_up_the_sample
//
// Authorize using one of the following scopes:
// 'https://www.googleapis.com/auth/drive'
// 'https://www.googleapis.com/auth/spreadsheets'
return null;
}
?>
When the files has been created and saved in your Google Drive, you can now try to set Permissions using the Drive REST API.

Symfony2 - Error on prod - Cannot use object of type Symfony\Component\HttpFoundation\Request as array

I have just uploaded my Symfony (2.7) project online and I have a 500 error happening only online in prod environnement (app.php). I have set $kernel = new AppKernel('prod', true); in app.php file in order to see the error message:
Error: Cannot use object of type Symfony\Component\HttpFoundation\Request as array
in vendor/symfony/symfony/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php at line 143
}
if (null !== $this->logger) {
// Below is line 143
$this->logger->info(sprintf('Matched route "%s".', isset($parameters['_route']) ? $parameters['_route'] : 'n/a'), array(
'route_parameters' => $parameters,
'request_uri' => $request->getUri(),
));
(This file is part of Symfony, see complete code here.)
In local (WAMP), I have no issue using app.php or app_dev.php .
Online, app_dev.php is working well but when try to access http://mydomain.fr/web/, I have this error.
I am a bit lost here, if you need more information, just ask me which file or else I should copy in this question.
Just to see what happens I commented the logger line in RouterListener.php, I have another different error showing. I guess there's something wrong with my server's config or something like that... but I have no idea what I should look at.
Some controller code is trying to access values by keys on an object as if it were an Array;
<?php
$moo = (object) ['foo' => 'bar' ];
/* run-time error below: */
$moo['foo'];
This happens when you upgrade "the library" or API without updating client code. It happens also when client code (your code) confuses the order of parameters in function invocations.

Listing objects filtered by prefix in AWS with PHP SDK

I recently got the task to manage data which is stored via the Amazone Web Service.
According to the docu of Amazone i tried the following code to list all Objects within a bucket and it works fine:
$aws = Aws::factory('/path/to/my/config.php');
$s3 = $aws->get('s3');
$it = $s3->getIterator('ListObjects', array (
'Bucket' => 'myBucket',
)
);
foreach($it as $o){
echo $o['Key']."<br />";
}
But i need to list all objects only with a certain prefix. To achieve this i added the following line below line 6 of the shown code:
'prefix' => 'myPrefix/',
(The actual key of the file i want to access is (scheme):
myPrefix/subPrefix/subPrefix2/file.txt)
But the code keeps returning all objects in the bucket.
I havn't found any helpfull hints in the Amazon docu for my question.
Can anyone tell me (one of) the correct syntax to list all objects of a given prefix in PHP?
thank you in advance for any help
According to the following thread ...
List objects in a specific folder on Amazon S3
... you need capitalized the index-values of the array that is passed as second argument to the getIterator-function:
'Prefix' => 'myPrefix/',

Categories