Skip to content

Commit

Permalink
parking-offstreet-sta: initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
dulvui committed Jan 9, 2024
1 parent e3a8272 commit 8847e05
Show file tree
Hide file tree
Showing 22 changed files with 683 additions and 0 deletions.
21 changes: 21 additions & 0 deletions data-collectors/parking-offstreet-sta/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
API_OAUTH_TOKEN_URI=
API_OAUTH_USERNAME=
API_OAUTH_PASSWORD=
API_OAUTH_CLIENT_SECRET=
API_OAUTH_CLIENT_ID=


SCHEDULER_CRON="*/10 * * * * *"

BASE_URI=https://mobility.share.opendatahub.testingmachine.eu/json
OAUTH_AUTH_URI=https://auth.opendatahub.testingmachine.eu/auth
OAUTH_TOKEN_URI=https://auth.opendatahub.testingmachine.eu/auth/realms/noi/protocol/openid-connect/token
OAUTH_CLIENT_ID=odh-mobility-datacollector-development
OAUTH_CLIENT_NAME=odh-mobility-datacollector-development
OAUTH_CLIENT_SECRET=7bd46f8f-c296-416d-a13d-dc81e68d0830
OAUTH_CLIENT_SCOPE=openid

PROVENANCE_VERSION=0.0.0-local
PROVENANCE_NAME=odh-mobility-golang-dc-parking-offstreet-sta

LOG_LEVEL=INFO
25 changes: 25 additions & 0 deletions data-collectors/parking-offstreet-sta/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Dependency directories (remove the comment below to include it)
# vendor/

# Go workspace file
go.work

.env

main
38 changes: 38 additions & 0 deletions data-collectors/parking-offstreet-sta/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<!--
SPDX-FileCopyrightText: NOI Techpark <[email protected]>
SPDX-License-Identifier: CC0-1.0
-->

# Parking off street STA

[![CI](https://github.com/noi-techpark/bdp-commons/actions/workflows/ci-parking-offstreet-sta.yml/badge.svg)](https://github.com/noi-techpark/bdp-commons/actions/workflows/ci-parking-offstreet-sta.yml)

This data collector gathers data about STA's parking facilities provided by Skidata.
The job runs as a scheduled cron job that periodically interrogates the onecenter REST API.

See the [requirements](./documentation/230214_SpecificheIntegrazione_NOI_v1.1.pdf) and [API specification](./documentation/230728_SpecificaSkidata.pdf) for more details

See [calls.http](./calls.http) for example API calls to the onecenter REST API.

## Getting started

General instructions can be found inside the [Open Data Hub Mobility - Data
Collectors README](../../README.md). Please read that first. The following
chapters will only contain specific configuration and setup steps.

These instructions will get you a copy of the project up and running on your
local machine for development and testing purposes.

### Prerequisites

To build the project, the following prerequisites must be met:
- Everything inside [Open Data Hub Mobility - Data Collectors README](../../README.md#prerequisites)

### Configuration

Create a local .env file by copying the [example .env](.env.example)

Credentials both for ODH and ONECENTER endpoints have to be obtained separately

After plugging in the relevant credentials, docker-compose up should fire up a local instance.
34 changes: 34 additions & 0 deletions data-collectors/parking-offstreet-sta/calls.http
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
##### VSCODE / REST Client
# Create a .env file and set the corresponding variables
# See all $dotenv fields below

@username={{$dotenv API_OAUTH_USERNAME}}
@password={{$dotenv API_OAUTH_PASSWORD}}
@secret={{$dotenv API_OAUTH_CLIENT_SECRET}}
@clientId={{$dotenv API_OAUTH_CLIENT_ID}}



### Get access token for the writer (LOCAL DEV)
# @name login
GET https://www.onecenter.info/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=password
&username={{username}}
&client_id={{clientId}}
&client_secret={{secret}}
&password={{password}}

### save token

@token = {{login.response.body.access_token}}

### GetFacilities
GET https://www.onecenter.info/api/DAZ/GetFacilities
Authorization: Bearer {{token}}

### FacilityID
GET https://www.onecenter.info/api/DAZ/FacilityFreePlaces
?FacilityID=608612
Authorization: Bearer {{login.response.body.access_token}}
13 changes: 13 additions & 0 deletions data-collectors/parking-offstreet-sta/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
version: "3.9"

services:
app:
image: golang:1.21.4-alpine
env_file:
- .env
entrypoint: >
go run main.go
volumes:
- ./src:/code
- ~/.go/pkg/mod:/go/pkg/mod
working_dir: /code
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[defaults]
inventory = ./hosts
roles_path = ./roles
retry_files_enabled = False
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
- hosts: all
vars:
ansible_python_interpreter: /usr/bin/python3
tasks:
- name: Login to GitHub Container Registry
ansible.builtin.shell:
cmd: echo "{{ docker_password }}" | docker login "{{ docker_host }}" --username "{{ docker_username }}" --password-stdin
- name: Execute Docker deployment
ansible.builtin.include_role:
name: ansible-docker-deployment
vars:
docker_deployment_project_name: '{{ project_name }}'
docker_deployment_release_name: '{{ release_name }}'
docker_deployment_release_files:
- local: ../docker-compose.run.yml
remote: docker-compose.yml
- local: ../../.env
remote: .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[test]
docker03.testingmachine.eu ansible_user='noi-techpark-bot' ansible_ssh_common_args='-o StrictHostKeyChecking=no'

[prod]
docker03.opendatahub.bz.it ansible_user='noi-techpark-bot' ansible_ssh_common_args='-o StrictHostKeyChecking=no'
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- src: git+https://github.com/noi-techpark/ansible-docker-deployment.git
version: "2.0"
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*
!.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
version: '3.4'

services:
app:
image: ${DOCKER_IMAGE}:${DOCKER_TAG}
build:
context: ../
dockerfile: infrastructure/docker/Dockerfile
env_file: ../.env
restart: unless-stopped
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
version: '3.4'

services:
app:
image: ${DOCKER_IMAGE}:${DOCKER_TAG}
restart: unless-stopped
env_file: .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM golang:1.21.4-bookworm

# install if docker host doesn't has libc6 installed
RUN apt-get update && apt-get install -y libc6

WORKDIR app

COPY src/main main

CMD [ "./main"]
98 changes: 98 additions & 0 deletions data-collectors/parking-offstreet-sta/src/dc/auth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package dc

import (
"encoding/json"
"io"
"log/slog"
"net/http"
"net/url"
"os"
"strconv"
"strings"
"time"
)

type Token struct {
AccessToken string `json:"access_token"`
ExpiresIn int64 `json:"expires_in"`
NotBeforePolicy int64 `json:"not-before-policy"`
RefreshExpiresIn int64 `json:"refresh_expires_in"`
TokenType string `json:"token_type"`
RefreshToken string `json:"refresh_token"`
Scope string
}

var tokenUri string = os.Getenv("API_OAUTH_TOKEN_URI")
var clientId string = os.Getenv("API_OAUTH_CLIENT_ID")
var clientSecret string = os.Getenv("API_OAUTH_CLIENT_SECRET")
var username string = os.Getenv("API_OAUTH_USERNAME")
var password string = os.Getenv("API_OAUTH_PASSWORD")

var token Token

var tokenExpiry int64

func GetToken() string {
ts := time.Now().Unix()

if len(token.AccessToken) == 0 || ts > tokenExpiry {
// if no token is available or refreshToken is expired, get new token
newToken()
}

return token.AccessToken
}

func newToken() {
slog.Info("Getting new API token...")

authRequest()

slog.Info("Getting new API token done.")
}

func authRequest() {
params := url.Values{}
params.Add("grant_type", "password")
params.Add("client_id", clientId)
params.Add("client_secret", clientSecret)
params.Add("username", username)
params.Add("password", password)

body := strings.NewReader(params.Encode())

req, err := http.NewRequest("GET", tokenUri, body)
if err != nil {
slog.Error("error", err)
return
}

req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

resp, err := http.DefaultClient.Do(req)
if err != nil {
slog.Error("error", err)
return
}
defer resp.Body.Close()

slog.Info("Auth response code is: " + strconv.Itoa(resp.StatusCode))
if resp.StatusCode == http.StatusOK {
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
slog.Error("error", err)
return
}

err = json.Unmarshal(bodyBytes, &token)
if err != nil {
slog.Error("error", err)
return
}
}

// calculate token expiry timestamp with 600 seconds margin
tokenExpiry = time.Now().Unix() + token.ExpiresIn - 600

slog.Info("auth token expires in " + strconv.FormatInt(tokenExpiry, 10))
}
72 changes: 72 additions & 0 deletions data-collectors/parking-offstreet-sta/src/dc/data.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package dc

import (
"encoding/json"
"io"
"log/slog"
"net/http"
"strconv"
)

type ApiResponse struct {
Data Data
}

type Data struct {
Status string
Facilities []Facility
}

type Facility struct {
IdCompany int
FacilityId int
Description string
City string
Address string
ZIPCode string
Telephone1 string
Telephone2 string
PostNumber int
ReceiptMerchant string
Web string
}

const apiUrl = "https://www.onecenter.info/api/DAZ/GetFacilities"

func GetData() ApiResponse {

var apiResponse ApiResponse

req, err := http.NewRequest("GET", apiUrl, nil)
if err != nil {
slog.Error("error", err)
return apiResponse
}
req.Header = http.Header{
"Content-Type": {"application/json"},
"Authorization": {"Bearer " + GetToken()},
}

resp, err := http.DefaultClient.Do(req)
if err != nil {
slog.Error("error", err)
return apiResponse
}
defer resp.Body.Close()

slog.Info("Auth response code is: " + strconv.Itoa(resp.StatusCode))
if resp.StatusCode == http.StatusOK {
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
slog.Error("error", err)
return apiResponse
}

err = json.Unmarshal(bodyBytes, &apiResponse)
if err != nil {
slog.Error("error", err)
return apiResponse
}
}
return apiResponse
}
Loading

0 comments on commit 8847e05

Please sign in to comment.