Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ services:
<<: *dev81
image: keboola/azure-api-client
working_dir: /code/libs/azure-api-client
volumes:
- .:/code
depends_on:
- mockserver

Expand Down
4 changes: 4 additions & 0 deletions libs/azure-api-client/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
AZURE_API_CLIENT_CI__EVENT_GRID__ACCESS_KEY=
AZURE_API_CLIENT_CI__EVENT_GRID__TOPIC_HOSTNAME=
AZURE_API_CLIENT_CI__SERVICE_BUS__ENDPOINT=
AZURE_API_CLIENT_CI__SERVICE_BUS__SHARED_ACCESS_KEY=
3 changes: 3 additions & 0 deletions libs/azure-api-client/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
vendor/
!.env
.env.local
.env.*.local
96 changes: 94 additions & 2 deletions libs/azure-api-client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ composer require keboola/azure-api-client
```

## Usage
The simplest way to use API client is just by creating its instance.

### Marketplaces

```php
use Keboola\AzureApiClient\ApiClientConfiguration;
Expand All @@ -19,6 +20,52 @@ $marketplaces = new MarketplaceApiClient(new ClientCredentialsAuth(
));
```

### Event Grid

> Event grid support only POST /events endpoint `EventGridApiClient::publishEvents

```php
use Keboola\AzureApiClient\ApiClientConfiguration;
use Keboola\AzureApiClient\EventGrid\EventGridApiClient
use Monolog\Logger;

$eventGrid = new EventGridApiClient(
topicHostname: '<topic>.northeurope-1.eventgrid.azure.net',
configuration: new ApiClientConfiguration(
authenticator: new CustomHeaderAuth('aeg-sas-key', '<token>'),
)
);
```

### Service Bus

> Service bus support only subset of endpoints:
> - There are no management endpoints
> - Supported are only endpoints for:
> - sending messages `ServiceBusApiClient::sendMessage`
> - deleting messages `ServiceBusApiClient::deleteMessage`
> - peak message `ServiceBusApiClient::peekMessage`

```php
use Keboola\AzureApiClient\ApiClientConfiguration;
use Keboola\AzureApiClient\ServiceBus\ServiceBusApiClient
use Keboola\AzureApiClient\Authentication\Authenticator\SASTokenAuthenticatorFactory;
use Monolog\Logger;

$endpoint = 'https://<queue>.servicebus.windows.net:443/';
$serviceBus = new ServiceBusApiClient(
serviceBusEndpoint: $endpoint,
configuration: new ApiClientConfiguration(
authenticator: new SASTokenAuthenticatorFactory(
url: $endpoint,
sharedAccessKeyName: 'RootManageSharedAccessKey',
sharedAccessKey: '<sharedAccessKey>',
),
)
);
```


### Authentication
By default, API client will try to authenticate using ENV variables `AZURE_TENANT_ID`, `AZURE_CLIENT_ID` and
`AZURE_CLIENT_SECRET`. If some of them is not available, it'll fall back to Azure metadata API.
Expand Down Expand Up @@ -51,7 +98,27 @@ $marketplaces = new MarketplaceApiClient(new ApiClientConfiguration(
));
```

Or even use custom authentication header if needed:
Or use sas token if service support it:

```php
use Keboola\AzureApiClient\ServiceBus\ServiceBusApiClient;
use Keboola\AzureApiClient\ApiClientConfiguration;
use Keboola\AzureApiClient\Authentication\Authenticator\SASTokenAuthenticatorFactory;

$endpoint = 'https://<queue>.servicebus.windows.net:443/';
$serviceBus = new ServiceBusApiClient(
serviceBusEndpoint: $endpoint,
configuration: new ApiClientConfiguration(
authenticator: new SASTokenAuthenticatorFactory(
url: $endpoint,
sharedAccessKeyName: 'RootManageSharedAccessKey',
sharedAccessKey: '<sharedAccessKey>',
),
)
);
```

Or custom authentication header if needed:

```php
use Keboola\AzureApiClient\ApiClientConfiguration;
Expand All @@ -66,6 +133,31 @@ $marketplaces = new MarketplaceApiClient(new ApiClientConfiguration(
If even this is not enough for your use-case, you can implement your own
`Keboola\AzureApiClient\Authentication\Authenticator\RequestAuthenticatorFactoryInterface` and pass it as `authenticator`.

## Development

### Resources
To run functional tests (PHPUnit group "functional") you have to setup resources in Azure.

Requirements:

- Terraform must be installed
- To print outputs command bellow use jq

```bash
terraform -chdir="provisioning" init
terraform -chdir="provisioning" apply -var name_prefix=<respource_group_prefix> -var az_subscription_id=<az_subscription_id> -var az_tenant_id=<az_tenant_id>
terraform -chdir="provisioning" output -json | jq -r 'keys[] as $k | "\($k)=\(.[$k] | .value)"' >| .env
```
### Tests

```bash
# Run only unit tests
docker-compose run --rm dev-azure-api-client composer tests -- --exclude=functional

# Run only functional tests
docker-compose run --rm dev-azure-api-client composer tests -- --group=functional
```

## License

MIT licensed, see [LICENSE](./LICENSE) file.
1 change: 1 addition & 0 deletions libs/azure-api-client/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"phpstan/phpstan-phpunit": "^1.3",
"phpstan/phpstan-webmozart-assert": "^1.2",
"sempro/phpunit-pretty-print": "^1.4",
"symfony/dotenv": "^6.3",
"symfony/http-client": "^6.2"
},
"scripts": {
Expand Down
34 changes: 34 additions & 0 deletions libs/azure-api-client/provisioning/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Local .terraform directories
**/.terraform/*

# .tfstate files
*.tfstate
*.tfstate.*

# Crash log files
crash.log

# Exclude all .tfvars files, which are likely to contain sentitive data, such as
# password, private keys, and other secrets. These should not be part of version
# control as they are data points which are potentially sensitive and subject
# to change depending on the environment.
#
*.tfvars

# Ignore override files as they are usually used to override resources locally and so
# are not checked in
override.tf
override.tf.json
*_override.tf
*_override.tf.json

# Include override files you do wish to add to version control using negated pattern
#
# !example_override.tf

# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
# example: *tfplan*

# Ignore CLI configuration files
.terraformrc
terraform.rc
40 changes: 40 additions & 0 deletions libs/azure-api-client/provisioning/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions libs/azure-api-client/provisioning/azure_eventGrid.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#
# Topics
#

resource "azurerm_eventgrid_topic" "topic_tests" {
location = azurerm_resource_group.api_client_tests.location
name = "tests-${local.resource_group_uuid}"
resource_group_name = azurerm_resource_group.api_client_tests.name
tags = local.resource_tags
}

#
# Subscriptions
#

resource "azurerm_eventgrid_event_subscription" "subscription_tests" {
name = "TestSubscriber"
scope = azurerm_eventgrid_topic.topic_tests.id
service_bus_queue_endpoint_id = azurerm_servicebus_queue.queue["queue-tests"].id
event_delivery_schema = "EventGridSchema"
}
37 changes: 37 additions & 0 deletions libs/azure-api-client/provisioning/azure_serviceBus.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#
# Service bus
#

resource "azurerm_servicebus_namespace" "queues" {
location = azurerm_resource_group.api_client_tests.location
name = "queue-${local.resource_group_uuid}"
resource_group_name = azurerm_resource_group.api_client_tests.name
sku = "Basic"
tags = local.resource_tags
}

#
# Queues
#

resource "azurerm_servicebus_queue" "queue" {
for_each = {
"queue-tests" = {
lock_duration : "PT5S"
}
}
name = each.key
namespace_id = azurerm_servicebus_namespace.queues.id
lock_duration = each.value.lock_duration
max_size_in_megabytes = "1024"
requires_duplicate_detection = false
requires_session = false
default_message_ttl = "PT10S"
dead_lettering_on_message_expiration = false
duplicate_detection_history_time_window = "PT10S"
enable_batched_operations = true
max_delivery_count = "10"
status = "Active"
enable_partitioning = false
enable_express = false
}
73 changes: 73 additions & 0 deletions libs/azure-api-client/provisioning/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0.0"
}
}
}

variable "name_prefix" {
type = string
description = "Use your nickname, RG will be prefixed with this value"
default = "ci"
}

provider "azurerm" {
features {}
tenant_id = var.az_tenant_id
subscription_id = var.az_subscription_id
}

provider "azuread" {
tenant_id = var.az_tenant_id
}

variable "az_tenant_id" {
type = string
description = "Default is Keboola tenant"
default = "9b85ee6f-4fb0-4a46-8cb7-4dcc6b262a89"
}
variable "az_subscription_id" {
type = string
description = "Default is PS team CI subscription"
default = "9577e289-304e-4165-abe0-91c933200878"
}

data "azurerm_client_config" "current" {}
data "azuread_client_config" "current" {}

locals {
resource_group_uuid = substr(md5(azurerm_resource_group.api_client_tests.id), 0, 17)
resource_tags = {
service = "api_client_tests"
env = azurerm_resource_group.api_client_tests.name
}
}

// resource group
resource "azurerm_resource_group" "api_client_tests" {
name = "${var.name_prefix}-api_client"
location = "North Europe"
}

output "AZURE_API_CLIENT_CI__SERVICE_BUS__ENDPOINT" {
value = "https://${azurerm_servicebus_namespace.queues.name}.servicebus.windows.net:443/"
}

output "AZURE_API_CLIENT_CI__SERVICE_BUS__SHARED_ACCESS_KEY" {
sensitive = true
value = azurerm_servicebus_namespace.queues.default_primary_key
}

output "AZURE_API_CLIENT_CI__EVENT_GRID__ACCESS_KEY" {
sensitive = true
value = azurerm_eventgrid_topic.topic_tests.primary_access_key
}
output "AZURE_API_CLIENT_CI__EVENT_GRID__TOPIC_HOSTNAME" {
value = replace(replace(azurerm_eventgrid_topic.topic_tests.endpoint, "https://", ""),"/api/events","")
}

output "AZURE_API_CLIENT_CI__EVENT_GRID__TOPIC_NAME" {
value = azurerm_eventgrid_topic.topic_tests.name
}
4 changes: 2 additions & 2 deletions libs/azure-api-client/src/ApiClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,9 @@ public function sendRequestAndMapResponse(
}
}

public function sendRequest(RequestInterface $request): void
public function sendRequest(RequestInterface $request): ResponseInterface
{
$this->doSendRequest($request);
return $this->doSendRequest($request);
}

private function doSendRequest(RequestInterface $request, array $options = []): ResponseInterface
Expand Down
Loading
Loading