Skip to content
Merged
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
6 changes: 3 additions & 3 deletions .env.template
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
BASE_URL=https://portainer.example.com/api
USERNAME=admin
PASSWORD=password
PORTAINER_API_URL=https://portainer.example.com/api
PORTAINER_USERNAME=admin
PORTAINER_PASSWORD=password
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ services:
ports:
- 3000:3000
environment:
BASE_URL: https://portainer.example.com/api # Required, full URL including /api
USERNAME: your-username # Required, username to login with
PASSWORD: your-password # Required, password to login with
PORT: 3000 # Optional, default 3000
API_KEY: your-api-key # Optional, set to a any string to require authentication
PORTAINER_API_URL: https://portainer.example.com/api # Required, full URL including /api
PORTAINER_USERNAME: your-username # Required, username to login with
PORTAINER_PASSWORD: your-password # Required, password to login with
PORT: 3000 # Optional, default 3000
API_KEY: your-api-key # Optional, set to a any string to require authentication
```

To tell Portainer to pull the latest images and update the stack, make a simple POST request:
Expand Down
2 changes: 1 addition & 1 deletion openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"openapi": "3.1.0",
"info": {
"title": "Portainer Stack Webhook",
"version": "0.2.1"
"version": "0.2.2"
},
"paths": {
"/api/health": {
Expand Down
22 changes: 18 additions & 4 deletions src/env.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { violet, bold, cyan, red } from "./colors";
import { violet, bold, cyan, red, yellow } from "./colors";

function requireEnv(key: string): string {
const value = process.env[key];
Expand All @@ -13,9 +13,11 @@ function requireEnv(key: string): string {

export const env = {
port: Number(process.env.PORT || 3000),
baseUrl: requireEnv("BASE_URL"),
username: requireEnv("USERNAME"),
password: requireEnv("PASSWORD"),
portainer: {
apiUrl: process.env.BASE_URL || requireEnv("PORTAINER_API_URL"),
username: process.env.USERNAME || requireEnv("PORTAINER_USERNAME"),
password: process.env.PASSWORD || requireEnv("PORTAINER_PASSWORD"),
},
apiKey: process.env.API_KEY || undefined,
};

Expand All @@ -29,4 +31,16 @@ export function logEnvWarnings() {
`${cyan(bold("ℹ"))} ${violet("API_KEY")} not set - endpoints are not protected`,
);
}

maybeLogDeprecated("BASE_URL", "PORTAINER_API_URL");
maybeLogDeprecated("USERNAME", "PORTAINER_USERNAME");
maybeLogDeprecated("PASSWORD", "PORTAINER_PASSWORD");
}

function maybeLogDeprecated(key: string, replacement: string): void {
if (process.env[key]) {
console.log(
`${yellow(bold("⚠"))} ${violet(key)} is deprecated, use ${violet(replacement)} instead`,
);
}
}
12 changes: 6 additions & 6 deletions src/utils/portainer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ export interface PortainerApi {
}

export async function createPortainerApi(): Promise<PortainerApi> {
const { baseUrl, username, password } = env;
const { apiUrl, username, password } = env.portainer;

const checkResponse = (response: Response, expectedStatus = 200) => {
if (response.status !== expectedStatus)
throw new PortainerApiError(response);
};

const login = async (): Promise<PortainerLoginResponse> => {
const res = await fetch(`${baseUrl}/auth`, {
const res = await fetch(`${apiUrl}/auth`, {
body: JSON.stringify({ username, password }),
method: "POST",
headers: {
Expand All @@ -34,7 +34,7 @@ export async function createPortainerApi(): Promise<PortainerApi> {
};

const listStacks: PortainerApi["listStacks"] = async () => {
const res = await fetch(`${baseUrl}/stacks`, {
const res = await fetch(`${apiUrl}/stacks`, {
headers: authHeaders,
});

Expand All @@ -43,7 +43,7 @@ export async function createPortainerApi(): Promise<PortainerApi> {
};

const getStack: PortainerApi["getStack"] = async (id) => {
const res = await fetch(`${baseUrl}/stacks/${id}`, {
const res = await fetch(`${apiUrl}/stacks/${id}`, {
headers: authHeaders,
});

Expand All @@ -52,7 +52,7 @@ export async function createPortainerApi(): Promise<PortainerApi> {
};

const getStackFile: PortainerApi["getStackFile"] = async (id) => {
const res = await fetch(`${baseUrl}/stacks/${id}/file`, {
const res = await fetch(`${apiUrl}/stacks/${id}/file`, {
headers: authHeaders,
});

Expand All @@ -64,7 +64,7 @@ export async function createPortainerApi(): Promise<PortainerApi> {
id,
options,
): Promise<void> => {
const updateUrl = new URL(`${baseUrl}/stacks/${id}`);
const updateUrl = new URL(`${apiUrl}/stacks/${id}`);
updateUrl.searchParams.set("endpointId", String(options.endpointId));

const res = await fetch(updateUrl.href, {
Expand Down