diff --git a/.doc_gen/metadata/ec2_metadata.yaml b/.doc_gen/metadata/ec2_metadata.yaml index 80bbcf8e77b..a87ade2f2e8 100644 --- a/.doc_gen/metadata/ec2_metadata.yaml +++ b/.doc_gen/metadata/ec2_metadata.yaml @@ -1570,6 +1570,19 @@ ec2_DescribeInstances: - aws-cli.bash-linux.ec2.aws_cli_error_log services: ec2: {DescribeInstances} +ec2_DescribeRouteTables: + languages: + PHP: + versions: + - sdk_version: 3 + github: php/example_code/ec2 + sdkguide: + excerpts: + - description: + snippet_tags: + - php.example_code.ec2.service.describeRouteTables + services: + ec2: {DescribeRouteTables} ec2_DescribeRegions: languages: Rust: @@ -1971,6 +1984,16 @@ ec2_CreateSubnet: ec2: {CreateSubnet} ec2_CreateVpc: languages: + PHP: + versions: + - sdk_version: 3 + github: php/example_code/ec2 + sdkguide: + excerpts: + - description: + snippet_tags: + - php.example_code.ec2.service.createVpc + Ruby: versions: - sdk_version: 3 @@ -1982,6 +2005,45 @@ ec2_CreateVpc: - ec2.Ruby.createVpc services: ec2: {CreateVpc} +ec2_DeleteVpc: + languages: + PHP: + versions: + - sdk_version: 3 + github: php/example_code/ec2 + sdkguide: + excerpts: + - description: + snippet_tags: + - php.example_code.ec2.service.deleteVpc + services: + ec2: {DeleteVpc} +ec2_CreateVpcEndpoint: + languages: + PHP: + versions: + - sdk_version: 3 + github: php/example_code/ec2 + sdkguide: + excerpts: + - description: + snippet_tags: + - php.example_code.ec2.service.createVpcEndpoint + services: + ec2: {CreateVpcEndpoint} +ec2_DeleteVpcEndpoint: + languages: + PHP: + versions: + - sdk_version: 3 + github: php/example_code/ec2 + sdkguide: + excerpts: + - description: + snippet_tags: + - php.example_code.ec2.service.deleteVpcEndpoint + services: + ec2: {DeleteVpcEndpoint} ec2_DescribeIamInstanceProfileAssociations: languages: .NET: diff --git a/.doc_gen/metadata/s3_metadata.yaml b/.doc_gen/metadata/s3_metadata.yaml index 0f338f89847..34c553b92b6 100644 --- a/.doc_gen/metadata/s3_metadata.yaml +++ b/.doc_gen/metadata/s3_metadata.yaml @@ -434,6 +434,15 @@ s3_DeleteObject: snippet_tags: - gov2.workflows.s3.ObjectLock.S3Actions.struct - gov2.workflows.s3.ObjectLock.DeleteObject + PHP: + versions: + - sdk_version: 3 + github: php/example_code/s3 + sdkguide: + excerpts: + - description: + snippet_tags: + - php.example_code.s3.service.deleteObject Python: versions: - sdk_version: 3 @@ -3458,3 +3467,29 @@ s3_Scenario_DeleteAllObjects: - javascriptv3/example_code/s3/scenarios/delete-all-objects.js services: s3: {DeleteObjects, ListObjectsV2} +s3_Scenario_ExpressBasics: + title: Learn the basics of Amazon S3 Express One Zone with an &AWS; SDK + title_abbrev: Learn the basics of S3 Express One Zone + synopsis_list: + - Set up a VPC and VPC Endpoint + - Set up the S3 Express Policies, Roles, and User to work with S3 Express buckets + - Create two S3 Clients + - Create two buckets + - Create an object and copy it over + - Demonstrate performance difference + - Populate the buckets to show the lexicographical difference + - Prompt the user to see if they want to clean up the resources + category: Basics + languages: + PHP: + versions: + - sdk_version: 3 + github: php/example_code/s3 + sdkguide: + excerpts: + - description: + snippet_tags: + - php.example_code.s3.ExpressBasics + - php.example_code.s3.service.S3Service + services: + s3: {CreateVpc, DescribeRouteTables, CreateVpcEndpoint, CreateBucket, CopyObject, GetObject, PutObject, ListObjects, DeleteObject, DeleteBucket, DeleteVpcEndpoint, DeleteVpc} diff --git a/.gitignore b/.gitignore index 787544bc724..90d910d34d9 100644 --- a/.gitignore +++ b/.gitignore @@ -7,8 +7,9 @@ .idea *.iml .metadata -.phpunit.result.cache .recommenders +.phpunit.result.cache +.phpunit.cache .swiftpm .venv .vs @@ -34,4 +35,4 @@ rust_dev_preview kotlin/services/**/build/ kotlin/services/**/gradle/ kotlin/services/**/gradlew -kotlin/services/**/gradlew.bat \ No newline at end of file +kotlin/services/**/gradlew.bat diff --git a/basics_scenarios/s3express_scenario/README.md b/basics_scenarios/s3express_scenario/README.md new file mode 100644 index 00000000000..4ed2d3a7419 --- /dev/null +++ b/basics_scenarios/s3express_scenario/README.md @@ -0,0 +1,47 @@ +# Amazon S3 Batch Basics Scenario + +## Introduction +This scenario demonstrates how to use the AWS SDK to interact with S3 Express One Zone operations. + +## Setting up Resources +To successfully run this basic scenario, the program requires an IAM (Identity and Access Management) role. The program creates the IAM role by using an AWS CloudFormation template. + +## Service Operations Invoked +The program performs the following tasks: + +1. **Set up a VPC and VPC Endpoint**: + - EC2 Operation: `CreateVpc` + - EC2 Operation: `DescribeRouteTables` + - EC2 Operation: `CreateVpcEndpoint` + +2. **Set up the S3 Express Policies, Roles, and User to work with S3 Express buckets**: + - CDK Operation to load a CloudFormation template + +3. **Create *two* S3 Clients**: + - S3 instantiate client, once with elevated Express permissions + +4. **Create two buckets**: + - S3 Operation`CreateBucket` + +5. **Create an object and copy it over**: + - S3 Operation`CreateSession` + - S3 Operation`PutObject` + - S3 Operation`CopyObject` + +6. **Demonstrate performance difference**: + - S3 Operation`GetObject` + +7. **Populate the buckets to show the lexicographical difference**: + - S3 Operation `PutObject` + - S3 Operation `ListObjectsV2` + +8. **Prompt the user to see if they want to clean up the resources **: + - S3 Operation `DeleteObject` + - S3 Operation `DeleteBucket` + - EC2 Operation `DeleteVpcEndpoint` + - EC2 Operation `DeleteVpc` + +## Usage +1. Clone the repository or download the source code. +2. Open the code in your preferred IDE. +3. Invoke the main method in the `S3ExpressBasics` class. diff --git a/basics_scenarios/s3express_scenario/SPECIFICATION.md b/basics_scenarios/s3express_scenario/SPECIFICATION.md new file mode 100644 index 00000000000..0db48678eed --- /dev/null +++ b/basics_scenarios/s3express_scenario/SPECIFICATION.md @@ -0,0 +1,144 @@ +# S3 Express One Zone Basics Scenario Specification + +## Overview +This SDK Basics scenario demonstrates how to interact with S3 Express One Zone (S3 Express) using the AWS SDK. It demonstrates various tasks such as creating a Directory bucket, using sessions for fast connect times, and downloading objects. Finally this scenario demonstrates how to clean up resources. + +## Resources and User Input +This scenario requires a {bunch of stuff}. +This program is intended for users not familiar with S3 Express to easily get up and running. + +## Scenario Program Flow + +The S3 Express Basics scenario follows these steps: + +1. **Set up a VPC and VPC Endpoint**: + - Explain to the user that running this code locally will show a lower performance increase than running it on an EC2 instance in the same AZ as the Directory bucket. + - Prompt the user for whether they are running the code locally or on an EC2 instance. If they are running it locally, skip the rest of step 1. + - Using the EC2 Client, create a VPC. + - Get the Route Table for the VPC using `DescribeRouteTables`. + - Using the EC2 client, create a VPC Endpoint with the created VPC and set the Route Table. + - **Exception Handling**: There are no unique errors for these operations. + +2. **Set up the S3 Express Policies, Roles, and User to work with S3 Express buckets**: + - Create the policies, roles, and user. + - Use STS to assume the role and create S3 Express credentials. + - **Exception Handling**: Check for `InvalidArgumentException`. + +3. **Create *two* S3 Clients**: + - Create a regular S3 Client using normal methods. + - Create an S3 Client with the created credentials. + - **Exception Handling**: Check for `InvalidArgumentException`. + +4. **Create two buckets**: + - Create a regular S3 bucket with the normal S3 Client. + - Create a directory bucket *also using the normal S3 Client*. + - **Exception Handling**: Check for `BucketAlreadyExists`. + +5. **Create an object and copy it over**: + - Create a basic object with text in the normal S3 bucket with the normal client. + - Use CopyObject to copy the object from the normal bucket to the directory bucket, using the S3 Express client. + - **Exception Handling**: No relevant unique errors for this operation. + +6. **Demonstrate performance difference**: + - Use GetObject to download the object X (1000) times using the S3 Express client. Measure how long it takes. If possible in the language being used, run these in parallel. + - Use GetObject to download the object X (1000) times using the normal S3 client. Measure how long it takes. If possible in the language being used, run these in parallel. + - **Exception Handling**: Check for `NoSuchKey`. + +7. **Populate the buckets to show the lexicographical difference**: + - In both buckets, add: + - `other/objectkey`, `alt/objectkey`, `other/alt/objectkey` + - Use `ListObjects` for each bucket and show the difference in ordering. + - **Exception Handling**: Check for `NoSuchBucket`. + +8. **Prompt the user to see if they want to clean up the resources**: + - **Description**: If the user chose to do so, clean up relevant resources. Let the user know if any resources could not be deleted. + - **Exception Handling**: Any relevant errors related to resource deletion. + +### Program execution +The following shows the output of the Amazon S3 Batch program in the console. + +``` +-------------------------------------- +Welcome to the Amazon S3 Express Basics demo using PHP! +-------------------------------------- +Let's get started! First, please not that S3 Express One Zone works best when working within the AWS infrastructure, +specifically when working in the same Availability Zone. To see the best results in this example, and when you implement +Directory buckets into your infrastructure, it is best to put your Compute resources in the same AZ as your Directory +bucket. + +1. First, we'll set up a new VPC and VPC Endpoint if this program is running in an EC2 instance in the same AZ as your Directory buckets will be. +Skipping the VPC setup. Don't forget to use this in production! + +2. Policies, users, and roles with CDK. +Now, we'll set up some policies, roles, and a user. This user will only have permissions to do S3 Express One Zone actions. + +3. Create an additional client using the credentials with S3 Express permissions. +This client is created with the credentials associated with the user account with the S3 Express policy attached, so it can perform S3 Express operations. +All the roles and policies were created an attached to the user. Then, a new S3 Client and Service were created using that user's credentials. +We can now use this client to make calls to S3 Express operations. Keeping permissions in mind (and adhering to least-privilege) is crucial to S3 Express. + +3. Create two buckets. +Now we will create a Directory bucket, which is the linchpin of the S3 Express One Zone service. +Directory buckets behave in different ways from regular S3 buckets, which we will explore here. +We'll also create a normal bucket, put an object into the normal bucket, and copy it over to the Directory bucket. +Now, let's create the actual Directory bucket, as well as a regular bucket. +Great! Both buckets were created. + +5. Create an object and copy it over. +We'll create a basic object consisting of some text and upload it to the normal bucket. +Next, we'll copy the object into the Directory bucket using the regular client. +This works fine, because Copy operations are not restricted for Directory buckets. +It worked! It's important to remember the user permissions when interacting with Directory buckets. +Instead of validating permissions on every call as normal buckets do, Directory buckets utilize the user credentials and session token to validate. +This allows for much faster connection speeds on every call. For single calls, this is low, but for many concurrent calls, this adds up to a lot of time saved. + +6. Demonstrate performance difference. +Now, let's do a performance test. We'll download the same object from each bucket 1000 times and compare the total time needed. Note: the performance difference will be much more pronounced if this example is run in an EC2 instance in the same AZ as the bucket. +The directory bucket took 2464126625 nanoseconds, while the normal bucket took 1989507125. +That's a difference of -474619500 nanoseconds, or -0.4746195 seconds. + +7. Populate the buckets to show the lexicographical difference. +Now let's explore how Directory buckets store objects in a different manner to regular buckets. +The key is in the name "Directory!" +Where regular buckets store their key/value pairs in a flat manner, Directory buckets use actual directories/folders. +This allows for more rapid indexing, traversing, and therefore retrieval times! +The more segmented your bucket is, with lots of directories, sub-directories, and objects, the more efficient it becomes. +This structural difference also causes ListObjects to behave differently, which can cause unexpected results. +Let's add a few more objects with layered directories as see how the output of ListObjects changes. +Directory bucket content +other/basic-text-object +other/alt/basic-text-object +basic-text-object +alt/basic-text-object + +Normal bucket content +alt/basic-text-object +basic-text-object +other/alt/basic-text-object +other/basic-text-object +Notice how the normal bucket lists objects in lexicographical order, while the directory bucket does not. This is because the normal bucket considers the whole "key" to be the object identifies, while the directory bucket actually creates directories and uses the object "key" as a path to the object. + +That's it for our tour of the basic operations for S3 Express One Zone. + +``` + +## SOS Tags + +The following table describes the metadata used in this SDK Getting Started Scenario. + + +| action | metadata file | metadata key | +|--------------------------------|--------------------------------|------------------------------------------| +| `CreateVpc` | ec2_metadata.yml | ec2_CreateVpc | +| `DescribeRouteTables` | ec2_metadata.yml | ec2_DescribeRouteTables | +| `CreateVpcEndpoint` | ec2_metadata.yml | ec2_CreateVpcEndpoint | +| `CreateBucket` | s3_metadata.yml | s3_CreateBucket | +| `CopyObject` | s3_metadata.yml | s3_CopyObject | +| `GetObject` | s3_metadata.yml | s3_GetObject | +| `PutObject` | s3_metadata.yml | s3_PutObject | +| `ListObjects` | s3_metadata.yml | s3_ListObjectsV2 | +| `DeleteObject` | s3_metadata.yml | s3_DeleteObject | +| `DeleteBucket` | s3_metadata.yml | s3_DeleteBucket | +| `DeleteVpcEndpoint` | ec2_metadata.yml | ec2_DeleteVpcEndpoint | +| `DeleteVpc` | ec2_metadata.yml | ec2_DeleteVpc | +| ------------------------------ | ------------------------------ | ---------------------------------------- | diff --git a/php/example_code/aws_utilities/TestableReadline.php b/php/example_code/aws_utilities/TestableReadline.php index edd41b6f4a9..f6773610174 100644 --- a/php/example_code/aws_utilities/TestableReadline.php +++ b/php/example_code/aws_utilities/TestableReadline.php @@ -25,6 +25,11 @@ function testable_readline($prompt) return readline($prompt); } +// This is a helper function which makes it easy to ask the user to press enter to continue. +function pressEnter(){ + testable_readline("Press enter to continue.\n"); +} + trait TestableReadline { function testable_readline($prompt) { diff --git a/php/example_code/composer.json b/php/example_code/composer.json index 343855fadb7..8d22c1e064d 100644 --- a/php/example_code/composer.json +++ b/php/example_code/composer.json @@ -21,6 +21,7 @@ "DynamoDb\\": "dynamodb/", "DynamoDb\\Basics\\": "dynamodb/dynamodb_basics", "DynamoDb\\PartiQL_Basics\\": "dynamodb/partiql_basics", + "Ec2\\": "ec2/", "Glue\\": "glue/", "Iam\\": "iam/", "Kms\\": "kms/", diff --git a/php/example_code/composer.lock b/php/example_code/composer.lock index 80539362eac..8a8d6099e10 100644 --- a/php/example_code/composer.lock +++ b/php/example_code/composer.lock @@ -62,16 +62,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.323.1", + "version": "3.323.2", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "1b393c41a73e1ef4c493c60c5eee0bb4b0632264" + "reference": "030b93340f0e7d6fd20276037087d3eab8f16575" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/1b393c41a73e1ef4c493c60c5eee0bb4b0632264", - "reference": "1b393c41a73e1ef4c493c60c5eee0bb4b0632264", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/030b93340f0e7d6fd20276037087d3eab8f16575", + "reference": "030b93340f0e7d6fd20276037087d3eab8f16575", "shasum": "" }, "require": { @@ -154,9 +154,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.323.1" + "source": "https://github.com/aws/aws-sdk-php/tree/3.323.2" }, - "time": "2024-10-04T18:07:17+00:00" + "time": "2024-10-07T18:11:24+00:00" }, { "name": "guzzlehttp/guzzle", diff --git a/php/example_code/ec2/EC2Service.php b/php/example_code/ec2/EC2Service.php new file mode 100644 index 00000000000..859705ae47e --- /dev/null +++ b/php/example_code/ec2/EC2Service.php @@ -0,0 +1,137 @@ +region; + } + + public function __construct($client = null, $region = 'us-west-2', $version = 'latest', $profile = 'default') + { + if (gettype($client) == Ec2Client::class) { + $this->ec2Client = $client; + return; + } + $this->ec2Client = new Ec2Client([ + 'region' => $region, + 'version' => $version, + 'profile' => $profile, + ]); + $this->region = $region; + /* Inline declaration example + // snippet-start:[php.example_code.ec2.basics.createClient] + $ec2Client = new Ec2Client(['region' => 'us-west-2', 'version' => 'latest', 'profile' => 'default']); + // snippet-end:[php.example_code.ec2.basics.createClient] + */ + } + + // snippet-start:[php.example_code.ec2.service.createVpcEndpoint] + + /** + * @param string $serviceName + * @param string $vpcId + * @param array $routeTableIds + * @return array + */ + public function createVpcEndpoint(string $serviceName, string $vpcId, array $routeTableIds): array + { + $result = $this->ec2Client->createVpcEndpoint([ + 'ServiceName' => $serviceName, + 'VpcId' => $vpcId, + 'RouteTableIds' => $routeTableIds, + ]); + + return $result["VpcEndpoint"]; + } + + // snippet-end:[php.example_code.ec2.service.createVpcEndpoint] + + // snippet-start:[php.example_code.ec2.service.createVpc] + + public function createVpc($cidr) + { + $result = $this->ec2Client->createVpc([ + "CidrBlock" => $cidr, + ]); + return $result['Vpc']; + } + + // snippet-end:[php.example_code.ec2.service.createVpc] + + // snippet-start:[php.example_code.ec2.service.deleteVpc] + + public function deleteVpc(mixed $vpcId) + { + $result = $this->ec2Client->deleteVpc([ + "VpcId" => $vpcId, + ]); + } + + // snippet-end:[php.example_code.ec2.service.deleteVpc] + + // snippet-start:[php.example_code.ec2.service.deleteVpcEndpoint] + + public function deleteVpcEndpoint(mixed $vpcEndpointId) + { + $result = $this->ec2Client->deleteVpcEndpoints([ + "VpcEndpointIds" => [$vpcEndpointId], + ]); + } + + // snippet-end:[php.example_code.ec2.service.deleteVpcEndpoint] + + // snippet-start:[php.example_code.ec2.service.describeRouteTables] + + public function describeRouteTables(array $routeTableIds = [], array $filters = []) + { + $parameters = []; + if($routeTableIds){ + $parameters['RouteTableIds'] = $routeTableIds; + } + if($filters){ + $parameters['Filters'] = $filters; + } + try { + $paginator = $this->ec2Client->getPaginator("DescribeRouteTables", $parameters); + $contents = []; + foreach ($paginator as $result) { + foreach ($result['RouteTables'] as $object) { + $contents[] = $object['RouteTableId']; + } + } + }catch (Ec2Exception $caught){ + echo "There was a problem paginating the results of DescribeRouteTables: {$caught->getAwsErrorMessage()}\n"; + throw $caught; + } + return $contents; + } + + // snippet-end:[php.example_code.ec2.service.describeRouteTables] + + // snippet-start:[php.example_code.ec2.service.waitForVpcAvailable] + + public function waitForVpcAvailable(string $VpcId) + { + + $waiter = $this->ec2Client->getWaiter("VpcAvailable", [ + 'VpcIds' => [$VpcId], + ]); + + $promise = $waiter->promise(); + $promise->wait(); + + } + + // snippet-end:[php.example_code.ec2.service.waitForVpcAvailable] +} diff --git a/php/example_code/ec2/README.md b/php/example_code/ec2/README.md index c8924c93c10..5f9b5e74c7b 100644 --- a/php/example_code/ec2/README.md +++ b/php/example_code/ec2/README.md @@ -29,6 +29,17 @@ For prerequisites, see the [README](../../README.md#Prerequisites) in the `php` +### Single actions + +Code excerpts that show you how to call individual service functions. + +- [CreateVpc](EC2Service.php#L60) +- [CreateVpcEndpoint](EC2Service.php#L39) +- [DeleteVpc](EC2Service.php#L72) +- [DeleteVpcEndpoint](EC2Service.php#L83) +- [DescribeRouteTables](EC2Service.php#L94) + + diff --git a/php/example_code/ec2/composer.json b/php/example_code/ec2/composer.json new file mode 100644 index 00000000000..3512259df8b --- /dev/null +++ b/php/example_code/ec2/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "aws/aws-sdk-php": "^3.323" + } +} diff --git a/php/example_code/ec2/composer.lock b/php/example_code/ec2/composer.lock new file mode 100644 index 00000000000..885ab3e5aac --- /dev/null +++ b/php/example_code/ec2/composer.lock @@ -0,0 +1,913 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "539b45e062c60b0a7f400727c1362c5d", + "packages": [ + { + "name": "aws/aws-crt-php", + "version": "v1.2.6", + "source": { + "type": "git", + "url": "https://github.com/awslabs/aws-crt-php.git", + "reference": "a63485b65b6b3367039306496d49737cf1995408" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/a63485b65b6b3367039306496d49737cf1995408", + "reference": "a63485b65b6b3367039306496d49737cf1995408", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35||^5.6.3||^9.5", + "yoast/phpunit-polyfills": "^1.0" + }, + "suggest": { + "ext-awscrt": "Make sure you install awscrt native extension to use any of the functionality." + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "AWS SDK Common Runtime Team", + "email": "aws-sdk-common-runtime@amazon.com" + } + ], + "description": "AWS Common Runtime for PHP", + "homepage": "https://github.com/awslabs/aws-crt-php", + "keywords": [ + "amazon", + "aws", + "crt", + "sdk" + ], + "support": { + "issues": "https://github.com/awslabs/aws-crt-php/issues", + "source": "https://github.com/awslabs/aws-crt-php/tree/v1.2.6" + }, + "time": "2024-06-13T17:21:28+00:00" + }, + { + "name": "aws/aws-sdk-php", + "version": "3.323.2", + "source": { + "type": "git", + "url": "https://github.com/aws/aws-sdk-php.git", + "reference": "030b93340f0e7d6fd20276037087d3eab8f16575" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/030b93340f0e7d6fd20276037087d3eab8f16575", + "reference": "030b93340f0e7d6fd20276037087d3eab8f16575", + "shasum": "" + }, + "require": { + "aws/aws-crt-php": "^1.2.3", + "ext-json": "*", + "ext-pcre": "*", + "ext-simplexml": "*", + "guzzlehttp/guzzle": "^6.5.8 || ^7.4.5", + "guzzlehttp/promises": "^1.4.0 || ^2.0", + "guzzlehttp/psr7": "^1.9.1 || ^2.4.5", + "mtdowling/jmespath.php": "^2.6", + "php": ">=7.2.5", + "psr/http-message": "^1.0 || ^2.0" + }, + "require-dev": { + "andrewsville/php-token-reflection": "^1.4", + "aws/aws-php-sns-message-validator": "~1.0", + "behat/behat": "~3.0", + "composer/composer": "^1.10.22", + "dms/phpunit-arraysubset-asserts": "^0.4.0", + "doctrine/cache": "~1.4", + "ext-dom": "*", + "ext-openssl": "*", + "ext-pcntl": "*", + "ext-sockets": "*", + "nette/neon": "^2.3", + "paragonie/random_compat": ">= 2", + "phpunit/phpunit": "^5.6.3 || ^8.5 || ^9.5", + "psr/cache": "^1.0", + "psr/simple-cache": "^1.0", + "sebastian/comparator": "^1.2.3 || ^4.0", + "yoast/phpunit-polyfills": "^1.0" + }, + "suggest": { + "aws/aws-php-sns-message-validator": "To validate incoming SNS notifications", + "doctrine/cache": "To use the DoctrineCacheAdapter", + "ext-curl": "To send requests using cURL", + "ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages", + "ext-sockets": "To use client-side monitoring" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Aws\\": "src/" + }, + "exclude-from-classmap": [ + "src/data/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Amazon Web Services", + "homepage": "http://aws.amazon.com" + } + ], + "description": "AWS SDK for PHP - Use Amazon Web Services in your PHP project", + "homepage": "http://aws.amazon.com/sdkforphp", + "keywords": [ + "amazon", + "aws", + "cloud", + "dynamodb", + "ec2", + "glacier", + "s3", + "sdk" + ], + "support": { + "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", + "issues": "https://github.com/aws/aws-sdk-php/issues", + "source": "https://github.com/aws/aws-sdk-php/tree/3.323.2" + }, + "time": "2024-10-07T18:11:24+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "7.9.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "d281ed313b989f213357e3be1a179f02196ac99b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/d281ed313b989f213357e3be1a179f02196ac99b", + "reference": "d281ed313b989f213357e3be1a179f02196ac99b", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.5.3 || ^2.0.3", + "guzzlehttp/psr7": "^2.7.0", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-curl": "*", + "guzzle/client-integration-tests": "3.0.2", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.39 || ^9.6.20", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.9.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "time": "2024-07-24T11:22:20+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "6ea8dd08867a2a42619d65c3deb2c0fcbf81c8f8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/6ea8dd08867a2a42619d65c3deb2c0fcbf81c8f8", + "reference": "6ea8dd08867a2a42619d65c3deb2c0fcbf81c8f8", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2024-07-18T10:29:17+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "2.7.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/a70f5c95fb43bc83f07c9c948baa0dc1829bf201", + "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "http-interop/http-factory-tests": "0.9.0", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.7.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2024-07-18T11:15:46+00:00" + }, + { + "name": "mtdowling/jmespath.php", + "version": "2.8.0", + "source": { + "type": "git", + "url": "https://github.com/jmespath/jmespath.php.git", + "reference": "a2a865e05d5f420b50cc2f85bb78d565db12a6bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/a2a865e05d5f420b50cc2f85bb78d565db12a6bc", + "reference": "a2a865e05d5f420b50cc2f85bb78d565db12a6bc", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "symfony/polyfill-mbstring": "^1.17" + }, + "require-dev": { + "composer/xdebug-handler": "^3.0.3", + "phpunit/phpunit": "^8.5.33" + }, + "bin": [ + "bin/jp.php" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "files": [ + "src/JmesPath.php" + ], + "psr-4": { + "JmesPath\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Declaratively specify how to extract elements from a JSON document", + "keywords": [ + "json", + "jsonpath" + ], + "support": { + "issues": "https://github.com/jmespath/jmespath.php/issues", + "source": "https://github.com/jmespath/jmespath.php/tree/2.8.0" + }, + "time": "2024-09-04T18:46:31+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client" + }, + "time": "2023-09-23T14:17:50+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory" + }, + "time": "2024-04-15T12:06:14+00:00" + }, + { + "name": "psr/http-message", + "version": "2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/2.0" + }, + "time": "2023-04-04T09:54:51+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "plugin-api-version": "2.6.0" +} diff --git a/php/example_code/iam/IAMService.php b/php/example_code/iam/IAMService.php index 9f76cf00866..e539ef81709 100644 --- a/php/example_code/iam/IAMService.php +++ b/php/example_code/iam/IAMService.php @@ -137,6 +137,11 @@ public function createUserPolicy(string $policyName, string $policyDocument, str # snippet-end:[php.example_code.iam.service.createUserPolicy] # snippet-start:[php.example_code.iam.service.createPolicy] + /** + * @param string $policyName + * @param string $policyDocument + * @return array + */ public function createPolicy(string $policyName, string $policyDocument) { $result = $this->customWaiter(function () use ($policyName, $policyDocument) { diff --git a/php/example_code/phpunit.xml b/php/example_code/phpunit.xml index 61e4a868cc5..81db3b294a1 100644 --- a/php/example_code/phpunit.xml +++ b/php/example_code/phpunit.xml @@ -8,10 +8,13 @@ failOnRisky="true" failOnWarning="true" verbose="true"> - - - kms/tests/KmsBasicsTests.php - + + + + + + + @@ -30,7 +33,7 @@ - + @@ -41,6 +44,7 @@ lambda auto-scaling kms + s3 *vendor* diff --git a/php/example_code/s3/README.md b/php/example_code/s3/README.md index 0aab0cf066b..727fb3354fc 100644 --- a/php/example_code/s3/README.md +++ b/php/example_code/s3/README.md @@ -39,6 +39,7 @@ For prerequisites, see the [README](../../README.md#Prerequisites) in the `php` Code examples that show you how to perform the essential operations within a service. - [Learn the basics](GettingStartedWithS3.php) +- [Learn the basics of S3 Express One Zone](S3ExpressBasics.php) ### Single actions @@ -48,6 +49,7 @@ Code excerpts that show you how to call individual service functions. - [CopyObject](GettingStartedWithS3.php#L104) - [CreateBucket](GettingStartedWithS3.php#L61) - [DeleteBucket](GettingStartedWithS3.php#L52) +- [DeleteObject](S3Service.php#L258) - [DeleteObjects](GettingStartedWithS3.php#L52) - [GetObject](GettingStartedWithS3.php#L52) - [ListObjectsV2](GettingStartedWithS3.php#L52) @@ -95,6 +97,26 @@ This example shows you how to do the following: +#### Learn the basics of S3 Express One Zone + +This example shows you how to do the following: + +- Set up a VPC and VPC Endpoint +- Set up the S3 Express Policies, Roles, and User to work with S3 Express buckets +- Create two S3 Clients +- Create two buckets +- Create an object and copy it over +- Demonstrate performance difference +- Populate the buckets to show the lexicographical difference +- Prompt the user to see if they want to clean up the resources + + + + + + + + #### Create a presigned URL diff --git a/php/example_code/s3/Runner.php b/php/example_code/s3/Runner.php index 04e18dafec9..1db7a32ce55 100644 --- a/php/example_code/s3/Runner.php +++ b/php/example_code/s3/Runner.php @@ -7,7 +7,7 @@ use Aws\Exception\AwsException; use AwsUtilities\RunnableExample; -require __DIR__ . "/vendor/autoload.php"; +require_once __DIR__ . "/vendor/autoload.php"; require "GettingStartedWithS3.php"; diff --git a/php/example_code/s3/S3ExpressBasics.php b/php/example_code/s3/S3ExpressBasics.php new file mode 100644 index 00000000000..8015dc01729 --- /dev/null +++ b/php/example_code/s3/S3ExpressBasics.php @@ -0,0 +1,374 @@ +s3Service = new S3Service(new S3Client(['region' => $region])); + $this->iamService = new IAMService(new IamClient(['region' => $region])); + + $uuid = uniqid(); + + echo <<ec2Service = new EC2Service(new Ec2Client(['region' => $region])); + $cidr = "10.0.0.0/16"; + $vpc = $this->ec2Service->createVpc($cidr); + $this->resources['vpcId'] = $vpc['VpcId']; + + $this->ec2Service->waitForVpcAvailable($vpc['VpcId']); + + $routeTable = $this->ec2Service->describeRouteTables([], [ + [ + 'Name' => "vpc-id", + 'Values' => [$vpc['VpcId']], + ], + ]); + + $serviceName = "com.amazonaws." . $this->ec2Service->getRegion() . ".s3express"; + $vpcEndpoint = $this->ec2Service->createVpcEndpoint($serviceName, $vpc['VpcId'], [$routeTable[0]]); + $this->resources['vpcEndpointId'] = $vpcEndpoint['VpcEndpointId']; + }else{ + echo "Skipping the VPC setup. Don't forget to use this in production!\n"; + } + + // 2. Policies, user, and roles with CDK. + echo "\n"; + echo "2. Policies, users, and roles with CDK.\n"; + echo "Now, we'll set up some policies, roles, and a user. This user will only have permissions to do S3 Express One Zone actions.\n"; + pressEnter(); + + $this->cloudFormationClient = new CloudFormationClient([]); + $stackName = "cfn-stack-s3-express-basics-" . uniqid(); + $file = file_get_contents(__DIR__ . "/../../../resources/cfn/s3_express_basics/s3_express_template.yml"); + $result = $this->cloudFormationClient->createStack([ + 'StackName' => $stackName, + 'TemplateBody' => $file, + 'Capabilities' => ['CAPABILITY_IAM'], + ]); + $waiter = $this->cloudFormationClient->getWaiter("StackCreateComplete", ['StackName' => $stackName]); + try { + $waiter->promise()->wait(); + }catch(CloudFormationException $caught){ + echo "Error waiting for the CloudFormation stack to create: {$caught->getAwsErrorMessage()}\n"; + throw $caught; + } + $this->resources['StackName'] = $stackName; + $stackInfo = $this->cloudFormationClient->describeStacks([ + 'StackName' => $result['StackId'], + ]); + + $expressUserName = ""; + $regularUserName = ""; + foreach($stackInfo['Stacks'][0]['Outputs'] as $output) { + if ($output['OutputKey'] == "RegularUser") { + $regularUserName = $output['OutputValue']; + } + if ($output['OutputKey'] == "ExpressUser") { + $expressUserName = $output['OutputValue']; + } + } + $regularKey = $this->iamService->createAccessKey($regularUserName); + $regularCredentials = new Credentials($regularKey['AccessKeyId'], $regularKey['SecretAccessKey']); + $expressKey = $this->iamService->createAccessKey($expressUserName); + $expressCredentials = new Credentials($expressKey['AccessKeyId'], $expressKey['SecretAccessKey']); + + // 3. Create an additional client using the credentials with S3 Express permissions. + echo "\n"; + echo "3. Create an additional client using the credentials with S3 Express permissions.\n"; + echo "This client is created with the credentials associated with the user account with the S3 Express policy attached, so it can perform S3 Express operations.\n"; + pressEnter(); + $s3RegularClient = new S3Client([ + 'Region' => $region, + 'Credentials' => $regularCredentials, + ]); + $s3RegularService = new S3Service($s3RegularClient); + $s3ExpressClient = new S3Client([ + 'Region' => $region, + 'Credentials' => $expressCredentials, + ]); + $s3ExpressService = new S3Service($s3ExpressClient); + echo "All the roles and policies were created an attached to the user. Then, a new S3 Client and Service were created using that user's credentials.\n"; + echo "We can now use this client to make calls to S3 Express operations. Keeping permissions in mind (and adhering to least-privilege) is crucial to S3 Express.\n"; + pressEnter(); + + // 4. Create two buckets. + echo "\n"; + echo "3. Create two buckets.\n"; + echo "Now we will create a Directory bucket, which is the linchpin of the S3 Express One Zone service.\n"; + echo "Directory buckets behave in different ways from regular S3 buckets, which we will explore here.\n"; + echo "We'll also create a normal bucket, put an object into the normal bucket, and copy it over to the Directory bucket.\n"; + pressEnter(); + + // Create a directory bucket. These are different from normal S3 buckets in subtle ways. + $directoryBucketName = "s3-express-demo-directory-bucket-$uuid--$az--x-s3"; + echo "Now, let's create the actual Directory bucket, as well as a regular bucket.\n"; + pressEnter(); + $s3ExpressService->createBucket($directoryBucketName, [ + 'CreateBucketConfiguration' => [ + 'Bucket' => [ + 'Type' => "Directory", // This is what causes S3 to create a Directory bucket as opposed to a normal bucket. + 'DataRedundancy' => "SingleAvailabilityZone", + ], + 'Location' => [ + 'Name' => $az, + 'Type' => "AvailabilityZone", + ], + ], + ]); + $this->resources['directoryBucketName'] = $directoryBucketName; + + // Create a normal bucket. + $normalBucketName = "normal-bucket-$uuid"; + $s3RegularService->createBucket($normalBucketName); + $this->resources['normalBucketName'] = $normalBucketName; + echo "Great! Both buckets were created.\n"; + pressEnter(); + + // 5. Create an object and copy it over. + echo "\n"; + echo "5. Create an object and copy it over.\n"; + echo "We'll create a basic object consisting of some text and upload it to the normal bucket.\n"; + echo "Next, we'll copy the object into the Directory bucket using the regular client.\n"; + echo "This works fine, because Copy operations are not restricted for Directory buckets.\n"; + pressEnter(); + + $objectKey = "basic-text-object"; + $s3RegularService->putObject($normalBucketName, $objectKey, $args = ['Body' => "Look Ma, I'm a bucket!"]); + $this->resources['objectKey'] = $objectKey; + + // Create a session to access the directory bucket. The SDK Client will automatically refresh this as needed. + $s3ExpressService->createSession($directoryBucketName); + $s3ExpressService->copyObject($directoryBucketName, $objectKey, "$normalBucketName/$objectKey"); + + echo "It worked! It's important to remember the user permissions when interacting with Directory buckets.\n"; + echo "Instead of validating permissions on every call as normal buckets do, Directory buckets utilize the user credentials and session token to validate.\n"; + echo "This allows for much faster connection speeds on every call. For single calls, this is low, but for many concurrent calls, this adds up to a lot of time saved.\n"; + pressEnter(); + + // 6. Demonstrate performance difference. + echo "\n"; + echo "6. Demonstrate performance difference.\n"; + $downloads = 1000; + echo "Now, let's do a performance test. We'll download the same object from each bucket $downloads times and compare the total time needed. Note: the performance difference will be much more pronounced if this example is run in an EC2 instance in the same AZ as the bucket.\n"; + $downloadChoice = testable_readline("If you would like to download each object $downloads times, press enter. Otherwise, enter a custom amount and press enter."); + if($downloadChoice && is_numeric($downloadChoice) && $downloadChoice < 1000000){ // A million is enough. I promise. + $downloads = $downloadChoice; + } + + // Download the object $downloads times from each bucket and time it to demonstrate the speed difference. + $directoryStartTime = hrtime(true); + for($i = 0; $i < $downloads; ++$i){ + $s3ExpressService->getObject($directoryBucketName, $objectKey); + } + $directoryEndTime = hrtime(true); + $directoryTimeDiff = $directoryEndTime - $directoryStartTime; + + $normalStartTime = hrtime(true); + for($i = 0; $i < $downloads; ++$i){ + $s3RegularService->getObject($normalBucketName, $objectKey); + } + $normalEndTime = hrtime(true); + $normalTimeDiff = $normalEndTime - $normalStartTime; + + echo "The directory bucket took $directoryTimeDiff nanoseconds, while the normal bucket took $normalTimeDiff.\n"; + echo "That's a difference of " . ($normalTimeDiff - $directoryTimeDiff) . " nanoseconds, or " . (($normalTimeDiff - $directoryTimeDiff)/1000000000) . " seconds.\n"; + pressEnter(); + + // 7. Populate the buckets to show the lexicographical difference. + echo "\n"; + echo "7. Populate the buckets to show the lexicographical difference.\n"; + echo "Now let's explore how Directory buckets store objects in a different manner to regular buckets.\n"; + echo "The key is in the name \"Directory!\"\n"; + echo "Where regular buckets store their key/value pairs in a flat manner, Directory buckets use actual directories/folders.\n"; + echo "This allows for more rapid indexing, traversing, and therefore retrieval times!\n"; + echo "The more segmented your bucket is, with lots of directories, sub-directories, and objects, the more efficient it becomes.\n"; + echo "This structural difference also causes ListObjects to behave differently, which can cause unexpected results.\n"; + echo "Let's add a few more objects with layered directories as see how the output of ListObjects changes.\n"; + pressEnter(); + + // Populate a few more files in each bucket so that we can use ListObjects and show the difference. + $otherObject = "other/$objectKey"; + $altObject = "alt/$objectKey"; + $otherAltObject = "other/alt/$objectKey"; + $s3ExpressService->putObject($directoryBucketName, $otherObject); + $s3RegularService->putObject($normalBucketName, $otherObject); + $this->resources['otherObject'] = $otherObject; + $s3ExpressService->putObject($directoryBucketName, $altObject); + $s3RegularService->putObject($normalBucketName, $altObject); + $this->resources['altObject'] = $altObject; + $s3ExpressService->putObject($directoryBucketName, $otherAltObject); + $s3RegularService->putObject($normalBucketName, $otherAltObject); + $this->resources['otherAltObject'] = $otherAltObject; + + $listDirectoryBucket = $s3ExpressService->listObjects($directoryBucketName); + $listNormalBucket = $s3RegularService->listObjects($normalBucketName); + + // Directory bucket content + echo "Directory bucket content\n"; + foreach($listDirectoryBucket['Contents'] as $result){ + echo $result['Key'] . "\n"; + } + + // Normal bucket content + echo "\nNormal bucket content\n"; + foreach($listNormalBucket['Contents'] as $result){ + echo $result['Key'] . "\n"; + } + + echo "Notice how the normal bucket lists objects in lexicographical order, while the directory bucket does not. This is because the normal bucket considers the whole \"key\" to be the object identifies, while the directory bucket actually creates directories and uses the object \"key\" as a path to the object.\n"; + pressEnter(); + + echo "\n"; + echo "That's it for our tour of the basic operations for S3 Express One Zone.\n"; + $cleanUp = testable_readline("Would you like to delete all the resources created during this demo? Enter Y/y to delete all the resources."); + if($cleanUp){ + $this->cleanUp(); + } + + // snippet-end:[php.example_code.s3.ExpressBasics] + } + + public function helloService() + { + return; // There is no value in an S3 Express One Zone Hello Service, but the interface requires a definition. + } + + public function cleanUp() + { + if(isset($this->ec2Service)) { + // delete VpcEndpoint + $this->ec2Service->deleteVpcEndpoint($this->resources['vpcEndpointId']); + unset($this->resources['vpcEndpointId']); + + // delete Vpc + $this->ec2Service->deleteVpc($this->resources['vpcId']); + unset($this->resources['vpcId']); + } + + //delete the stack + if(isset($this->resources['StackName'])){ + $this->cloudFormationClient->deleteStack([ + 'StackName' => $this->resources['StackName'], + ]); + unset($this->resources['StackName']); + } + +// $this->iamService->deleteRole($this->resources['roleName']); +// unset($this->resources['roleName']); + + // delete User +// $this->iamService->deleteUser($this->resources['userName']); +// unset($this->resources['userName']); + + // delete all the objects in both buckets + if(isset($this->resources['objectKey'])){ + $this->s3Service->deleteObject($this->resources['directoryBucketName'], $this->resources['objectKey']); + $this->s3Service->deleteObject($this->resources['normalBucketName'], $this->resources['objectKey']); + unset($this->resources['objectKey']); + } + if(isset($this->resources['otherObject'])){ + $this->s3Service->deleteObject($this->resources['directoryBucketName'], $this->resources['otherObject']); + $this->s3Service->deleteObject($this->resources['normalBucketName'], $this->resources['otherObject']); + unset($this->resources['otherObject']); + } + if(isset($this->resources['altObject'])){ + $this->s3Service->deleteObject($this->resources['directoryBucketName'], $this->resources['altObject']); + $this->s3Service->deleteObject($this->resources['normalBucketName'], $this->resources['altObject']); + unset($this->resources['altObject']); + } + if(isset($this->resources['otherAltObject'])){ + $this->s3Service->deleteObject($this->resources['directoryBucketName'], $this->resources['otherAltObject']); + $this->s3Service->deleteObject($this->resources['normalBucketName'], $this->resources['otherAltObject']); + unset($this->resources['otherAltObject']); + } + + // delete the directory bucket + if(isset($this->resources['directoryBucketName'])){ + $this->s3Service->deleteBucket($this->resources['directoryBucketName']); + unset($this->resources['directoryBucketName']); + } + + // delete the normal bucket + if(isset($this->resources['normalBucketName'])){ + $this->s3Service->deleteBucket($this->resources['normalBucketName']); + unset($this->resources['normalBucketName']); + } + + if(count($this->resources) > 0){ + echo "There was a problem deleting some resources. The following keys are still set: \n"; + var_dump($this->resources); + } + + } +} diff --git a/php/example_code/s3/S3Service.php b/php/example_code/s3/S3Service.php index dc6c7b3f6e5..b9a4a8d65ef 100644 --- a/php/example_code/s3/S3Service.php +++ b/php/example_code/s3/S3Service.php @@ -2,11 +2,14 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 +// snippet-start:[php.example_code.s3.service.S3Service] + namespace S3; use Aws\CommandInterface; use Aws\Exception\AwsException; use Aws\Result; +use Aws\S3\Exception\S3Exception; use Aws\S3\S3Client; use AwsUtilities\AWSServiceClass; use DateTimeInterface; @@ -50,6 +53,7 @@ public function setClient(S3Client $client) } // snippet-start:[php.example_code.s3.service.emptyAndDeleteBucket] + public function emptyAndDeleteBucket($bucketName, array $args = []) { try { @@ -67,9 +71,11 @@ public function emptyAndDeleteBucket($bucketName, array $args = []) throw $exception; } } + // snippet-end:[php.example_code.s3.service.emptyAndDeleteBucket] // snippet-start:[php.example_code.s3.service.createBucket] + public function createBucket(string $bucketName, array $args = []) { $parameters = array_merge(['Bucket' => $bucketName], $args); @@ -86,9 +92,11 @@ public function createBucket(string $bucketName, array $args = []) throw $exception; } } + // snippet-end:[php.example_code.s3.service.createBucket] // snippet-start:[php.example_code.s3.service.putObject] + public function putObject(string $bucketName, string $key, array $args = []) { $parameters = array_merge(['Bucket' => $bucketName, 'Key' => $key], $args); @@ -105,9 +113,11 @@ public function putObject(string $bucketName, string $key, array $args = []) throw $exception; } } + // snippet-end:[php.example_code.s3.service.putObject] // snippet-start:[php.example_code.s3.service.getObject] + public function getObject(string $bucketName, string $key, array $args = []): Result { $parameters = array_merge(['Bucket' => $bucketName, 'Key' => $key], $args); @@ -125,9 +135,11 @@ public function getObject(string $bucketName, string $key, array $args = []): Re } return $object; } + // snippet-end:[php.example_code.s3.service.getObject] // snippet-start:[php.example_code.s3.service.copyObject] + public function copyObject($bucketName, $key, $copySource, array $args = []) { $parameters = array_merge(['Bucket' => $bucketName, 'Key' => $key, "CopySource" => $copySource], $args); @@ -144,9 +156,11 @@ public function copyObject($bucketName, $key, $copySource, array $args = []) throw $exception; } } + // snippet-end:[php.example_code.s3.service.copyObject] // snippet-start:[php.example_code.s3.service.listObjects] + public function listObjects(string $bucketName, $start = 0, $max = 1000, array $args = []) { $parameters = array_merge(['Bucket' => $bucketName, 'Marker' => $start, "MaxKeys" => $max], $args); @@ -164,25 +178,33 @@ public function listObjects(string $bucketName, $start = 0, $max = 1000, array $ } return $objects; } + // snippet-end:[php.example_code.s3.service.listObjects] // snippet-start:[php.example_code.s3.service.listAllObjects] + public function listAllObjects($bucketName, array $args = []) { $parameters = array_merge(['Bucket' => $bucketName], $args); $contents = []; $paginator = $this->client->getPaginator("ListObjectsV2", $parameters); + foreach ($paginator as $result) { - foreach ($result['Content'] as $object) { + if($result['KeyCount'] == 0){ + break; + } + foreach ($result['Contents'] as $object) { $contents[] = $object; } } return $contents; } + // snippet-end:[php.example_code.s3.service.listAllObjects] // snippet-start:[php.example_code.s3.service.deleteObjects] + public function deleteObjects(string $bucketName, array $objects, array $args = []) { $listOfObjects = array_map( @@ -191,6 +213,9 @@ function ($object) { }, array_column($objects, 'Key') ); + if(!$listOfObjects){ + return; + } $parameters = array_merge(['Bucket' => $bucketName, 'Delete' => ['Objects' => $listOfObjects]], $args); try { @@ -206,9 +231,11 @@ function ($object) { throw $exception; } } + // snippet-end:[php.example_code.s3.service.deleteObjects] // snippet-start:[php.example_code.s3.service.deleteBucket] + public function deleteBucket(string $bucketName, array $args = []) { $parameters = array_merge(['Bucket' => $bucketName], $args); @@ -225,9 +252,11 @@ public function deleteBucket(string $bucketName, array $args = []) throw $exception; } } + // snippet-end:[php.example_code.s3.service.deleteBucket] // snippet-start:[php.example_code.s3.service.deleteObject] + public function deleteObject(string $bucketName, string $fileName, array $args = []) { $parameters = array_merge(['Bucket' => $bucketName, 'Key' => $fileName], $args); @@ -244,9 +273,11 @@ public function deleteObject(string $bucketName, string $fileName, array $args = throw $exception; } } + // snippet-end:[php.example_code.s3.service.deleteObject] // snippet-start:[php.example_code.s3.service.listBuckets] + public function listBuckets(array $args = []) { try { @@ -263,9 +294,11 @@ public function listBuckets(array $args = []) } return $buckets; } + // snippet-end:[php.example_code.s3.service.listBuckets] // snippet-start:[php.example_code.s3.service.preSignedUrl] + public function preSignedUrl(CommandInterface $command, DateTimeInterface|int|string $expires, array $options = []) { $request = $this->client->createPresignedRequest($command, $expires, $options); @@ -280,5 +313,27 @@ public function preSignedUrl(CommandInterface $command, DateTimeInterface|int|st } return $presignedUrl; } + // snippet-end:[php.example_code.s3.service.preSignedUrl] + + // snippet-start:[php.example_code.s3.service.createSession] + + public function createSession(string $bucketName) + { + try{ + $result = $this->client->createSession([ + 'Bucket' => $bucketName, + ]); + return $result; + }catch(S3Exception $caught){ + if($caught->getAwsErrorType() == "NoSuchBucket"){ + echo "The specified bucket does not exist."; + } + throw $caught; + } + } + + // snippet-end:[php.example_code.s3.service.createSession] } + +// snippet-end:[php.example_code.s3.service.S3Service] diff --git a/php/example_code/s3/composer.json b/php/example_code/s3/composer.json index 5512dbefce8..b79a632501f 100644 --- a/php/example_code/s3/composer.json +++ b/php/example_code/s3/composer.json @@ -10,8 +10,11 @@ "": "*" }, "psr-4": { + "Ec2\\": "../ec2/", + "Iam\\": "../iam/", "S3\\": "../s3/", "AwsUtilities\\": "../aws_utilities/" - } + }, + "files": ["../aws_utilities/TestableReadline.php"] } } diff --git a/php/example_code/s3/composer.lock b/php/example_code/s3/composer.lock index cdf5b9266a5..b30c82f4d4b 100644 --- a/php/example_code/s3/composer.lock +++ b/php/example_code/s3/composer.lock @@ -8,16 +8,16 @@ "packages": [ { "name": "aws/aws-crt-php", - "version": "v1.2.4", + "version": "v1.2.6", "source": { "type": "git", "url": "https://github.com/awslabs/aws-crt-php.git", - "reference": "eb0c6e4e142224a10b08f49ebf87f32611d162b2" + "reference": "a63485b65b6b3367039306496d49737cf1995408" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/eb0c6e4e142224a10b08f49ebf87f32611d162b2", - "reference": "eb0c6e4e142224a10b08f49ebf87f32611d162b2", + "url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/a63485b65b6b3367039306496d49737cf1995408", + "reference": "a63485b65b6b3367039306496d49737cf1995408", "shasum": "" }, "require": { @@ -56,22 +56,22 @@ ], "support": { "issues": "https://github.com/awslabs/aws-crt-php/issues", - "source": "https://github.com/awslabs/aws-crt-php/tree/v1.2.4" + "source": "https://github.com/awslabs/aws-crt-php/tree/v1.2.6" }, - "time": "2023-11-08T00:42:13+00:00" + "time": "2024-06-13T17:21:28+00:00" }, { "name": "aws/aws-sdk-php", - "version": "3.295.6", + "version": "3.323.1", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "9b0b2daf46d5e6a4600575917cea0764e4dbb6b5" + "reference": "1b393c41a73e1ef4c493c60c5eee0bb4b0632264" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/9b0b2daf46d5e6a4600575917cea0764e4dbb6b5", - "reference": "9b0b2daf46d5e6a4600575917cea0764e4dbb6b5", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/1b393c41a73e1ef4c493c60c5eee0bb4b0632264", + "reference": "1b393c41a73e1ef4c493c60c5eee0bb4b0632264", "shasum": "" }, "require": { @@ -124,7 +124,10 @@ ], "psr-4": { "Aws\\": "src/" - } + }, + "exclude-from-classmap": [ + "src/data/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -151,9 +154,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.295.6" + "source": "https://github.com/aws/aws-sdk-php/tree/3.323.1" }, - "time": "2024-01-04T19:43:02+00:00" + "time": "2024-10-04T18:07:17+00:00" }, { "name": "doctrine/instantiator", @@ -227,22 +230,22 @@ }, { "name": "guzzlehttp/guzzle", - "version": "7.8.1", + "version": "7.9.2", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "41042bc7ab002487b876a0683fc8dce04ddce104" + "reference": "d281ed313b989f213357e3be1a179f02196ac99b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/41042bc7ab002487b876a0683fc8dce04ddce104", - "reference": "41042bc7ab002487b876a0683fc8dce04ddce104", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/d281ed313b989f213357e3be1a179f02196ac99b", + "reference": "d281ed313b989f213357e3be1a179f02196ac99b", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.5.3 || ^2.0.1", - "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", + "guzzlehttp/promises": "^1.5.3 || ^2.0.3", + "guzzlehttp/psr7": "^2.7.0", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.2 || ^3.0" @@ -253,9 +256,9 @@ "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "ext-curl": "*", - "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", + "guzzle/client-integration-tests": "3.0.2", "php-http/message-factory": "^1.1", - "phpunit/phpunit": "^8.5.36 || ^9.6.15", + "phpunit/phpunit": "^8.5.39 || ^9.6.20", "psr/log": "^1.1 || ^2.0 || ^3.0" }, "suggest": { @@ -333,7 +336,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.8.1" + "source": "https://github.com/guzzle/guzzle/tree/7.9.2" }, "funding": [ { @@ -349,20 +352,20 @@ "type": "tidelift" } ], - "time": "2023-12-03T20:35:24+00:00" + "time": "2024-07-24T11:22:20+00:00" }, { "name": "guzzlehttp/promises", - "version": "2.0.2", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223" + "reference": "6ea8dd08867a2a42619d65c3deb2c0fcbf81c8f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/bbff78d96034045e58e13dedd6ad91b5d1253223", - "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223", + "url": "https://api.github.com/repos/guzzle/promises/zipball/6ea8dd08867a2a42619d65c3deb2c0fcbf81c8f8", + "reference": "6ea8dd08867a2a42619d65c3deb2c0fcbf81c8f8", "shasum": "" }, "require": { @@ -370,7 +373,7 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.36 || ^9.6.15" + "phpunit/phpunit": "^8.5.39 || ^9.6.20" }, "type": "library", "extra": { @@ -416,7 +419,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.0.2" + "source": "https://github.com/guzzle/promises/tree/2.0.3" }, "funding": [ { @@ -432,20 +435,20 @@ "type": "tidelift" } ], - "time": "2023-12-03T20:19:20+00:00" + "time": "2024-07-18T10:29:17+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.6.2", + "version": "2.7.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221" + "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/45b30f99ac27b5ca93cb4831afe16285f57b8221", - "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/a70f5c95fb43bc83f07c9c948baa0dc1829bf201", + "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201", "shasum": "" }, "require": { @@ -460,8 +463,8 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "http-interop/http-factory-tests": "^0.9", - "phpunit/phpunit": "^8.5.36 || ^9.6.15" + "http-interop/http-factory-tests": "0.9.0", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" @@ -532,7 +535,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.6.2" + "source": "https://github.com/guzzle/psr7/tree/2.7.0" }, "funding": [ { @@ -548,20 +551,20 @@ "type": "tidelift" } ], - "time": "2023-12-03T20:05:35+00:00" + "time": "2024-07-18T11:15:46+00:00" }, { "name": "mtdowling/jmespath.php", - "version": "2.7.0", + "version": "2.8.0", "source": { "type": "git", "url": "https://github.com/jmespath/jmespath.php.git", - "reference": "bbb69a935c2cbb0c03d7f481a238027430f6440b" + "reference": "a2a865e05d5f420b50cc2f85bb78d565db12a6bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/bbb69a935c2cbb0c03d7f481a238027430f6440b", - "reference": "bbb69a935c2cbb0c03d7f481a238027430f6440b", + "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/a2a865e05d5f420b50cc2f85bb78d565db12a6bc", + "reference": "a2a865e05d5f420b50cc2f85bb78d565db12a6bc", "shasum": "" }, "require": { @@ -578,7 +581,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { @@ -612,22 +615,22 @@ ], "support": { "issues": "https://github.com/jmespath/jmespath.php/issues", - "source": "https://github.com/jmespath/jmespath.php/tree/2.7.0" + "source": "https://github.com/jmespath/jmespath.php/tree/2.8.0" }, - "time": "2023-08-25T10:54:48+00:00" + "time": "2024-09-04T18:46:31+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.11.1", + "version": "1.12.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", "shasum": "" }, "require": { @@ -635,11 +638,12 @@ }, "conflict": { "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3,<3.2.2" + "doctrine/common": "<2.13.3 || >=3 <3.2.2" }, "require-dev": { "doctrine/collections": "^1.6.8", "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", @@ -665,7 +669,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" }, "funding": [ { @@ -673,29 +677,31 @@ "type": "tidelift" } ], - "time": "2023-03-08T13:26:56+00:00" + "time": "2024-06-12T14:39:25+00:00" }, { "name": "nikic/php-parser", - "version": "v4.18.0", + "version": "v5.3.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999" + "reference": "3abf7425cd284141dc5d8d14a9ee444de3345d1a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1bcbb2179f97633e98bbbc87044ee2611c7d7999", - "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/3abf7425cd284141dc5d8d14a9ee444de3345d1a", + "reference": "3abf7425cd284141dc5d8d14a9ee444de3345d1a", "shasum": "" }, "require": { + "ext-ctype": "*", + "ext-json": "*", "ext-tokenizer": "*", - "php": ">=7.0" + "php": ">=7.4" }, "require-dev": { "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^9.0" }, "bin": [ "bin/php-parse" @@ -703,7 +709,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.9-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -727,26 +733,27 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.18.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.3.0" }, - "time": "2023-12-10T21:03:43+00:00" + "time": "2024-09-29T13:56:26+00:00" }, { "name": "phar-io/manifest", - "version": "2.0.3", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53" + "reference": "54750ef60c58e43759730615a392c31c80e23176" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", "shasum": "" }, "require": { "ext-dom": "*", + "ext-libxml": "*", "ext-phar": "*", "ext-xmlwriter": "*", "phar-io/version": "^3.0.1", @@ -787,9 +794,15 @@ "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", "support": { "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.3" + "source": "https://github.com/phar-io/manifest/tree/2.0.4" }, - "time": "2021-07-20T11:28:43+00:00" + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" }, { "name": "phar-io/version", @@ -844,35 +857,35 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.30", + "version": "9.2.32", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089" + "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ca2bd87d2f9215904682a9cb9bb37dda98e76089", - "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/85402a822d1ecf1db1096959413d35e1c37cf1a5", + "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.18 || ^5.0", + "nikic/php-parser": "^4.19.1 || ^5.1.0", "php": ">=7.3", - "phpunit/php-file-iterator": "^3.0.3", - "phpunit/php-text-template": "^2.0.2", - "sebastian/code-unit-reverse-lookup": "^2.0.2", - "sebastian/complexity": "^2.0", - "sebastian/environment": "^5.1.2", - "sebastian/lines-of-code": "^1.0.3", - "sebastian/version": "^3.0.1", - "theseer/tokenizer": "^1.2.0" + "phpunit/php-file-iterator": "^3.0.6", + "phpunit/php-text-template": "^2.0.4", + "sebastian/code-unit-reverse-lookup": "^2.0.3", + "sebastian/complexity": "^2.0.3", + "sebastian/environment": "^5.1.5", + "sebastian/lines-of-code": "^1.0.4", + "sebastian/version": "^3.0.2", + "theseer/tokenizer": "^1.2.3" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^9.6" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -881,7 +894,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.2-dev" + "dev-main": "9.2.x-dev" } }, "autoload": { @@ -910,7 +923,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.30" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.32" }, "funding": [ { @@ -918,7 +931,7 @@ "type": "github" } ], - "time": "2023-12-22T06:47:57+00:00" + "time": "2024-08-22T04:23:01+00:00" }, { "name": "phpunit/php-file-iterator", @@ -1163,45 +1176,45 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.15", + "version": "9.6.21", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "05017b80304e0eb3f31d90194a563fd53a6021f1" + "reference": "de6abf3b6f8dd955fac3caad3af7a9504e8c2ffa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/05017b80304e0eb3f31d90194a563fd53a6021f1", - "reference": "05017b80304e0eb3f31d90194a563fd53a6021f1", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/de6abf3b6f8dd955fac3caad3af7a9504e8c2ffa", + "reference": "de6abf3b6f8dd955fac3caad3af7a9504e8c2ffa", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1 || ^2", + "doctrine/instantiator": "^1.5.0 || ^2", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", + "myclabs/deep-copy": "^1.12.0", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.28", - "phpunit/php-file-iterator": "^3.0.5", + "phpunit/php-code-coverage": "^9.2.32", + "phpunit/php-file-iterator": "^3.0.6", "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.3", - "phpunit/php-timer": "^5.0.2", - "sebastian/cli-parser": "^1.0.1", - "sebastian/code-unit": "^1.0.6", + "phpunit/php-text-template": "^2.0.4", + "phpunit/php-timer": "^5.0.3", + "sebastian/cli-parser": "^1.0.2", + "sebastian/code-unit": "^1.0.8", "sebastian/comparator": "^4.0.8", - "sebastian/diff": "^4.0.3", - "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.5", - "sebastian/global-state": "^5.0.1", - "sebastian/object-enumerator": "^4.0.3", - "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^3.2", + "sebastian/diff": "^4.0.6", + "sebastian/environment": "^5.1.5", + "sebastian/exporter": "^4.0.6", + "sebastian/global-state": "^5.0.7", + "sebastian/object-enumerator": "^4.0.4", + "sebastian/resource-operations": "^3.0.4", + "sebastian/type": "^3.2.1", "sebastian/version": "^3.0.2" }, "suggest": { @@ -1246,7 +1259,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.15" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.21" }, "funding": [ { @@ -1262,7 +1275,7 @@ "type": "tidelift" } ], - "time": "2023-12-01T16:55:19+00:00" + "time": "2024-09-19T10:50:18+00:00" }, { "name": "psr/http-client", @@ -1318,20 +1331,20 @@ }, { "name": "psr/http-factory", - "version": "1.0.2", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-factory.git", - "reference": "e616d01114759c4c489f93b099585439f795fe35" + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", - "reference": "e616d01114759c4c489f93b099585439f795fe35", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", "shasum": "" }, "require": { - "php": ">=7.0.0", + "php": ">=7.1", "psr/http-message": "^1.0 || ^2.0" }, "type": "library", @@ -1355,7 +1368,7 @@ "homepage": "https://www.php-fig.org/" } ], - "description": "Common interfaces for PSR-7 HTTP message factories", + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", "keywords": [ "factory", "http", @@ -1367,9 +1380,9 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-factory/tree/1.0.2" + "source": "https://github.com/php-fig/http-factory" }, - "time": "2023-04-10T20:10:41+00:00" + "time": "2024-04-15T12:06:14+00:00" }, { "name": "psr/http-message", @@ -1470,16 +1483,16 @@ }, { "name": "sebastian/cli-parser", - "version": "1.0.1", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b", + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b", "shasum": "" }, "require": { @@ -1514,7 +1527,7 @@ "homepage": "https://github.com/sebastianbergmann/cli-parser", "support": { "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.2" }, "funding": [ { @@ -1522,7 +1535,7 @@ "type": "github" } ], - "time": "2020-09-28T06:08:49+00:00" + "time": "2024-03-02T06:27:43+00:00" }, { "name": "sebastian/code-unit", @@ -1768,16 +1781,16 @@ }, { "name": "sebastian/diff", - "version": "4.0.5", + "version": "4.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131" + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131", - "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc", + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc", "shasum": "" }, "require": { @@ -1822,7 +1835,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5" + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6" }, "funding": [ { @@ -1830,7 +1843,7 @@ "type": "github" } ], - "time": "2023-05-07T05:35:17+00:00" + "time": "2024-03-02T06:30:58+00:00" }, { "name": "sebastian/environment", @@ -1897,16 +1910,16 @@ }, { "name": "sebastian/exporter", - "version": "4.0.5", + "version": "4.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" + "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", - "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", + "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", "shasum": "" }, "require": { @@ -1962,7 +1975,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" }, "funding": [ { @@ -1970,20 +1983,20 @@ "type": "github" } ], - "time": "2022-09-14T06:03:37+00:00" + "time": "2024-03-02T06:33:00+00:00" }, { "name": "sebastian/global-state", - "version": "5.0.6", + "version": "5.0.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bde739e7565280bda77be70044ac1047bc007e34" + "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34", - "reference": "bde739e7565280bda77be70044ac1047bc007e34", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", + "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", "shasum": "" }, "require": { @@ -2026,7 +2039,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6" + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7" }, "funding": [ { @@ -2034,7 +2047,7 @@ "type": "github" } ], - "time": "2023-08-02T09:26:13+00:00" + "time": "2024-03-02T06:35:11+00:00" }, { "name": "sebastian/lines-of-code", @@ -2270,16 +2283,16 @@ }, { "name": "sebastian/resource-operations", - "version": "3.0.3", + "version": "3.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e", + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e", "shasum": "" }, "require": { @@ -2291,7 +2304,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -2312,8 +2325,7 @@ "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", "support": { - "issues": "https://github.com/sebastianbergmann/resource-operations/issues", - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4" }, "funding": [ { @@ -2321,7 +2333,7 @@ "type": "github" } ], - "time": "2020-09-28T06:45:17+00:00" + "time": "2024-03-14T16:00:52+00:00" }, { "name": "sebastian/type", @@ -2434,16 +2446,16 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.4.0", + "version": "v3.5.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", "shasum": "" }, "require": { @@ -2452,7 +2464,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -2481,7 +2493,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" }, "funding": [ { @@ -2497,24 +2509,24 @@ "type": "tidelift" } ], - "time": "2023-05-23T14:45:45+00:00" + "time": "2024-04-18T09:32:20+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.28.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "42292d99c55abe617799667f454222c54c60e229" + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", - "reference": "42292d99c55abe617799667f454222c54c60e229", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-mbstring": "*" @@ -2524,9 +2536,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -2564,7 +2573,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" }, "funding": [ { @@ -2580,20 +2589,20 @@ "type": "tidelift" } ], - "time": "2023-07-28T09:04:16+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "theseer/tokenizer", - "version": "1.2.2", + "version": "1.2.3", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96" + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96", - "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", "shasum": "" }, "require": { @@ -2622,7 +2631,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.2" + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" }, "funding": [ { @@ -2630,7 +2639,7 @@ "type": "github" } ], - "time": "2023-11-20T00:12:19+00:00" + "time": "2024-03-03T12:36:25+00:00" } ], "packages-dev": [], @@ -2641,5 +2650,5 @@ "prefer-lowest": false, "platform": [], "platform-dev": [], - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } diff --git a/php/example_code/s3/tests/S3ExpressBasicsTest.php b/php/example_code/s3/tests/S3ExpressBasicsTest.php new file mode 100644 index 00000000000..4db50ee7842 --- /dev/null +++ b/php/example_code/s3/tests/S3ExpressBasicsTest.php @@ -0,0 +1,57 @@ +runExample(); + self::assertTrue(true); // This asserts that we made it to this line with no exceptions thrown. + }catch(S3Exception $caught){ + echo "There was a problem running the tests: {$caught->getAwsErrorMessage()}\n"; + }finally{ + $start->cleanUp(); + } + } +} diff --git a/resources/cfn/s3_express_basics/s3_express_template.yml b/resources/cfn/s3_express_basics/s3_express_template.yml new file mode 100644 index 00000000000..450c1d1d1a9 --- /dev/null +++ b/resources/cfn/s3_express_basics/s3_express_template.yml @@ -0,0 +1,23 @@ +Resources: + RegularUser: + Type: AWS::IAM::User + ExpressUser: + Type: AWS::IAM::User + ExpressPolicy: + Type: AWS::IAM::Policy + Properties: + PolicyName: AllowExpressOperations + PolicyDocument: + Statement: + - Effect: Allow + Action: + - "s3express:CreateBucket" + - "s3express:CreateSession" + Resource: "*" + Users: + - !Ref ExpressUser +Outputs: + RegularUser: + Value: !Ref RegularUser + ExpressUser: + Value: !Ref ExpressUser