Neue Skills, Referenzen & OpenWiki-Doku integriert
Umfangreiche Erweiterung der Skill-Bibliothek: Neue Skills für Humanisierung (Englisch/PT-BR), Design-Validierung, AI-SEO und Coolify-Deployment inkl. Regelwerke, Presets, Pattern-Referenzen, Testfälle und Automatisierungsskripte. Zusätzliche Skills für Revenue-Centric Design, Pier Cloud, OKF, Lebenslauf- und LinkedIn-Optimierung sowie zahlreiche Referenzdateien, Checklisten und YAML/JSON/Markdown-Templates. Einführung einer vollständigen OpenWiki-Dokumentation mit Architektur-, Domain- und Workflow-Beschreibungen, zentralem Index und automatisierten Updates. Modularer Aufbau, restriktive Lizenzen und umfassende Qualitäts- und Evaluationsmechanismen für alle neuen Inhalte.
This commit is contained in:
9
.github/skills/pier-cloud/.env.example
vendored
Normal file
9
.github/skills/pier-cloud/.env.example
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
PIERCLOUD_CLIENT_ID=
|
||||
PIERCLOUD_CLIENT_SECRET=
|
||||
PIERCLOUD_TENANCY_ID=
|
||||
# Legado (TENANCY_ID tem prioridade, mas BUSINESS_ID ainda funciona como fallback)
|
||||
# PIERCLOUD_BUSINESS_ID=
|
||||
# PIERCLOUD_ORG_ID= (nao mais necessario na nova API)
|
||||
|
||||
|
||||
|
||||
103
.github/skills/pier-cloud/SKILL.md
vendored
Normal file
103
.github/skills/pier-cloud/SKILL.md
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
---
|
||||
name: "pier-cloud"
|
||||
description: "This skill should be used when the user needs to consume the Pier Cloud (Lighthouse) API for cloud cost management — including JWT authentication, listing contexts, workspaces, and FinOps data views. Trigger whenever there is a need to integrate, automate, or debug calls to the Pier Cloud platform via Python, Node.js, or cURL."
|
||||
metadata:
|
||||
author: ft.ia.br
|
||||
version: "1.1"
|
||||
date: 2026-03-05
|
||||
repository: https://github.com/fabricioctelles/skills
|
||||
license: Apache 2.0
|
||||
keywords: ["pier", "piercloud", "lighthouse", "api", "finops", "cloud", "costs"]
|
||||
category: library-and-api-reference
|
||||
---
|
||||
|
||||
# Pier Cloud API
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Credentials
|
||||
|
||||
Locate the `.env` file in the skill directory with the following variables:
|
||||
|
||||
```env
|
||||
PIERCLOUD_CLIENT_ID=your_client_id
|
||||
PIERCLOUD_CLIENT_SECRET=your_client_secret
|
||||
PIERCLOUD_TENANCY_ID=your_tenancy_id
|
||||
```
|
||||
|
||||
If the `.env` file does not exist, inform the user that credentials must be obtained from the Pier Cloud platform before proceeding. Do not proceed without the `.env` file.
|
||||
|
||||
> Note: `PIERCLOUD_TENANCY_ID` is equivalent to the former `PIERCLOUD_BUSINESS_ID`. Scripts accept both as fallback.
|
||||
|
||||
### Python Dependencies
|
||||
|
||||
```bash
|
||||
pip install requests python-dotenv
|
||||
```
|
||||
|
||||
## Basic Configuration
|
||||
|
||||
The API uses JWT authentication. Required flow:
|
||||
|
||||
1. Authenticate via `POST /auth` with `client_id` and `client_secret` to obtain a JWT token
|
||||
2. Include the token in all requests: `Authorization: Bearer {token}`
|
||||
3. Renew the token upon expiration (default validity: 1 hour)
|
||||
|
||||
**Base URL**: `https://api.piercloud.io`
|
||||
|
||||
Verify the connection by running:
|
||||
|
||||
```bash
|
||||
python scripts/pier-cloud-auth.py
|
||||
```
|
||||
|
||||
## Available Scripts
|
||||
|
||||
Ready-to-use scripts in `scripts/`. See `scripts/README.md` for detailed instructions.
|
||||
|
||||
| Script | Description |
|
||||
|--------|-------------|
|
||||
| `pier-cloud-auth.py` | Authenticate and obtain JWT token |
|
||||
| `pier-cloud-list-contexts.py` | List available contexts |
|
||||
| `pier-cloud-list-workspaces.py` | List workspaces with pagination |
|
||||
| `pier-cloud-get-workspace.py` | Get specific workspace details |
|
||||
| `pier-cloud-get-all-workspaces.py` | Get all workspaces (automatic pagination) |
|
||||
| `pier-cloud-list-views.py` | List views for a workspace |
|
||||
| `pier-cloud-get-view.py` | Get specific view information |
|
||||
| `pier-cloud-get-view-data.py` | Get view data with filters |
|
||||
| `pier_cloud_client.py` | Robust client with CLI and reusable library |
|
||||
|
||||
> Note: Workspace-groups scripts (`pier-cloud-list-workspace-groups.py`, `pier-cloud-get-workspace-group.py`) do not work — the corresponding endpoints do not exist in the current API.
|
||||
|
||||
## Workflows
|
||||
|
||||
Follow the detailed workflows with request and response examples in `references/REFERENCE.md`:
|
||||
|
||||
- **Workflow 1** — Authentication and Token Retrieval
|
||||
- **Workflow 2** — List Contexts
|
||||
- **Workflow 3** — List Workspaces
|
||||
- **Workflow 4** — Get Workspace Details
|
||||
- **Workflow 5** — Get All Workspaces (Automatic Pagination)
|
||||
- **Workflow 6** — Robust Client with Retry and Token Renewal
|
||||
- **Workflow 9** — List Workspace Views
|
||||
- **Workflow 10** — Get View Information
|
||||
- **Workflow 11** — Get View Data with Filters
|
||||
|
||||
For endpoint reference, parameters, response structures, and cURL examples, see `references/REFERENCE.md`.
|
||||
|
||||
For error diagnosis (401, 403, 404, timeout, rate limiting), see `references/TROUBLESHOOTING.md`.
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- **API Docs**: https://docs.piercloud.com/api-docs-pier-cloud
|
||||
- **Pier Cloud Platform**: https://piercloud.com/en/
|
||||
|
||||
## Quality Checklist
|
||||
|
||||
- [ ] `.env` file present with `PIERCLOUD_CLIENT_ID`, `PIERCLOUD_CLIENT_SECRET`, and `PIERCLOUD_TENANCY_ID`
|
||||
- [ ] Python dependencies installed (`requests`, `python-dotenv`)
|
||||
- [ ] Authentication successful (JWT token obtained without errors)
|
||||
- [ ] Correct endpoint being used (default `/lighthouse/tenancies/{tenancy_id}/...`)
|
||||
- [ ] Token being renewed before expiration in long sessions
|
||||
- [ ] Workspace/view IDs confirmed via listing before using directly
|
||||
- [ ] Errors handled per `references/TROUBLESHOOTING.md`
|
||||
115
.github/skills/pier-cloud/references/TROUBLESHOOTING.md
vendored
Normal file
115
.github/skills/pier-cloud/references/TROUBLESHOOTING.md
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
## Troubleshooting
|
||||
|
||||
### Error 401 - Invalid Credentials
|
||||
|
||||
**Problem**: Authentication fails with error 401
|
||||
|
||||
**Symptoms**:
|
||||
```json
|
||||
{
|
||||
"code": "failed",
|
||||
"message": "invalid or expired token"
|
||||
}
|
||||
```
|
||||
|
||||
**Common Causes**:
|
||||
- Incorrect `client_id` or `client_secret`
|
||||
- Credentials not registered on the Pier Cloud platform
|
||||
- Environment variables not loaded correctly
|
||||
|
||||
**Solutions**:
|
||||
1. Check credentials in the `.env` file
|
||||
2. Confirm that variables are being loaded
|
||||
3. Validate credentials with the Pier Cloud team
|
||||
4. Verify that the HTTP client is registered on the platform
|
||||
|
||||
### Error 403 - Access Denied
|
||||
|
||||
**Problem**: Valid token but no permission to access resource
|
||||
|
||||
**Symptoms**:
|
||||
```json
|
||||
{
|
||||
"code": "authorization/forbidden",
|
||||
"message": "Access denied"
|
||||
}
|
||||
```
|
||||
|
||||
**Causes**:
|
||||
- Account without adequate permissions
|
||||
- Incorrect `tenancy_id`
|
||||
- Resource does not belong to the specified tenant
|
||||
|
||||
**Solutions**:
|
||||
1. Check account permissions on the Pier Cloud platform
|
||||
2. Confirm correct `tenancy_id`
|
||||
3. Contact administrator to request permissions
|
||||
|
||||
### Error 404 - Resource Not Found
|
||||
|
||||
**Problem**: Endpoint or resource does not exist
|
||||
|
||||
**Symptoms**:
|
||||
```json
|
||||
{
|
||||
"code": "workspace/not-found",
|
||||
"message": "Workspace not found"
|
||||
}
|
||||
```
|
||||
|
||||
**Causes**:
|
||||
- Incorrect or non-existent `workspace_id`
|
||||
- Invalid `tenancy_id`
|
||||
- Incorrect endpoint URL
|
||||
|
||||
**Solutions**:
|
||||
1. List all workspaces first to verify available IDs
|
||||
2. Confirm endpoint URL is correct
|
||||
3. Validate tenancy_id
|
||||
|
||||
### Expired Token
|
||||
|
||||
**Problem**: JWT token expired after ~1 hour
|
||||
|
||||
**Symptoms**:
|
||||
- Requests that were working start returning 401
|
||||
- Error "invalid or expired token"
|
||||
|
||||
**Solution**:
|
||||
|
||||
Use the robust client that implements automatic renewal:
|
||||
|
||||
```bash
|
||||
python scripts/pier_cloud_client.py --action list-contexts
|
||||
```
|
||||
|
||||
The `pier_cloud_client.py` client automatically renews the token before it expires.
|
||||
|
||||
### Connection Timeout
|
||||
|
||||
**Problem**: Request takes too long or does not respond
|
||||
|
||||
**Symptoms**:
|
||||
- Timeout after 30+ seconds
|
||||
- Connection not established
|
||||
- Network error
|
||||
|
||||
**Solutions**:
|
||||
1. Check internet connectivity
|
||||
2. Test API availability: `curl -I https://api.piercloud.io/auth`
|
||||
3. Check if there is a proxy or firewall blocking
|
||||
4. Try again after a few minutes
|
||||
|
||||
### Rate Limiting (Too Many Requests)
|
||||
|
||||
**Problem**: API returns error 429 (Too Many Requests)
|
||||
|
||||
**Symptoms**:
|
||||
- Error 429 after several rapid requests
|
||||
- Message about rate limit
|
||||
|
||||
**Solutions**:
|
||||
1. Use the robust client that implements automatic retry
|
||||
2. Reduce request frequency
|
||||
3. Implement delays between requests
|
||||
4. Use pagination with smaller `page_size` if needed
|
||||
166
.github/skills/pier-cloud/scripts/README.md
vendored
Normal file
166
.github/skills/pier-cloud/scripts/README.md
vendored
Normal file
@@ -0,0 +1,166 @@
|
||||
# Scripts da API Pier Cloud
|
||||
|
||||
Scripts prontos para consumir a API Pier Cloud (Lighthouse).
|
||||
|
||||
## Prerequisitos
|
||||
|
||||
```bash
|
||||
pip install requests python-dotenv
|
||||
```
|
||||
|
||||
## Configuracao
|
||||
|
||||
Crie arquivo `.env` na raiz do projeto:
|
||||
|
||||
```env
|
||||
PIERCLOUD_CLIENT_ID=seu_client_id
|
||||
PIERCLOUD_CLIENT_SECRET=seu_client_secret
|
||||
PIERCLOUD_TENANCY_ID=seu_tenancy_id
|
||||
```
|
||||
|
||||
> **Nota**: O `TENANCY_ID` corresponde ao antigo `BUSINESS_ID`. Se voce ja tem `PIERCLOUD_BUSINESS_ID` no `.env`, os scripts usam como fallback automaticamente.
|
||||
|
||||
## API - Mudanca de Endpoints (Fev 2026)
|
||||
|
||||
A API Pier Cloud atualizou seus endpoints:
|
||||
|
||||
- **Antes**: `/lighthouse/orgs/{org_id}/businesses/{business_id}/...`
|
||||
- **Agora**: `/lighthouse/tenancies/{tenancy_id}/...`
|
||||
|
||||
O `PIERCLOUD_ORG_ID` nao e mais necessario. O `tenancy_id` equivale ao antigo `BUSINESS_ID`.
|
||||
|
||||
Documentacao oficial: https://docs.piercloud.com/api-docs-pier-cloud
|
||||
|
||||
## Scripts Disponiveis
|
||||
|
||||
### 1. pier-cloud-auth.py
|
||||
Autentica e obtem token JWT.
|
||||
|
||||
```bash
|
||||
python scripts/pier-cloud-auth.py
|
||||
```
|
||||
|
||||
### 2. pier-cloud-list-contexts.py
|
||||
Lista todos os contextos disponiveis.
|
||||
|
||||
```bash
|
||||
python scripts/pier-cloud-list-contexts.py
|
||||
```
|
||||
|
||||
### 3. pier-cloud-list-workspaces.py
|
||||
Lista workspaces com paginacao.
|
||||
|
||||
```bash
|
||||
# Padrao (pagina 1, 10 itens)
|
||||
python scripts/pier-cloud-list-workspaces.py
|
||||
|
||||
# Pagina especifica
|
||||
python scripts/pier-cloud-list-workspaces.py --page 2 --page-size 50
|
||||
|
||||
# Ordenar por data
|
||||
python scripts/pier-cloud-list-workspaces.py --sort-field created_at --sort-order DESC
|
||||
```
|
||||
|
||||
### 4. pier-cloud-get-workspace.py
|
||||
Obtem detalhes de workspace especifico.
|
||||
|
||||
```bash
|
||||
python scripts/pier-cloud-get-workspace.py --workspace-id 16969
|
||||
```
|
||||
|
||||
### 5. pier-cloud-get-all-workspaces.py
|
||||
Obtem todos os workspaces com paginacao automatica.
|
||||
|
||||
```bash
|
||||
# Exibir no terminal
|
||||
python scripts/pier-cloud-get-all-workspaces.py
|
||||
|
||||
# Salvar em JSON
|
||||
python scripts/pier-cloud-get-all-workspaces.py --output workspaces.json
|
||||
|
||||
# Salvar em CSV
|
||||
python scripts/pier-cloud-get-all-workspaces.py --output workspaces.csv --format csv
|
||||
```
|
||||
|
||||
### 6. pier-cloud-list-views.py
|
||||
Lista visualizacoes de um workspace.
|
||||
|
||||
```bash
|
||||
python scripts/pier-cloud-list-views.py --workspace-id 16969
|
||||
```
|
||||
|
||||
### 7. pier-cloud-get-view.py
|
||||
Obtem informacoes de visualizacao especifica.
|
||||
|
||||
```bash
|
||||
python scripts/pier-cloud-get-view.py --view-id 193195
|
||||
```
|
||||
|
||||
### 8. pier-cloud-get-view-data.py
|
||||
Obtem dados de uma visualizacao com filtros.
|
||||
|
||||
```bash
|
||||
# Basico
|
||||
python scripts/pier-cloud-get-view-data.py --view-id 193195
|
||||
|
||||
# Com periodo
|
||||
python scripts/pier-cloud-get-view-data.py --view-id 193195 \
|
||||
--start-date 2026-01-01 --end-date 2026-01-31
|
||||
|
||||
# Com filtros
|
||||
python scripts/pier-cloud-get-view-data.py --view-id 193195 \
|
||||
--filters '[{"name":"lineitem/usageaccountid","data_type":"string","role":"filter","filters":[{"expression":"IS","value":["123456"],"negative_expression":false}]}]'
|
||||
|
||||
# Salvar em arquivo
|
||||
python scripts/pier-cloud-get-view-data.py --view-id 193195 \
|
||||
--start-date 2026-01-01 --end-date 2026-01-31 --output dados.json
|
||||
```
|
||||
|
||||
### 9. pier_cloud_client.py
|
||||
Cliente robusto com CLI e biblioteca reutilizavel.
|
||||
|
||||
**Como CLI**:
|
||||
```bash
|
||||
# Listar contextos
|
||||
python scripts/pier_cloud_client.py --action list-contexts
|
||||
|
||||
# Listar workspaces
|
||||
python scripts/pier_cloud_client.py --action list-workspaces --page 1 --page-size 20
|
||||
|
||||
# Obter workspace
|
||||
python scripts/pier_cloud_client.py --action get-workspace --workspace-id 16969
|
||||
|
||||
# Obter todos
|
||||
python scripts/pier_cloud_client.py --action get-all-workspaces --output results.json
|
||||
```
|
||||
|
||||
### 10. appscript-pier-cloud.gs
|
||||
Codigo Google Apps Script para integrar com Google Sheets.
|
||||
|
||||
Veja instrucoes no proprio arquivo.
|
||||
|
||||
## Endpoints da API (Atualizado Fev 2026)
|
||||
|
||||
| Metodo | Endpoint | Descricao |
|
||||
|--------|----------|-----------|
|
||||
| POST | `/auth` | Obter token JWT |
|
||||
| GET | `/lighthouse/tenancies/{tenancy_id}/contexts` | Listar contextos |
|
||||
| GET | `/lighthouse/tenancies/{tenancy_id}/workspaces` | Listar workspaces |
|
||||
| GET | `/lighthouse/tenancies/{tenancy_id}/workspaces/{id}` | Obter workspace |
|
||||
| GET | `/lighthouse/tenancies/{tenancy_id}/workspaces/{workspace_id}/views` | Listar views |
|
||||
| GET | `/lighthouse/tenancies/{tenancy_id}/views/{id}` | Obter view |
|
||||
| GET | `/lighthouse/tenancies/{tenancy_id}/views/{id}/data` | Obter dados da view |
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Erro: Variaveis faltando
|
||||
Verifique se o arquivo `.env` existe e contem `PIERCLOUD_TENANCY_ID` (ou `PIERCLOUD_BUSINESS_ID` como fallback).
|
||||
|
||||
### Erro 401
|
||||
Credenciais invalidas. Verifique CLIENT_ID e CLIENT_SECRET.
|
||||
|
||||
### Erro 403
|
||||
Sem permissao. Verifique TENANCY_ID.
|
||||
|
||||
### Erro 404
|
||||
Recurso nao encontrado. Verifique IDs fornecidos.
|
||||
62
.github/skills/pier-cloud/scripts/pier-cloud-auth.py
vendored
Normal file
62
.github/skills/pier-cloud/scripts/pier-cloud-auth.py
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Script to authenticate with the Pier Cloud API and obtain a JWT token.
|
||||
"""
|
||||
|
||||
import requests
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Load environment variables
|
||||
load_dotenv()
|
||||
|
||||
API_BASE = "https://api.piercloud.io"
|
||||
CLIENT_ID = os.getenv("PIERCLOUD_CLIENT_ID")
|
||||
CLIENT_SECRET = os.getenv("PIERCLOUD_CLIENT_SECRET")
|
||||
|
||||
def authenticate():
|
||||
"""Obtain authentication token"""
|
||||
print("Authenticating with Pier Cloud API...")
|
||||
|
||||
url = f"{API_BASE}/auth"
|
||||
payload = {
|
||||
"client_id": CLIENT_ID,
|
||||
"client_secret": CLIENT_SECRET
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.post(url, json=payload, timeout=30)
|
||||
|
||||
if response.status_code == 201:
|
||||
data = response.json()
|
||||
token = data['data']['access_token']
|
||||
expires_in = data['data']['expires_in']
|
||||
|
||||
print(f"\n✓ Token obtained successfully!")
|
||||
print(f"Token: {token[:50]}...")
|
||||
print(f"Expires in: {expires_in} seconds ({expires_in//60} minutes)")
|
||||
print(f"Type: {data['data']['token_type']}")
|
||||
|
||||
return token
|
||||
else:
|
||||
print(f"\n✗ Authentication error (Status {response.status_code})")
|
||||
print(f"Response: {response.text}")
|
||||
return None
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"\n✗ Connection error: {e}")
|
||||
return None
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Validate environment variables
|
||||
if not CLIENT_ID or not CLIENT_SECRET:
|
||||
print("✗ Error: PIERCLOUD_CLIENT_ID and PIERCLOUD_CLIENT_SECRET must be defined in .env")
|
||||
exit(1)
|
||||
|
||||
token = authenticate()
|
||||
|
||||
if token:
|
||||
print("\n✓ Authentication completed successfully!")
|
||||
else:
|
||||
print("\n✗ Authentication failed")
|
||||
exit(1)
|
||||
124
.github/skills/pier-cloud/scripts/pier-cloud-get-all-workspaces.py
vendored
Normal file
124
.github/skills/pier-cloud/scripts/pier-cloud-get-all-workspaces.py
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Script para obter todos os workspaces da API Pier Cloud com paginacao automatica.
|
||||
"""
|
||||
|
||||
import requests
|
||||
import os
|
||||
import argparse
|
||||
import json
|
||||
import csv
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
API_BASE = "https://api.piercloud.io"
|
||||
CLIENT_ID = os.getenv("PIERCLOUD_CLIENT_ID")
|
||||
CLIENT_SECRET = os.getenv("PIERCLOUD_CLIENT_SECRET")
|
||||
TENANCY_ID = os.getenv("PIERCLOUD_TENANCY_ID", os.getenv("PIERCLOUD_BUSINESS_ID"))
|
||||
|
||||
def authenticate():
|
||||
"""Obter token de autenticacao"""
|
||||
url = f"{API_BASE}/auth"
|
||||
payload = {"client_id": CLIENT_ID, "client_secret": CLIENT_SECRET}
|
||||
response = requests.post(url, json=payload, timeout=30)
|
||||
|
||||
if response.status_code == 201:
|
||||
return response.json()['data']['access_token']
|
||||
else:
|
||||
raise Exception(f"Erro na autenticacao: {response.text}")
|
||||
|
||||
def get_all_workspaces(token):
|
||||
"""Obter todos os workspaces com paginacao automatica"""
|
||||
all_workspaces = []
|
||||
page = 1
|
||||
page_size = 100 # Maximo permitido
|
||||
|
||||
while True:
|
||||
url = f"{API_BASE}/lighthouse/tenancies/{TENANCY_ID}/workspaces"
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
params = {"page": page, "page_size": page_size}
|
||||
|
||||
response = requests.get(url, headers=headers, params=params, timeout=30)
|
||||
|
||||
if response.status_code != 200:
|
||||
raise Exception(f"Erro na pagina {page}: {response.text}")
|
||||
|
||||
data = response.json()
|
||||
workspaces = data['data']['workspaces']
|
||||
meta = data['meta']
|
||||
|
||||
all_workspaces.extend(workspaces)
|
||||
|
||||
print(f"OK Pagina {page}: {len(workspaces)} workspaces obtidos")
|
||||
|
||||
# Verificar se ha mais paginas
|
||||
if page * page_size >= meta['total']:
|
||||
break
|
||||
|
||||
page += 1
|
||||
|
||||
return all_workspaces
|
||||
|
||||
def save_json(workspaces, filename):
|
||||
"""Salvar workspaces em arquivo JSON"""
|
||||
with open(filename, 'w', encoding='utf-8') as f:
|
||||
json.dump(workspaces, f, indent=2, ensure_ascii=False)
|
||||
print(f"OK Salvo em {filename}")
|
||||
|
||||
def save_csv(workspaces, filename):
|
||||
"""Salvar workspaces em arquivo CSV"""
|
||||
if not workspaces:
|
||||
print("Nenhum workspace para salvar")
|
||||
return
|
||||
|
||||
keys = ['id', 'name', 'description', 'access_scope', 'count_views', 'created_at']
|
||||
|
||||
with open(filename, 'w', newline='', encoding='utf-8') as f:
|
||||
writer = csv.DictWriter(f, fieldnames=keys)
|
||||
writer.writeheader()
|
||||
|
||||
for ws in workspaces:
|
||||
row = {k: ws.get(k, '') for k in keys}
|
||||
writer.writerow(row)
|
||||
|
||||
print(f"OK Salvo em {filename}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Obter todos os workspaces da API Pier Cloud")
|
||||
parser.add_argument("--output", help="Arquivo de saida (JSON ou CSV)")
|
||||
parser.add_argument("--format", choices=["json", "csv"], default="json", help="Formato de saida")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Validar variaveis
|
||||
if not TENANCY_ID:
|
||||
print("X Erro: PIERCLOUD_TENANCY_ID (ou PIERCLOUD_BUSINESS_ID) deve estar definido no .env")
|
||||
exit(1)
|
||||
required = ["CLIENT_ID", "CLIENT_SECRET"]
|
||||
missing = [v for v in required if not os.getenv(f"PIERCLOUD_{v}")]
|
||||
|
||||
if missing:
|
||||
print(f"X Erro: Variaveis faltando no .env: {missing}")
|
||||
exit(1)
|
||||
|
||||
try:
|
||||
print("Autenticando...")
|
||||
token = authenticate()
|
||||
print("OK Autenticado\n")
|
||||
|
||||
print("Obtendo todos os workspaces...")
|
||||
workspaces = get_all_workspaces(token)
|
||||
|
||||
print(f"\nOK Total: {len(workspaces)} workspaces obtidos")
|
||||
|
||||
# Salvar em arquivo se especificado
|
||||
if args.output:
|
||||
if args.format == "json":
|
||||
save_json(workspaces, args.output)
|
||||
else:
|
||||
save_csv(workspaces, args.output)
|
||||
|
||||
except Exception as e:
|
||||
print(f"\nX Erro: {e}")
|
||||
exit(1)
|
||||
130
.github/skills/pier-cloud/scripts/pier-cloud-get-view-data.py
vendored
Normal file
130
.github/skills/pier-cloud/scripts/pier-cloud-get-view-data.py
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Script para obter dados de uma visualizacao da API Pier Cloud com filtros.
|
||||
"""
|
||||
|
||||
import requests
|
||||
import os
|
||||
import argparse
|
||||
import json
|
||||
from datetime import datetime, timedelta
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
API_BASE = "https://api.piercloud.io"
|
||||
CLIENT_ID = os.getenv("PIERCLOUD_CLIENT_ID")
|
||||
CLIENT_SECRET = os.getenv("PIERCLOUD_CLIENT_SECRET")
|
||||
TENANCY_ID = os.getenv("PIERCLOUD_TENANCY_ID", os.getenv("PIERCLOUD_BUSINESS_ID"))
|
||||
|
||||
def authenticate():
|
||||
"""Obter token de autenticacao"""
|
||||
url = f"{API_BASE}/auth"
|
||||
payload = {"client_id": CLIENT_ID, "client_secret": CLIENT_SECRET}
|
||||
response = requests.post(url, json=payload, timeout=30)
|
||||
|
||||
if response.status_code == 201:
|
||||
return response.json()['data']['access_token']
|
||||
else:
|
||||
raise Exception(f"Erro na autenticacao: {response.text}")
|
||||
|
||||
def get_view_data(token, view_id, start_date=None, end_date=None, date_type="date", filters=None):
|
||||
"""Obter dados de uma visualizacao"""
|
||||
url = f"{API_BASE}/lighthouse/tenancies/{TENANCY_ID}/views/{view_id}/data"
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
|
||||
# Parametros de query
|
||||
params = {}
|
||||
|
||||
if start_date:
|
||||
params['start_date'] = start_date
|
||||
if end_date:
|
||||
params['end_date'] = end_date
|
||||
if date_type:
|
||||
params['date_type'] = date_type
|
||||
if filters:
|
||||
params['filters'] = json.dumps(filters)
|
||||
|
||||
response = requests.get(url, headers=headers, params=params, timeout=60)
|
||||
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
results = data['data']
|
||||
|
||||
print(f"\n=== Dados da Visualizacao {view_id} ===")
|
||||
print(f"Periodo: {start_date or 'inicio do mes'} ate {end_date or 'fim do mes'}")
|
||||
print(f"Tipo de data: {date_type}")
|
||||
print(f"Total de registros: {len(results)}\n")
|
||||
|
||||
if results:
|
||||
# Mostrar primeiros registros
|
||||
print("Primeiros registros:")
|
||||
for i, record in enumerate(results[:5]):
|
||||
print(f"\nRegistro {i+1}:")
|
||||
for key, value in record.items():
|
||||
print(f" {key}: {value}")
|
||||
|
||||
if len(results) > 5:
|
||||
print(f"\n... e mais {len(results) - 5} registros")
|
||||
|
||||
return results
|
||||
else:
|
||||
raise Exception(f"Erro ao obter dados: {response.text}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Obter dados de visualizacao da API Pier Cloud")
|
||||
parser.add_argument("--view-id", "--view_id", dest="view_id", type=int, required=True, help="ID da visualizacao")
|
||||
parser.add_argument("--start-date", "--start_date", dest="start_date", help="Data inicial (YYYY-MM-DD)")
|
||||
parser.add_argument("--end-date", "--end_date", dest="end_date", help="Data final (YYYY-MM-DD)")
|
||||
parser.add_argument("--date-type", "--date_type", dest="date_type", choices=["date", "month"], default="date",
|
||||
help="Tipo de filtro de data (date ou month)")
|
||||
parser.add_argument("--filters", help="Filtros em formato JSON")
|
||||
parser.add_argument("--output", help="Arquivo de saida JSON")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Validar variaveis
|
||||
if not TENANCY_ID:
|
||||
print("X Erro: PIERCLOUD_TENANCY_ID (ou PIERCLOUD_BUSINESS_ID) deve estar definido no .env")
|
||||
exit(1)
|
||||
required = ["CLIENT_ID", "CLIENT_SECRET"]
|
||||
missing = [v for v in required if not os.getenv(f"PIERCLOUD_{v}")]
|
||||
|
||||
if missing:
|
||||
print(f"X Erro: Variaveis faltando no .env: {missing}")
|
||||
exit(1)
|
||||
|
||||
# Parse filters se fornecido
|
||||
filters = None
|
||||
if args.filters:
|
||||
try:
|
||||
filters = json.loads(args.filters)
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"X Erro ao parsear filtros JSON: {e}")
|
||||
exit(1)
|
||||
|
||||
try:
|
||||
print("Autenticando...")
|
||||
token = authenticate()
|
||||
print("OK Autenticado")
|
||||
|
||||
results = get_view_data(
|
||||
token,
|
||||
args.view_id,
|
||||
start_date=args.start_date,
|
||||
end_date=args.end_date,
|
||||
date_type=args.date_type,
|
||||
filters=filters
|
||||
)
|
||||
|
||||
# Salvar em arquivo se especificado
|
||||
if args.output:
|
||||
with open(args.output, 'w', encoding='utf-8') as f:
|
||||
json.dump(results, f, indent=2, ensure_ascii=False)
|
||||
print(f"\nOK Salvo em {args.output}")
|
||||
|
||||
print(f"\nOK Total: {len(results)} registros obtidos")
|
||||
|
||||
except Exception as e:
|
||||
print(f"\nX Erro: {e}")
|
||||
exit(1)
|
||||
82
.github/skills/pier-cloud/scripts/pier-cloud-get-view.py
vendored
Normal file
82
.github/skills/pier-cloud/scripts/pier-cloud-get-view.py
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Script para obter informacoes de uma visualizacao especifica da API Pier Cloud.
|
||||
"""
|
||||
|
||||
import requests
|
||||
import os
|
||||
import argparse
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
API_BASE = "https://api.piercloud.io"
|
||||
CLIENT_ID = os.getenv("PIERCLOUD_CLIENT_ID")
|
||||
CLIENT_SECRET = os.getenv("PIERCLOUD_CLIENT_SECRET")
|
||||
TENANCY_ID = os.getenv("PIERCLOUD_TENANCY_ID", os.getenv("PIERCLOUD_BUSINESS_ID"))
|
||||
|
||||
def authenticate():
|
||||
"""Obter token de autenticacao"""
|
||||
url = f"{API_BASE}/auth"
|
||||
payload = {"client_id": CLIENT_ID, "client_secret": CLIENT_SECRET}
|
||||
response = requests.post(url, json=payload, timeout=30)
|
||||
|
||||
if response.status_code == 201:
|
||||
return response.json()['data']['access_token']
|
||||
else:
|
||||
raise Exception(f"Erro na autenticacao: {response.text}")
|
||||
|
||||
def get_view(token, view_id):
|
||||
"""Obter informacoes de uma visualizacao especifica"""
|
||||
url = f"{API_BASE}/lighthouse/tenancies/{TENANCY_ID}/views/{view_id}"
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
|
||||
response = requests.get(url, headers=headers, timeout=30)
|
||||
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
view = data['data']
|
||||
|
||||
print(f"\n=== Visualizacao: {view['name']} ===\n")
|
||||
print(f"ID: {view['id']}")
|
||||
print(f"Nome: {view['name']}")
|
||||
print(f"Descricao: {view.get('description', 'N/A')}")
|
||||
|
||||
if 'workspace' in view:
|
||||
print(f"\nWorkspace:")
|
||||
print(f" ID: {view['workspace']['id']}")
|
||||
print(f" Nome: {view['workspace']['name']}")
|
||||
|
||||
return view
|
||||
else:
|
||||
raise Exception(f"Erro ao obter visualizacao: {response.text}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Obter informacoes de visualizacao da API Pier Cloud")
|
||||
parser.add_argument("--view-id", "--view_id", dest="view_id", type=int, required=True, help="ID da visualizacao")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Validar variaveis
|
||||
if not TENANCY_ID:
|
||||
print("X Erro: PIERCLOUD_TENANCY_ID (ou PIERCLOUD_BUSINESS_ID) deve estar definido no .env")
|
||||
exit(1)
|
||||
required = ["CLIENT_ID", "CLIENT_SECRET"]
|
||||
missing = [v for v in required if not os.getenv(f"PIERCLOUD_{v}")]
|
||||
|
||||
if missing:
|
||||
print(f"X Erro: Variaveis faltando no .env: {missing}")
|
||||
exit(1)
|
||||
|
||||
try:
|
||||
print("Autenticando...")
|
||||
token = authenticate()
|
||||
print("OK Autenticado")
|
||||
|
||||
view = get_view(token, args.view_id)
|
||||
|
||||
print(f"\nOK Visualizacao obtida com sucesso")
|
||||
|
||||
except Exception as e:
|
||||
print(f"\nX Erro: {e}")
|
||||
exit(1)
|
||||
93
.github/skills/pier-cloud/scripts/pier-cloud-get-workspace-group.py
vendored
Normal file
93
.github/skills/pier-cloud/scripts/pier-cloud-get-workspace-group.py
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Script para obter detalhes de um grupo de workspace especifico da API Pier Cloud.
|
||||
"""
|
||||
|
||||
import requests
|
||||
import os
|
||||
import argparse
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
API_BASE = "https://api.piercloud.io"
|
||||
CLIENT_ID = os.getenv("PIERCLOUD_CLIENT_ID")
|
||||
CLIENT_SECRET = os.getenv("PIERCLOUD_CLIENT_SECRET")
|
||||
TENANCY_ID = os.getenv("PIERCLOUD_TENANCY_ID", os.getenv("PIERCLOUD_BUSINESS_ID"))
|
||||
|
||||
def authenticate():
|
||||
"""Obter token de autenticacao"""
|
||||
url = f"{API_BASE}/auth"
|
||||
payload = {"client_id": CLIENT_ID, "client_secret": CLIENT_SECRET}
|
||||
response = requests.post(url, json=payload, timeout=30)
|
||||
|
||||
if response.status_code == 201:
|
||||
return response.json()['data']['access_token']
|
||||
else:
|
||||
raise Exception(f"Erro na autenticacao: {response.text}")
|
||||
|
||||
def get_workspace_group(token, group_id):
|
||||
"""Obter detalhes de um grupo de workspace especifico"""
|
||||
url = f"{API_BASE}/lighthouse/tenancies/{TENANCY_ID}/workspace-groups/{group_id}"
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
|
||||
response = requests.get(url, headers=headers, timeout=30)
|
||||
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
group = data['data']
|
||||
|
||||
print(f"\n=== Grupo de Workspace: {group['name']} ===\n")
|
||||
print(f"ID: {group['id']}")
|
||||
print(f"Nome: {group['name']}")
|
||||
print(f"Descricao: {group.get('description', 'N/A')}")
|
||||
print(f"Acesso: {group['access_scope']}")
|
||||
print(f"Context ID: {group['context_id']}")
|
||||
print(f"Business ID: {group['business_id']}")
|
||||
print(f"Criado em: {group['created_at']}")
|
||||
print(f"Atualizado em: {group['updated_at']}")
|
||||
|
||||
if 'workspaces' in group and group['workspaces']:
|
||||
print(f"\n--- Workspaces ({len(group['workspaces'])}) ---")
|
||||
for ws in group['workspaces']:
|
||||
print(f"\n ID: {ws['id']}")
|
||||
print(f" Nome: {ws['name']}")
|
||||
print(f" Descricao: {ws.get('description', 'N/A')}")
|
||||
print(f" Acesso: {ws['access_scope']}")
|
||||
print(f" Criado em: {ws['created_at']}")
|
||||
else:
|
||||
print("\nNenhum workspace neste grupo.")
|
||||
|
||||
return group
|
||||
else:
|
||||
raise Exception(f"Erro ao obter grupo: {response.text}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Obter detalhes de grupo de workspace da API Pier Cloud")
|
||||
parser.add_argument("--group-id", "--group_id", dest="group_id", required=True, help="ID do grupo de workspace (numerico ou UUID)")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Validar variaveis
|
||||
if not TENANCY_ID:
|
||||
print("X Erro: PIERCLOUD_TENANCY_ID (ou PIERCLOUD_BUSINESS_ID) deve estar definido no .env")
|
||||
exit(1)
|
||||
required = ["CLIENT_ID", "CLIENT_SECRET"]
|
||||
missing = [v for v in required if not os.getenv(f"PIERCLOUD_{v}")]
|
||||
|
||||
if missing:
|
||||
print(f"X Erro: Variaveis faltando no .env: {missing}")
|
||||
exit(1)
|
||||
|
||||
try:
|
||||
print("Autenticando...")
|
||||
token = authenticate()
|
||||
print("OK Autenticado")
|
||||
|
||||
group = get_workspace_group(token, args.group_id)
|
||||
|
||||
print(f"\nOK Grupo obtido com sucesso")
|
||||
|
||||
except Exception as e:
|
||||
print(f"\nX Erro: {e}")
|
||||
exit(1)
|
||||
88
.github/skills/pier-cloud/scripts/pier-cloud-get-workspace.py
vendored
Normal file
88
.github/skills/pier-cloud/scripts/pier-cloud-get-workspace.py
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Script para obter detalhes de um workspace especifico da API Pier Cloud.
|
||||
"""
|
||||
|
||||
import requests
|
||||
import os
|
||||
import argparse
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
API_BASE = "https://api.piercloud.io"
|
||||
CLIENT_ID = os.getenv("PIERCLOUD_CLIENT_ID")
|
||||
CLIENT_SECRET = os.getenv("PIERCLOUD_CLIENT_SECRET")
|
||||
TENANCY_ID = os.getenv("PIERCLOUD_TENANCY_ID", os.getenv("PIERCLOUD_BUSINESS_ID"))
|
||||
|
||||
def authenticate():
|
||||
"""Obter token de autenticacao"""
|
||||
url = f"{API_BASE}/auth"
|
||||
payload = {"client_id": CLIENT_ID, "client_secret": CLIENT_SECRET}
|
||||
response = requests.post(url, json=payload, timeout=30)
|
||||
|
||||
if response.status_code == 201:
|
||||
return response.json()['data']['access_token']
|
||||
else:
|
||||
raise Exception(f"Erro na autenticacao: {response.text}")
|
||||
|
||||
def get_workspace(token, workspace_id):
|
||||
"""Obter detalhes de um workspace especifico"""
|
||||
url = f"{API_BASE}/lighthouse/tenancies/{TENANCY_ID}/workspaces/{workspace_id}"
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
|
||||
response = requests.get(url, headers=headers, timeout=30)
|
||||
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
ws = data['data']
|
||||
|
||||
print(f"\n=== Workspace: {ws['name']} ===\n")
|
||||
print(f"ID: {ws['id']}")
|
||||
print(f"Descricao: {ws.get('description', 'N/A')}")
|
||||
print(f"Acesso: {ws['access_scope']}")
|
||||
print(f"Grupo: {ws['workspace_group_id']}")
|
||||
|
||||
if 'views' in ws and ws['views']:
|
||||
print(f"\n--- Visualizacoes ({len(ws['views'])}) ---")
|
||||
for view in ws['views']:
|
||||
print(f"\n ID: {view['id']}")
|
||||
print(f" Nome: {view['name']}")
|
||||
print(f" Descricao: {view.get('description', 'N/A')}")
|
||||
print(f" Criado em: {view['created_at']}")
|
||||
else:
|
||||
print("\nNenhuma visualizacao encontrada.")
|
||||
|
||||
return ws
|
||||
else:
|
||||
raise Exception(f"Erro ao obter workspace: {response.text}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Obter detalhes de workspace da API Pier Cloud")
|
||||
parser.add_argument("--workspace-id", "--workspace_id", dest="workspace_id", type=int, required=True, help="ID do workspace")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Validar variaveis
|
||||
if not TENANCY_ID:
|
||||
print("X Erro: PIERCLOUD_TENANCY_ID (ou PIERCLOUD_BUSINESS_ID) deve estar definido no .env")
|
||||
exit(1)
|
||||
required = ["CLIENT_ID", "CLIENT_SECRET"]
|
||||
missing = [v for v in required if not os.getenv(f"PIERCLOUD_{v}")]
|
||||
|
||||
if missing:
|
||||
print(f"X Erro: Variaveis faltando no .env: {missing}")
|
||||
exit(1)
|
||||
|
||||
try:
|
||||
print("Autenticando...")
|
||||
token = authenticate()
|
||||
print("OK Autenticado")
|
||||
|
||||
workspace = get_workspace(token, args.workspace_id)
|
||||
|
||||
print(f"\nOK Workspace obtido com sucesso")
|
||||
|
||||
except Exception as e:
|
||||
print(f"\nX Erro: {e}")
|
||||
exit(1)
|
||||
76
.github/skills/pier-cloud/scripts/pier-cloud-list-contexts.py
vendored
Normal file
76
.github/skills/pier-cloud/scripts/pier-cloud-list-contexts.py
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Script to list contexts from the Pier Cloud API.
|
||||
"""
|
||||
|
||||
import requests
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
API_BASE = "https://api.piercloud.io"
|
||||
CLIENT_ID = os.getenv("PIERCLOUD_CLIENT_ID")
|
||||
CLIENT_SECRET = os.getenv("PIERCLOUD_CLIENT_SECRET")
|
||||
TENANCY_ID = os.getenv("PIERCLOUD_TENANCY_ID", os.getenv("PIERCLOUD_BUSINESS_ID"))
|
||||
|
||||
def authenticate():
|
||||
"""Obtain authentication token"""
|
||||
url = f"{API_BASE}/auth"
|
||||
payload = {"client_id": CLIENT_ID, "client_secret": CLIENT_SECRET}
|
||||
|
||||
response = requests.post(url, json=payload, timeout=30)
|
||||
|
||||
if response.status_code == 201:
|
||||
return response.json()['data']['access_token']
|
||||
else:
|
||||
raise Exception(f"Authentication error: {response.text}")
|
||||
|
||||
def list_contexts(token):
|
||||
"""List all contexts"""
|
||||
url = f"{API_BASE}/lighthouse/tenancies/{TENANCY_ID}/contexts"
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
|
||||
response = requests.get(url, headers=headers, timeout=30)
|
||||
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
contexts = data['data']['contexts']
|
||||
|
||||
print(f"\n=== Contexts ({len(contexts)} found) ===\n")
|
||||
|
||||
for ctx in contexts:
|
||||
print(f"ID: {ctx['id']}")
|
||||
print(f"Name: {ctx['name']}")
|
||||
print(f"Provider: {ctx['provider']}")
|
||||
print(f"Currency: {ctx['currency']}")
|
||||
print(f"Default: {'Yes' if ctx['is_default'] else 'No'}")
|
||||
print("-" * 60)
|
||||
|
||||
return contexts
|
||||
else:
|
||||
raise Exception(f"Error listing contexts: {response.text}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Validate variables
|
||||
if not TENANCY_ID:
|
||||
print("X Error: PIERCLOUD_TENANCY_ID (or PIERCLOUD_BUSINESS_ID) must be defined in .env")
|
||||
exit(1)
|
||||
required = ["CLIENT_ID", "CLIENT_SECRET"]
|
||||
missing = [v for v in required if not os.getenv(f"PIERCLOUD_{v}")]
|
||||
|
||||
if missing:
|
||||
print(f"✗ Error: Missing variables in .env: {missing}")
|
||||
exit(1)
|
||||
|
||||
try:
|
||||
print("Authenticating...")
|
||||
token = authenticate()
|
||||
print("✓ Authenticated")
|
||||
|
||||
contexts = list_contexts(token)
|
||||
print(f"\n✓ Total: {len(contexts)} contexts")
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n✗ Error: {e}")
|
||||
exit(1)
|
||||
83
.github/skills/pier-cloud/scripts/pier-cloud-list-views.py
vendored
Normal file
83
.github/skills/pier-cloud/scripts/pier-cloud-list-views.py
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Script para listar visualizacoes de um workspace da API Pier Cloud.
|
||||
"""
|
||||
|
||||
import requests
|
||||
import os
|
||||
import argparse
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
API_BASE = "https://api.piercloud.io"
|
||||
CLIENT_ID = os.getenv("PIERCLOUD_CLIENT_ID")
|
||||
CLIENT_SECRET = os.getenv("PIERCLOUD_CLIENT_SECRET")
|
||||
TENANCY_ID = os.getenv("PIERCLOUD_TENANCY_ID", os.getenv("PIERCLOUD_BUSINESS_ID"))
|
||||
|
||||
def authenticate():
|
||||
"""Obter token de autenticacao"""
|
||||
url = f"{API_BASE}/auth"
|
||||
payload = {"client_id": CLIENT_ID, "client_secret": CLIENT_SECRET}
|
||||
response = requests.post(url, json=payload, timeout=30)
|
||||
|
||||
if response.status_code == 201:
|
||||
return response.json()['data']['access_token']
|
||||
else:
|
||||
raise Exception(f"Erro na autenticacao: {response.text}")
|
||||
|
||||
def list_views(token, workspace_id):
|
||||
"""Listar visualizacoes de um workspace"""
|
||||
url = f"{API_BASE}/lighthouse/tenancies/{TENANCY_ID}/workspaces/{workspace_id}/views"
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
|
||||
response = requests.get(url, headers=headers, timeout=30)
|
||||
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
views = data['data']['views']
|
||||
total = data['data']['total']
|
||||
|
||||
print(f"\n=== Visualizacoes do Workspace {workspace_id} ===")
|
||||
print(f"Total: {total} visualizacoes\n")
|
||||
|
||||
for view in views:
|
||||
print(f"ID: {view['id']}")
|
||||
print(f"Nome: {view['name']}")
|
||||
print(f"Descricao: {view.get('description', 'N/A')}")
|
||||
print(f"Criado em: {view['created_at']}")
|
||||
print("-" * 60)
|
||||
|
||||
return views
|
||||
else:
|
||||
raise Exception(f"Erro ao listar visualizacoes: {response.text}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Listar visualizacoes de workspace da API Pier Cloud")
|
||||
parser.add_argument("--workspace-id", "--workspace_id", dest="workspace_id", type=int, required=True, help="ID do workspace")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Validar variaveis
|
||||
if not TENANCY_ID:
|
||||
print("X Erro: PIERCLOUD_TENANCY_ID (ou PIERCLOUD_BUSINESS_ID) deve estar definido no .env")
|
||||
exit(1)
|
||||
required = ["CLIENT_ID", "CLIENT_SECRET"]
|
||||
missing = [v for v in required if not os.getenv(f"PIERCLOUD_{v}")]
|
||||
|
||||
if missing:
|
||||
print(f"X Erro: Variaveis faltando no .env: {missing}")
|
||||
exit(1)
|
||||
|
||||
try:
|
||||
print("Autenticando...")
|
||||
token = authenticate()
|
||||
print("OK Autenticado")
|
||||
|
||||
views = list_views(token, args.workspace_id)
|
||||
|
||||
print(f"\nOK Total: {len(views)} visualizacoes")
|
||||
|
||||
except Exception as e:
|
||||
print(f"\nX Erro: {e}")
|
||||
exit(1)
|
||||
101
.github/skills/pier-cloud/scripts/pier-cloud-list-workspace-groups.py
vendored
Normal file
101
.github/skills/pier-cloud/scripts/pier-cloud-list-workspace-groups.py
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Script para listar grupos de workspaces da API Pier Cloud.
|
||||
"""
|
||||
|
||||
import requests
|
||||
import os
|
||||
import argparse
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
API_BASE = "https://api.piercloud.io"
|
||||
CLIENT_ID = os.getenv("PIERCLOUD_CLIENT_ID")
|
||||
CLIENT_SECRET = os.getenv("PIERCLOUD_CLIENT_SECRET")
|
||||
TENANCY_ID = os.getenv("PIERCLOUD_TENANCY_ID", os.getenv("PIERCLOUD_BUSINESS_ID"))
|
||||
|
||||
def authenticate():
|
||||
"""Obter token de autenticacao"""
|
||||
url = f"{API_BASE}/auth"
|
||||
payload = {"client_id": CLIENT_ID, "client_secret": CLIENT_SECRET}
|
||||
response = requests.post(url, json=payload, timeout=30)
|
||||
|
||||
if response.status_code == 201:
|
||||
return response.json()['data']['access_token']
|
||||
else:
|
||||
raise Exception(f"Erro na autenticacao: {response.text}")
|
||||
|
||||
def list_workspace_groups(token, page=1, page_size=10):
|
||||
"""Listar grupos de workspaces"""
|
||||
url = f"{API_BASE}/lighthouse/tenancies/{TENANCY_ID}/workspace-groups"
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
params = {"page": page, "page_size": page_size}
|
||||
|
||||
response = requests.get(url, headers=headers, params=params, timeout=30)
|
||||
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
groups = data['data']
|
||||
meta = data['meta']
|
||||
|
||||
print(f"\n=== Grupos de Workspaces (Pagina {meta['page']}) ===")
|
||||
print(f"Total: {meta['total']} grupos\n")
|
||||
|
||||
for i, group in enumerate(groups, 1):
|
||||
print(f"\n{'='*60}")
|
||||
print(f"GRUPO {i}")
|
||||
print(f"{'='*60}")
|
||||
print(f"ID COMPLETO: {group['id']}")
|
||||
print(f"Nome: {group['name']}")
|
||||
print(f"Descricao: {group.get('description', 'N/A')}")
|
||||
print(f"Acesso: {group['access_scope']}")
|
||||
print(f"Context ID: {group.get('context_id', 'N/A')}")
|
||||
print(f"Business ID: {group.get('business_id', 'N/A')}")
|
||||
print(f"Criado em: {group['created_at']}")
|
||||
print(f"Atualizado em: {group.get('updated_at', 'N/A')}")
|
||||
print(f"Workspaces: {len(group.get('workspaces', []))}")
|
||||
|
||||
if group.get('workspaces'):
|
||||
print("\n Workspaces incluidos:")
|
||||
for ws in group['workspaces']:
|
||||
print(f" - [{ws['id']}] {ws['name']}")
|
||||
|
||||
print(f"\n Comando para obter detalhes:")
|
||||
print(f" python scripts/pier-cloud-get-workspace-group.py --group-id {group['id']}")
|
||||
print(f"{'='*60}")
|
||||
|
||||
return groups, meta
|
||||
else:
|
||||
raise Exception(f"Erro ao listar grupos: {response.text}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Listar grupos de workspaces da API Pier Cloud")
|
||||
parser.add_argument("--page", type=int, default=1, help="Numero da pagina (padrao: 1)")
|
||||
parser.add_argument("--page-size", "--page_size", dest="page_size", type=int, default=10, help="Itens por pagina (padrao: 10)")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Validar variaveis
|
||||
if not TENANCY_ID:
|
||||
print("X Erro: PIERCLOUD_TENANCY_ID (ou PIERCLOUD_BUSINESS_ID) deve estar definido no .env")
|
||||
exit(1)
|
||||
required = ["CLIENT_ID", "CLIENT_SECRET"]
|
||||
missing = [v for v in required if not os.getenv(f"PIERCLOUD_{v}")]
|
||||
|
||||
if missing:
|
||||
print(f"X Erro: Variaveis faltando no .env: {missing}")
|
||||
exit(1)
|
||||
|
||||
try:
|
||||
print("Autenticando...")
|
||||
token = authenticate()
|
||||
print("OK Autenticado")
|
||||
|
||||
groups, meta = list_workspace_groups(token, page=args.page, page_size=args.page_size)
|
||||
|
||||
print(f"\nOK Exibidos {len(groups)} grupos de {meta['total']} total")
|
||||
|
||||
except Exception as e:
|
||||
print(f"\nX Erro: {e}")
|
||||
exit(1)
|
||||
103
.github/skills/pier-cloud/scripts/pier-cloud-list-workspaces.py
vendored
Normal file
103
.github/skills/pier-cloud/scripts/pier-cloud-list-workspaces.py
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Script to list workspaces from the Pier Cloud API with pagination.
|
||||
"""
|
||||
|
||||
import requests
|
||||
import os
|
||||
import argparse
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
API_BASE = "https://api.piercloud.io"
|
||||
CLIENT_ID = os.getenv("PIERCLOUD_CLIENT_ID")
|
||||
CLIENT_SECRET = os.getenv("PIERCLOUD_CLIENT_SECRET")
|
||||
TENANCY_ID = os.getenv("PIERCLOUD_TENANCY_ID", os.getenv("PIERCLOUD_BUSINESS_ID"))
|
||||
|
||||
def authenticate():
|
||||
"""Obtain authentication token"""
|
||||
url = f"{API_BASE}/auth"
|
||||
payload = {"client_id": CLIENT_ID, "client_secret": CLIENT_SECRET}
|
||||
response = requests.post(url, json=payload, timeout=30)
|
||||
|
||||
if response.status_code == 201:
|
||||
return response.json()['data']['access_token']
|
||||
else:
|
||||
raise Exception(f"Authentication error: {response.text}")
|
||||
|
||||
def list_workspaces(token, page=1, page_size=10, sort_field="name", sort_order="ASC"):
|
||||
"""List workspaces with pagination"""
|
||||
url = f"{API_BASE}/lighthouse/tenancies/{TENANCY_ID}/workspaces"
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
params = {
|
||||
"page": page,
|
||||
"page_size": page_size,
|
||||
"sort_field": sort_field,
|
||||
"sort_order": sort_order
|
||||
}
|
||||
|
||||
response = requests.get(url, headers=headers, params=params, timeout=30)
|
||||
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
workspaces = data['data']['workspaces']
|
||||
meta = data['meta']
|
||||
|
||||
total_pages = (meta['total'] - 1) // meta['pageSize'] + 1
|
||||
|
||||
print(f"\n=== Workspaces (Page {meta['page']}/{total_pages}) ===")
|
||||
print(f"Total: {meta['total']} workspaces")
|
||||
print(f"Sort: {meta['sortBy']['field']} {meta['sortBy']['order']}\n")
|
||||
|
||||
for ws in workspaces:
|
||||
print(f"ID: {ws['id']}")
|
||||
print(f"Name: {ws['name']}")
|
||||
print(f"Description: {ws.get('description', 'N/A')}")
|
||||
print(f"Views: {ws['count_views']}")
|
||||
print(f"Access: {ws['access_scope']}")
|
||||
print(f"Created at: {ws['created_at']}")
|
||||
print("-" * 60)
|
||||
|
||||
return workspaces, meta
|
||||
else:
|
||||
raise Exception(f"Error listing workspaces: {response.text}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="List workspaces from the Pier Cloud API")
|
||||
parser.add_argument("--page", type=int, default=1, help="Page number (default: 1)")
|
||||
parser.add_argument("--page-size", "--page_size", dest="page_size", type=int, default=10, help="Items per page (default: 10, max: 100)")
|
||||
parser.add_argument("--sort-field", "--sort_field", dest="sort_field", choices=["name", "created_at"], default="name", help="Sort field")
|
||||
parser.add_argument("--sort-order", "--sort_order", dest="sort_order", choices=["ASC", "DESC"], default="ASC", help="Sort order")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Validate variables
|
||||
if not TENANCY_ID:
|
||||
print("X Error: PIERCLOUD_TENANCY_ID (or PIERCLOUD_BUSINESS_ID) must be defined in .env")
|
||||
exit(1)
|
||||
required = ["CLIENT_ID", "CLIENT_SECRET"]
|
||||
missing = [v for v in required if not os.getenv(f"PIERCLOUD_{v}")]
|
||||
|
||||
if missing:
|
||||
print(f"✗ Error: Missing variables in .env: {missing}")
|
||||
exit(1)
|
||||
|
||||
try:
|
||||
print("Authenticating...")
|
||||
token = authenticate()
|
||||
print("✓ Authenticated")
|
||||
|
||||
workspaces, meta = list_workspaces(
|
||||
token,
|
||||
page=args.page,
|
||||
page_size=args.page_size,
|
||||
sort_field=args.sort_field,
|
||||
sort_order=args.sort_order
|
||||
)
|
||||
|
||||
print(f"\n✓ Displayed {len(workspaces)} workspaces of {meta['total']} total")
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n✗ Error: {e}")
|
||||
exit(1)
|
||||
199
.github/skills/pier-cloud/scripts/pier_cloud_client.py
vendored
Normal file
199
.github/skills/pier-cloud/scripts/pier_cloud_client.py
vendored
Normal file
@@ -0,0 +1,199 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Cliente robusto para API Pier Cloud com retry, renovacao automatica e CLI.
|
||||
"""
|
||||
|
||||
import requests
|
||||
import os
|
||||
import time
|
||||
import logging
|
||||
import argparse
|
||||
import json
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Configurar logging
|
||||
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class PierCloudClient:
|
||||
"""Cliente robusto para API Pier Cloud"""
|
||||
|
||||
def __init__(self):
|
||||
load_dotenv()
|
||||
self.api_base = "https://api.piercloud.io"
|
||||
self.client_id = os.getenv("PIERCLOUD_CLIENT_ID")
|
||||
self.client_secret = os.getenv("PIERCLOUD_CLIENT_SECRET")
|
||||
self.tenancy_id = os.getenv("PIERCLOUD_TENANCY_ID", os.getenv("PIERCLOUD_BUSINESS_ID"))
|
||||
|
||||
self.token = None
|
||||
self.token_expires = None
|
||||
|
||||
self._validate_config()
|
||||
|
||||
def _validate_config(self):
|
||||
"""Validar configuracao necessaria"""
|
||||
required = ["client_id", "client_secret", "tenancy_id"]
|
||||
missing = [k for k in required if not getattr(self, k)]
|
||||
|
||||
if missing:
|
||||
raise ValueError(f"Configuracao faltando: {missing}")
|
||||
|
||||
def authenticate(self):
|
||||
"""Autenticar e obter token"""
|
||||
logger.info("Autenticando...")
|
||||
|
||||
response = requests.post(
|
||||
f"{self.api_base}/auth",
|
||||
json={"client_id": self.client_id, "client_secret": self.client_secret},
|
||||
timeout=30
|
||||
)
|
||||
|
||||
if response.status_code == 201:
|
||||
data = response.json()['data']
|
||||
self.token = data['access_token']
|
||||
# Renovar 5 minutos antes de expirar
|
||||
self.token_expires = time.time() + data['expires_in'] - 300
|
||||
logger.info("OK Autenticado com sucesso")
|
||||
return True
|
||||
else:
|
||||
logger.error(f"X Falha na autenticacao: {response.text}")
|
||||
return False
|
||||
|
||||
def ensure_authenticated(self):
|
||||
"""Garantir token valido"""
|
||||
if not self.token or time.time() >= self.token_expires:
|
||||
return self.authenticate()
|
||||
return True
|
||||
|
||||
def make_request(self, method, endpoint, **kwargs):
|
||||
"""Fazer requisicao com retry e renovacao automatica"""
|
||||
max_retries = 3
|
||||
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
if not self.ensure_authenticated():
|
||||
raise Exception("Falha na autenticacao")
|
||||
|
||||
headers = kwargs.get('headers', {})
|
||||
headers['Authorization'] = f"Bearer {self.token}"
|
||||
kwargs['headers'] = headers
|
||||
kwargs.setdefault('timeout', 30)
|
||||
|
||||
response = requests.request(method, f"{self.api_base}{endpoint}", **kwargs)
|
||||
|
||||
if response.status_code == 401:
|
||||
logger.warning("Token expirado, renovando...")
|
||||
self.authenticate()
|
||||
continue
|
||||
|
||||
if response.status_code == 429:
|
||||
wait_time = 2 ** attempt
|
||||
logger.warning(f"Rate limit. Aguardando {wait_time}s...")
|
||||
time.sleep(wait_time)
|
||||
continue
|
||||
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.error(f"Erro na tentativa {attempt + 1}: {e}")
|
||||
|
||||
if attempt == max_retries - 1:
|
||||
raise
|
||||
|
||||
time.sleep(2 ** attempt)
|
||||
|
||||
return None
|
||||
|
||||
def list_contexts(self):
|
||||
"""Listar contextos"""
|
||||
endpoint = f"/lighthouse/tenancies/{self.tenancy_id}/contexts"
|
||||
return self.make_request('GET', endpoint)
|
||||
|
||||
def list_workspaces(self, page=1, page_size=10):
|
||||
"""Listar workspaces"""
|
||||
endpoint = f"/lighthouse/tenancies/{self.tenancy_id}/workspaces"
|
||||
params = {"page": page, "page_size": page_size}
|
||||
return self.make_request('GET', endpoint, params=params)
|
||||
|
||||
def get_workspace(self, workspace_id):
|
||||
"""Obter workspace especifico"""
|
||||
endpoint = f"/lighthouse/tenancies/{self.tenancy_id}/workspaces/{workspace_id}"
|
||||
return self.make_request('GET', endpoint)
|
||||
|
||||
def get_all_workspaces(self):
|
||||
"""Obter todos os workspaces com paginacao automatica"""
|
||||
all_workspaces = []
|
||||
page = 1
|
||||
page_size = 100
|
||||
|
||||
while True:
|
||||
result = self.list_workspaces(page=page, page_size=page_size)
|
||||
workspaces = result['data']['workspaces']
|
||||
meta = result['meta']
|
||||
|
||||
all_workspaces.extend(workspaces)
|
||||
logger.info(f"Pagina {page}: {len(workspaces)} workspaces")
|
||||
|
||||
if page * page_size >= meta['total']:
|
||||
break
|
||||
|
||||
page += 1
|
||||
|
||||
return all_workspaces
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Cliente CLI para API Pier Cloud")
|
||||
parser.add_argument("--action", required=True,
|
||||
choices=["list-contexts", "list-workspaces", "get-workspace", "get-all-workspaces"],
|
||||
help="Acao a executar")
|
||||
parser.add_argument("--workspace-id", type=int, help="ID do workspace (para get-workspace)")
|
||||
parser.add_argument("--page", type=int, default=1, help="Numero da pagina")
|
||||
parser.add_argument("--page-size", type=int, default=10, help="Itens por pagina")
|
||||
parser.add_argument("--output", help="Arquivo de saida JSON")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
client = PierCloudClient()
|
||||
|
||||
if args.action == "list-contexts":
|
||||
result = client.list_contexts()
|
||||
contexts = result['data']['contexts']
|
||||
print(f"\nContextos: {len(contexts)}")
|
||||
for ctx in contexts:
|
||||
print(f" - {ctx['name']} ({ctx['provider']})")
|
||||
|
||||
elif args.action == "list-workspaces":
|
||||
result = client.list_workspaces(page=args.page, page_size=args.page_size)
|
||||
workspaces = result['data']['workspaces']
|
||||
meta = result['meta']
|
||||
print(f"\nWorkspaces: {len(workspaces)} de {meta['total']}")
|
||||
for ws in workspaces:
|
||||
print(f" - [{ws['id']}] {ws['name']}")
|
||||
|
||||
elif args.action == "get-workspace":
|
||||
if not args.workspace_id:
|
||||
print("X Erro: --workspace-id e obrigatorio")
|
||||
exit(1)
|
||||
result = client.get_workspace(args.workspace_id)
|
||||
ws = result['data']
|
||||
print(f"\nWorkspace: {ws['name']}")
|
||||
print(f"ID: {ws['id']}")
|
||||
print(f"Visualizacoes: {len(ws.get('views', []))}")
|
||||
|
||||
elif args.action == "get-all-workspaces":
|
||||
workspaces = client.get_all_workspaces()
|
||||
print(f"\nTotal: {len(workspaces)} workspaces")
|
||||
|
||||
if args.output:
|
||||
with open(args.output, 'w', encoding='utf-8') as f:
|
||||
json.dump(workspaces, f, indent=2, ensure_ascii=False)
|
||||
print(f"OK Salvo em {args.output}")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"X Erro: {e}")
|
||||
exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user