Skip to content

Commit 424ebe6

Browse files
authored
Merge pull request #1 from keboola/odin-init
initial import
2 parents bb02090 + 119ff8b commit 424ebe6

42 files changed

Lines changed: 2129 additions & 1 deletion

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.dockerignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.idea/
2+
.git/
3+
vendor/
4+
build/
5+
/build/logs
6+
/infection.log
7+
/.phpunit.result.cache
8+
/set-env.sh
9+
/provisioning/environments.yaml

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
vendor/
2+
.idea/
3+
composer.lock
4+
/.php_cs.cache
5+
/build/logs
6+
/infection.log
7+
/.phpunit.result.cache
8+
/set-env.sh
9+
/provisioning/environments.yaml

Dockerfile

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
FROM php:7-cli
2+
3+
ENV COMPOSER_ALLOW_SUPERUSER 1
4+
5+
WORKDIR /code
6+
7+
RUN apt-get update && apt-get install -y \
8+
git \
9+
unzip \
10+
--no-install-recommends && rm -r /var/lib/apt/lists/*
11+
12+
COPY docker/php.ini /usr/local/etc/php/php.ini
13+
14+
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin/ --filename=composer
15+
16+
RUN pecl channel-update pecl.php.net \
17+
&& pecl config-set php_ini /usr/local/etc/php.ini \
18+
&& yes | pecl install xdebug \
19+
&& docker-php-ext-enable xdebug
20+
21+
COPY composer.* ./
22+
RUN composer install $COMPOSER_FLAGS --no-scripts --no-autoloader
23+
COPY . .
24+
RUN composer install $COMPOSER_FLAGS

README.md

Lines changed: 152 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,152 @@
1-
# notification-client
1+
# Notification API PHP Client [![Build Status]
2+
3+
PHP client for the Notification API ([API docs](https://app.swaggerhub.com/apis/odinuv/notifications-service/1.0.0)).
4+
5+
## Usage
6+
The client uses two kinds of authorizations - Storage API token for Subscription API (`SubscriptionClient` class) and
7+
Manage API Application token with scope `notifications:push-event` for the Events API (`EventsClient` class).
8+
9+
```bash
10+
composer require keboola/notification-api-php-client
11+
```
12+
13+
```php
14+
use Keboola\NotificationClient\EventsClient;
15+
use Keboola\NotificationClient\Requests\PostEvent\FailedJobEventData;
16+
use Keboola\NotificationClient\Requests\PostEvent\JobData;
17+
use Keboola\NotificationClient\Requests\Event;
18+
use Psr\Log\NullLogger;
19+
20+
$client = new EventsClient(
21+
new NullLogger(),
22+
'http://notifications.connection.keboola.com/',
23+
'xxx-xxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
24+
);
25+
$client->postEvent(
26+
new Event(
27+
'job_failed',
28+
new FailedJobEventData(
29+
'job failed',
30+
new JobData('my-project', '123', 'http://someUrl', '2020-01-02', '2020-01-01', 'my-orchestration')
31+
)
32+
)
33+
);
34+
```
35+
36+
## Development
37+
- Create an Azure service principal to download the required images and login:
38+
39+
```bash
40+
SERVICE_PRINCIPAL_NAME=[USERNAME]-notification-api-pull
41+
ACR_REGISTRY_ID=$(az acr show --name keboolapes --query id --output tsv --subscription c5182964-8dca-42c8-a77a-fa2a3c6946ea)
42+
SP_PASSWORD=$(az ad sp create-for-rbac --name http://$SERVICE_PRINCIPAL_NAME --scopes $ACR_REGISTRY_ID --role acrpull --query password --output tsv)
43+
SP_APP_ID=$(az ad sp show --id http://$SERVICE_PRINCIPAL_NAME --query appId --output tsv)
44+
```
45+
46+
- Login and check that you can pull the image:
47+
48+
```bash
49+
docker login keboolapes.azurecr.io --username $SP_APP_ID --password $SP_PASSWORD
50+
docker pull keboolapes.azurecr.io/notification-service:latest
51+
```
52+
53+
- Add the credentials to the k8s cluster:
54+
55+
```bash
56+
kubectl create secret docker-registry regcred --docker-server="https://keboolapes.azurecr.io" --docker-username="$SP_APP_ID" --docker-password="$SP_PASSWORD" --namespace dev-notification-client
57+
kubectl patch serviceaccount default -p "{\"imagePullSecrets\":[{\"name\":\"regcred\"}]}" --namespace dev-notification-client
58+
```
59+
60+
- Set the following environment variables in `set-env.sh` file (use `set-env.template.sh` as sample):
61+
- `STORAGE_API_URL` - Keboola Connection URL.
62+
- `TEST_STORAGE_API_TOKEN` - Token to a test project.
63+
- `TEST_MANAGE_API_APPLICATION_TOKEN` - Application token with scope `notifications:push-event`.
64+
65+
- Set one of Azure or AWS resources (or both, but only one is needed).
66+
67+
### AWS Setup
68+
- Create a user (`NotificationUser`) for local development using the `provisioning/aws.json` CF template.
69+
- Create AWS key for the created user.
70+
- Set the following environment variables in `set-env.sh` file (use `set-env.template.sh` as sample):
71+
- `TEST_AWS_ACCESS_KEY` - The created security credentials for the `JobQueueApiPhpClient` user.
72+
- `TEST_AWS_SECRET_ACCESS_KEY` - The created security credentials for the `JobQueueApiPhpClient` user.
73+
- `AWS_REGION` - `Region` output of the above stack.
74+
- `AWS_LOGS_S3_BUCKET` - `S3LogsBucket` output of the above stackk.
75+
76+
### Azure Setup
77+
78+
- Create a resource group:
79+
```bash
80+
az account set --subscription "Keboola DEV PS Team CI"
81+
az group create --name testing-notification-api-php-client --location "East US"
82+
```
83+
84+
- Create a service principal:
85+
```bash
86+
az ad sp create-for-rbac --name testing-notification-api-php-client
87+
```
88+
89+
- Use the response to set values `TEST_AZURE_CLIENT_ID`, `TEST_AZURE_CLIENT_SECRET` and `TEST_AZURE_TENANT_ID` in the `set-env.sh` file:
90+
```json
91+
{
92+
"appId": "268a6f05-xxxxxxxxxxxxxxxxxxxxxxxxxxx", //-> TEST_AZURE_CLIENT_ID
93+
"displayName": "testing-notification-api-php-client",
94+
"name": "http://testing-notification-api-php-client",
95+
"password": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", //-> TEST_AZURE_CLIENT_SECRET
96+
"tenant": "9b85ee6f-xxxxxxxxxxxxxxxxxxxxxxxxxxx" //-> TEST_AZURE_TENANT_ID
97+
}
98+
```
99+
100+
- Get ID of the service principal:
101+
```bash
102+
SERVICE_PRINCIPAL_ID=$(az ad sp list --display-name testing-notification-api-php-client --query "[0].objectId" --output tsv)
103+
```
104+
105+
- Deploy the key vault, provide tenant ID, service principal ID and group ID from the previous commands:
106+
```bash
107+
az deployment group create --resource-group testing-job-queue-api-php-client --template-file provisioning/azure.json --parameters vault_name=test-job-queue-client tenant_id=$TEST_AZURE_TENANT_ID service_principal_object_id=$SERVICE_PRINCIPAL_ID
108+
```
109+
110+
- Show Key Vault URL
111+
```bash
112+
az keyvault show --name test-job-queue-client --query "properties.vaultUri" --output tsv
113+
```
114+
115+
returns e.g. `https://test-job-queue-client.vault.azure.net/`, use this to set values in `set-env.sh` file:
116+
- `test_azure_key_vault_url` - https://test-job-queue-client.vault.azure.net/
117+
118+
## Generate environment configuration
119+
120+
```bash
121+
export DATABASE_URL_BASE64=$(printf "mysql://root:root@dev-mysql-service:3310/notifications?serverVersion=8.0" | base64 --wrap=0)
122+
export DATABASE_PASSWORD_BASE64=$(printf "root" | base64 --wrap=0)
123+
export TEST_AZURE_CLIENT_SECRET_BASE64=$(printf "%s" "$TEST_AZURE_CLIENT_SECRET"| base64 --wrap=0)
124+
export TEST_AWS_SECRET_ACCESS_KEY_BASE64=$(printf "%s" "$TEST_AWS_SECRET_ACCESS_KEY"| base64 --wrap=0)
125+
export AZURE_LOGS_ABS_CONNECTION_STRING_BASE64=$(printf "%s" "$AZURE_LOGS_ABS_CONNECTION_STRING"| base64 --wrap=0)
126+
127+
./set-env.sh
128+
envsubst < provisioning/environments.yaml.template > provisioning/environments.yaml
129+
kubectl apply -f provisioning/environments.yaml
130+
kubectl apply -f provisioning/notification.yaml
131+
TEST_NOTIFICATION_API_IP=`kubectl get svc --output jsonpath --template "{.items[?(@.metadata.name==\"dev-notification-service\")].status.loadBalancer.ingress[].ip}" --namespace=dev-notification-client`
132+
133+
printf "TEST_NOTIFICATION_API_URL: http://%s:8181" "$TEST_NOTIFICATION_API_IP"
134+
```
135+
136+
Store the result `TEST_NOTIFICATION_API_URL` in `set-env.sh`.
137+
138+
139+
## Run tests
140+
- With the above setup, you can run tests:
141+
142+
```bash
143+
docker-compose build
144+
source ./set-env.sh && docker-compose run tests
145+
```
146+
147+
- To run tests with local code use:
148+
149+
```bash
150+
docker-compose run tests-local composer install
151+
source ./set-env.sh && docker-compose run tests-local
152+
```

azure-pipelines.yml

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
pr: none
2+
trigger:
3+
batch: true
4+
branches:
5+
include:
6+
- '*'
7+
8+
pool:
9+
vmImage: ubuntu-latest
10+
11+
variables:
12+
DOCKER_BUILDKIT: 1
13+
k8sNamespace: 'dev-notification-client'
14+
ciClusterServiceConnection: 'CI AKS'
15+
16+
stages:
17+
- stage: prepare
18+
displayName: Prepare
19+
jobs:
20+
- job: services_setup
21+
variables:
22+
DECODE_PERCENTS: false # https://github.com/microsoft/azure-pipelines-agent/blob/master/docs/design/percentEncoding.md
23+
displayName: 'Setup services'
24+
steps:
25+
- task: Kubernetes@1
26+
displayName: kubectl login
27+
inputs:
28+
connectionType: 'Kubernetes Service Connection'
29+
kubernetesServiceEndpoint: $(ciClusterServiceConnection)
30+
command: login
31+
- script: |
32+
set -Eeuo pipefail
33+
34+
./provisioning/ci-setup-cluster.sh
35+
NOTIFICATION_API_IP=$(kubectl get svc \
36+
--output jsonpath \
37+
--template "{.items[?(@.metadata.name==\"dev-notification-service\")].status.loadBalancer.ingress[].ip}" \
38+
--namespace="$KUBERNETES_NAMESPACE")
39+
40+
printf "API IP:%s" "$NOTIFICATION_API_IP"
41+
echo "##vso[task.setvariable variable=NOTIFICATION_API_IP;isOutput=true]$NOTIFICATION_API_IP"
42+
displayName: 'Prepare cluster'
43+
name: prepare_cluster
44+
env:
45+
KUBERNETES_NAMESPACE: $(k8sNamespace)
46+
STORAGE_API_URL: $(STORAGE_API_URL)
47+
AWS_LOGS_S3_BUCKET: $(AWS_LOGS_S3_BUCKET)
48+
AWS_REGION: $(AWS_REGION)
49+
TEST_AWS_ACCESS_KEY_ID: $(TEST_AWS_ACCESS_KEY_ID)
50+
TEST_AWS_SECRET_ACCESS_KEY: $(TEST_AWS_SECRET_ACCESS_KEY)
51+
52+
- stage: tests
53+
dependsOn: prepare
54+
displayName: Build & Test
55+
jobs:
56+
- job: test
57+
displayName: 'Test'
58+
variables:
59+
NOTIFICATION_API_IP: $[ stageDependencies.prepare.services_setup.outputs['prepare_cluster.NOTIFICATION_API_IP'] ]
60+
steps:
61+
- script: |
62+
set -Eeuo pipefail
63+
64+
echo "Notification API URL: $NOTIFICATION_API_IP"
65+
66+
docker-compose build --pull
67+
docker-compose run --rm tests
68+
displayName: 'Build & Run Tests'
69+
env:
70+
TEST_STORAGE_API_TOKEN: $(TEST_STORAGE_API_TOKEN)
71+
TEST_MANAGE_API_APPLICATION_TOKEN: $(TEST_MANAGE_API_APPLICATION_TOKEN)
72+
TEST_NOTIFICATION_API_URL: http://$(NOTIFICATION_API_IP):8181
73+
74+
- task: PublishTestResults@2
75+
displayName: 'Publish Test results'
76+
inputs:
77+
testResultsFormat: 'JUnit'
78+
testResultsFiles: 'build/logs/*.xml'
79+
80+
- stage: cleanup
81+
displayName: Cleanup
82+
variables:
83+
- name: isDebugBuild
84+
value: ${{ startsWith(variables['Build.SourceBranch'],'refs/tags/debug') }}
85+
condition: eq(variables['isDebugBuild'], 'false')
86+
jobs:
87+
- job:
88+
displayName: Remove Services
89+
steps:
90+
- task: Kubernetes@1
91+
displayName: kubectl login
92+
inputs:
93+
connectionType: 'Kubernetes Service Connection'
94+
kubernetesServiceEndpoint: $(ciClusterServiceConnection)
95+
command: login
96+
97+
- script: |
98+
set -Eeuo pipefail
99+
100+
kubectl delete deployment dev-mysql --namespace=$KUBERNETES_NAMESPACE
101+
kubectl delete deployment dev-notification-api --namespace=$KUBERNETES_NAMESPACE
102+
kubectl delete service dev-mysql-service --namespace=$KUBERNETES_NAMESPACE
103+
kubectl delete service dev-notification-service --namespace=$KUBERNETES_NAMESPACE
104+
kubectl delete secret dev-notification-environments --namespace=$KUBERNETES_NAMESPACE
105+
kubectl delete configmap dev-notification-environments --namespace=$KUBERNETES_NAMESPACE
106+
displayName: Cleanup cluster
107+
env:
108+
KUBERNETES_NAMESPACE: $(k8sNamespace)

composer.json

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{
2+
"name": "keboola/notification-api-php-client",
3+
"license": "MIT",
4+
"type": "library",
5+
"description": "Client for Notification API",
6+
"keywords": [
7+
"keboola",
8+
"notification",
9+
"client"
10+
],
11+
"authors": [
12+
{
13+
"name": "Keboola",
14+
"email": "devel@keboola.com"
15+
}
16+
],
17+
"autoload": {
18+
"psr-4": {
19+
"Keboola\\NotificationClient\\": "src/"
20+
}
21+
},
22+
"autoload-dev": {
23+
"psr-4": {
24+
"Keboola\\NotificationClient\\Tests\\": "tests/"
25+
}
26+
},
27+
"require": {
28+
"php": "^7.4",
29+
"ext-json": "*",
30+
"guzzlehttp/guzzle": "^6.3|^7.2",
31+
"psr/log": "^1.1",
32+
"symfony/validator": "^5.2"
33+
},
34+
"require-dev": {
35+
"infection/infection": "^0.18.2|^0.21.2",
36+
"keboola/coding-standard": ">=10.0.0",
37+
"php-parallel-lint/php-parallel-lint": "^1.2",
38+
"phpstan/phpstan": "^0.12.80",
39+
"phpunit/phpunit": "^9.5"
40+
},
41+
"scripts": {
42+
"tests": "phpunit --coverage-clover build/logs/clover.xml --coverage-xml=build/logs/coverage-xml --log-junit=build/logs/phpunit.junit.xml",
43+
"phpstan": "phpstan analyse --no-progress -c phpstan.neon",
44+
"phpcs": "phpcs --extensions=php src tests",
45+
"phpcbf": "phpcbf --extensions=php src tests",
46+
"phplint": "parallel-lint -j 10 --exclude vendor .",
47+
"infection": "infection --threads=4 --min-covered-msi=90 --coverage=build/logs",
48+
"build": [
49+
"@phplint",
50+
"@phpcs",
51+
"@phpstan",
52+
"@tests",
53+
"@infection"
54+
],
55+
"ci": [
56+
"@composer validate --no-check-all --strict",
57+
"@build"
58+
]
59+
},
60+
"config": {
61+
"sort-packages": true,
62+
"process-timeout": 3600
63+
}
64+
}

docker-compose.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
version: "3"
2+
3+
services:
4+
tests: &tests
5+
image: keboola/dev-notification-api-php-client
6+
build: .
7+
volumes:
8+
- ./build/logs/:/code/build/logs/
9+
environment:
10+
TEST_NOTIFICATION_API_URL:
11+
TEST_STORAGE_API_TOKEN:
12+
TEST_MANAGE_API_APPLICATION_TOKEN:
13+
command: ['composer', 'ci']
14+
15+
tests-local:
16+
<<: *tests
17+
volumes:
18+
- .:/code

0 commit comments

Comments
 (0)