diff --git a/.github/workflow-readme.md b/.github/workflow-readme.md
index 3e75fad2..8980d4af 100644
--- a/.github/workflow-readme.md
+++ b/.github/workflow-readme.md
@@ -30,7 +30,7 @@ The "Build PR on Dev" pipeline will be triggered when it identified pull request
- Squash merge the tracking pull request to main
- Create the release on GitHub from main branch
-- Create the new release branch from main branch (this is done automatically by pipeline create-release.yaml)
+- Create the new release branch from main branch
- Change the new release branch as the default branch in the repo and update the branch protection rules https://github.com/bcgov/itvr/settings/branches
- Update frontend/package.json
- version
diff --git a/django/Dockerfile b/django/Dockerfile
index d80005fe..94c81547 100644
--- a/django/Dockerfile
+++ b/django/Dockerfile
@@ -1,4 +1,4 @@
-FROM --platform=linux/amd64 python:3.9.1
+FROM python:3.9.1
ENV PYTHONUNBUFFERED=1
diff --git a/django/api/apps.py b/django/api/apps.py
index f844f05b..0c5c9e8a 100644
--- a/django/api/apps.py
+++ b/django/api/apps.py
@@ -16,6 +16,8 @@ def ready(self):
schedule_get_ncda_redeemed_rebates,
schedule_expire_expired_applications,
schedule_send_expiry_emails,
+ schedule_send_to_cra,
+ schedule_retrieve_from_cra,
)
if settings.RUN_JOBS and "qcluster" in sys.argv:
@@ -23,6 +25,8 @@ def ready(self):
schedule_get_ncda_redeemed_rebates()
schedule_expire_expired_applications()
schedule_send_expiry_emails()
+ schedule_send_to_cra()
+ schedule_retrieve_from_cra()
class ITVRAdminConfig(AdminConfig):
diff --git a/django/api/migrations/0023_crafiletracker.py b/django/api/migrations/0023_crafiletracker.py
new file mode 100644
index 00000000..da6907bd
--- /dev/null
+++ b/django/api/migrations/0023_crafiletracker.py
@@ -0,0 +1,26 @@
+# Generated by Django 4.0.9 on 2025-09-05 03:31
+
+from django.db import migrations, models
+import django_extensions.db.fields
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('api', '0022_legacygoelectricrebateapplication'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='CraFileTracker',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('created', django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, verbose_name='created')),
+ ('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, verbose_name='modified')),
+ ('sequence_number', models.IntegerField()),
+ ],
+ options={
+ 'db_table': 'cra_file_tracker',
+ },
+ ),
+ ]
diff --git a/django/api/models/__init__.py b/django/api/models/__init__.py
index 0dacf459..86f48421 100644
--- a/django/api/models/__init__.py
+++ b/django/api/models/__init__.py
@@ -4,3 +4,4 @@
from . import go_electric_rebate_application
from . import household_member
from . import go_electric_rebate
+from . import cra_file_tracker
diff --git a/django/api/models/cra_file_tracker.py b/django/api/models/cra_file_tracker.py
new file mode 100644
index 00000000..351f37aa
--- /dev/null
+++ b/django/api/models/cra_file_tracker.py
@@ -0,0 +1,11 @@
+from django_extensions.db.models import TimeStampedModel
+from django.db.models import (
+ IntegerField,
+)
+
+
+class CraFileTracker(TimeStampedModel):
+ sequence_number = IntegerField()
+
+ class Meta:
+ db_table = "cra_file_tracker"
diff --git a/django/api/scheduled_jobs.py b/django/api/scheduled_jobs.py
index 4c4d5498..9a2508e3 100644
--- a/django/api/scheduled_jobs.py
+++ b/django/api/scheduled_jobs.py
@@ -59,3 +59,29 @@ def schedule_send_expiry_emails():
)
except IntegrityError:
pass
+
+
+def schedule_send_to_cra():
+ try:
+ schedule(
+ "api.tasks.send_to_cra",
+ name="send_to_cra",
+ schedule_type="C",
+ cron="00 * * * *",
+ q_options={"timeout": 900, "ack_failure": True},
+ )
+ except IntegrityError:
+ pass
+
+
+def schedule_retrieve_from_cra():
+ try:
+ schedule(
+ "api.tasks.retrieve_from_cra",
+ name="retrieve_from_cra",
+ schedule_type="C",
+ cron="30 * * * *",
+ q_options={"timeout": 900, "ack_failure": True},
+ )
+ except IntegrityError:
+ pass
diff --git a/django/api/services/cra.py b/django/api/services/cra.py
index c38aaf0d..1bd8b188 100644
--- a/django/api/services/cra.py
+++ b/django/api/services/cra.py
@@ -1,7 +1,10 @@
import requests
import json
+import io
from unidecode import unidecode
from django.conf import settings
+from api.services.minio import get_minio_object
+import paramiko
def read(file):
@@ -42,9 +45,8 @@ def read(file):
return results
-def write(
- data, today="20220516", program_code="BCVR", cra_env="A", cra_sequence="00001"
-):
+def write(data, today="20220516", program_code="BCVR", cra_env="A", cra_sequence=1):
+ sequence_number = (str(cra_sequence)).rjust(5, "0")
file = ""
# Number of records to write.
@@ -58,7 +60,7 @@ def write(
file += today #
file += " " # Blank space
- file += program_code + cra_env + cra_sequence
+ file += program_code + cra_env + sequence_number
file += " " * 99 # Blank space
@@ -82,7 +84,7 @@ def write(
file += today # Request date
file += " " # Blank space
- file += program_code + cra_env + cra_sequence
+ file += program_code + cra_env + sequence_number
file += " " * 6 # Blank space
@@ -124,3 +126,40 @@ def encrypt(to_encrypt):
)
response.raise_for_status()
return response.content
+
+
+def get_to_cra_filename(program_code="BCVR", cra_env="A", cra_sequence=1, directory=""):
+ filename = "{directory}/TO.{cra_env}TO#@@00.R7005.IN.{program_code}.{cra_env}{cra_sequence:05}.p7m".format(
+ directory=directory,
+ cra_env=cra_env,
+ cra_sequence=cra_sequence,
+ program_code=program_code,
+ )
+ return filename
+
+
+def get_from_cra_filename(
+ program_code="BCVR", cra_env="A", cra_sequence=1, directory=""
+):
+ filename = "{directory}/{cra_env}{program_code}{cra_sequence:05}.p7m".format(
+ directory=directory,
+ cra_env=cra_env,
+ cra_sequence=cra_sequence,
+ program_code=program_code,
+ )
+ return filename
+
+
+def get_ssh_client():
+ pkey_file = get_minio_object(settings.SSH_PKEY_FILENAME)
+ pkey = paramiko.RSAKey.from_private_key(io.StringIO(pkey_file.data.decode("utf-8")))
+ client = paramiko.SSHClient()
+ client.set_missing_host_key_policy(paramiko.AutoAddPolicy)
+ client.connect(
+ settings.CRA_SFTP_HOST,
+ port=int(settings.CRA_SFTP_PORT),
+ username=settings.CRA_SFTP_USERNAME,
+ pkey=pkey,
+ disabled_algorithms={"pubkeys": ["rsa-sha2-256", "rsa-sha2-512"]},
+ )
+ return client
diff --git a/django/api/services/minio.py b/django/api/services/minio.py
new file mode 100644
index 00000000..c044d8d8
--- /dev/null
+++ b/django/api/services/minio.py
@@ -0,0 +1,16 @@
+from minio import Minio
+from django.conf import settings
+
+
+def get_minio_client():
+ return Minio(
+ settings.MINIO_ENDPOINT_INTERNAL,
+ settings.MINIO_ACCESS_KEY,
+ settings.MINIO_SECRET_KEY,
+ secure=(settings.MINIO_USE_SSL == "True"),
+ )
+
+
+def get_minio_object(object_name):
+ client = get_minio_client()
+ return client.get_object(settings.MINIO_BUCKET_NAME, object_name)
diff --git a/django/api/services/rebate.py b/django/api/services/rebate.py
index 02461a97..dcd47344 100644
--- a/django/api/services/rebate.py
+++ b/django/api/services/rebate.py
@@ -87,3 +87,34 @@ def update_application_statuses(rebates, applications):
created=False,
update_fields={"status"},
)
+
+
+def get_rebate_data_for_cra():
+ result = []
+ rebates = GoElectricRebateApplication.objects.filter(
+ status=GoElectricRebateApplication.Status.VERIFIED
+ )
+ for rebate in rebates:
+ result.append(
+ {
+ "sin": rebate.sin,
+ "years": [rebate.tax_year],
+ "given_name": rebate.first_name,
+ "family_name": rebate.last_name,
+ "birth_date": rebate.date_of_birth.strftime("%Y%m%d"),
+ "application_id": rebate.id,
+ }
+ )
+ if rebate.application_type == "household":
+ household_member = rebate.householdmember
+ result.append(
+ {
+ "sin": household_member.sin,
+ "years": [rebate.tax_year],
+ "given_name": household_member.first_name,
+ "family_name": household_member.last_name,
+ "birth_date": household_member.date_of_birth.strftime("%Y%m%d"),
+ "application_id": rebate.id,
+ }
+ )
+ return result
diff --git a/django/api/settings.py b/django/api/settings.py
index 3bdbf53b..c4998c6d 100644
--- a/django/api/settings.py
+++ b/django/api/settings.py
@@ -173,6 +173,8 @@
MINIO_SECRET_KEY = os.getenv("MINIO_ROOT_PASSWORD")
MINIO_BUCKET_NAME = os.getenv("MINIO_BUCKET_NAME")
MINIO_ENDPOINT = os.getenv("MINIO_ENDPOINT")
+MINIO_ENDPOINT_INTERNAL = os.getenv("MINIO_ENDPOINT_INTERNAL")
+MINIO_USE_SSL = os.getenv("MINIO_USE_SSL", "True")
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
@@ -227,7 +229,7 @@
# NCDA Sharepoint config
NCDA_CLIENT_ID = os.getenv(
"NCDA_CLIENT_ID",
- "d4d97d40-bb26-44f8-ba70-c677471d6cc1@1d4864aa-f2da-42dc-a62a-34b4dd790b6a",
+ "d7a76f01-ddff-43a3-98d4-e20a3c52a0e5@1d4864aa-f2da-42dc-a62a-34b4dd790b6a",
)
NCDA_CLIENT_SECRET = os.getenv("NCDA_CLIENT_SECRET")
NCDA_RESOURCE = os.getenv(
@@ -251,9 +253,15 @@
CLAMD_HOST = os.getenv("CLAMD_HOST", "clamav")
CLAMD_PORT = int(os.getenv("CLAMD_PORT", 3310))
-USE_CRYPTO_SERVICE = os.getenv("USE_CRYPTO_SERVICE", False)
CRYPTO_SERVICE_URL = os.getenv("CRYPTO_SERVICE_URL", "http://spring:8080")
CRA_CERTIFICATE = os.getenv("CRA_CERTIFICATE")
CRA_CERTIFICATE_CRL_DN = os.getenv("CRA_CERTIFICATE_CRL_DN")
EPF_FILENAME = os.getenv("EPF_FILENAME")
EPF_PASSWORD = os.getenv("EPF_PASSWORD")
+SSH_PKEY_FILENAME = os.getenv("SSH_PKEY_FILENAME")
+CRA_SFTP_HOST = os.getenv("CRA_SFTP_HOST")
+CRA_SFTP_PORT = os.getenv("CRA_SFTP_PORT")
+CRA_SFTP_USERNAME = os.getenv("CRA_SFTP_USERNAME")
+CRA_SFTP_GET_PATH = os.getenv("CRA_SFTP_GET_PATH")
+CRA_SFTP_PUT_PATH = os.getenv("CRA_SFTP_PUT_PATH")
+CRA_PROGRAM_CODE = os.getenv("CRA_PROGRAM_CODE")
diff --git a/django/api/site.py b/django/api/site.py
index 4a48022e..9e98dc27 100644
--- a/django/api/site.py
+++ b/django/api/site.py
@@ -1,133 +1,7 @@
-from datetime import date
from django.contrib.admin import AdminSite
-from django.contrib import messages
-from django.urls import path
-from django.http import HttpResponse, HttpResponseRedirect
-from django.shortcuts import render
-
-from .services.rebate import get_applications, save_rebates, update_application_statuses
-from .services.calculate_rebate import get_cra_results_individuals_only
-from sequences import get_next_value
-from django.conf import settings
-from django import forms
-from .models.go_electric_rebate_application import GoElectricRebateApplication
-from .services import cra
-from django.db import transaction
-
-
-class UploadFileForm(forms.Form):
- adjective = "encrypted" if settings.USE_CRYPTO_SERVICE else "decrypted"
- cra_response_file = forms.FileField(
- help_text="Please upload the {adjective} CRA OUT file.".format(adjective=adjective)
- )
class ITVRAdminSite(AdminSite):
- def get_urls(self):
- urls = super().get_urls()
- custom_urls = [
- path(
- "cra-download", self.admin_view(self.download_file), name="cra-download"
- ),
- path("cra-upload", self.admin_view(self.upload_file), name="cra-upload"),
- ]
- return custom_urls + urls
-
- # Create the filename for a CRA in file.
- # This needs to be named properly on the file before being encrypted.
- # '.p7m' is automatically added when the file is encrypted using Entrust.
- def get_cra_filename(self, program_code="BCVR", cra_env="A", cra_sequence="00001"):
- filename = "TO.{cra_env}TO#@@00.R7005.IN.{program_code}.{cra_env}{cra_sequence:05}".format(
- cra_env=cra_env, cra_sequence=cra_sequence, program_code=program_code
- )
- return filename
-
- @transaction.atomic
- def upload_file(self, request):
- if request.method == "POST":
- form = UploadFileForm(request.POST, request.FILES)
- if form.is_valid():
- file = request.FILES["cra_response_file"]
- if settings.USE_CRYPTO_SERVICE and file.name.endswith(".p7m"):
- content = cra.decrypt_file(file)
- else:
- content = file.read().decode(encoding="utf-8", errors="replace")
- data = cra.read(content)
- rebates = get_cra_results_individuals_only(data)
- associated_applications = get_applications(rebates)
- save_rebates(rebates, associated_applications)
- update_application_statuses(rebates, associated_applications)
- messages.add_message(
- request, messages.SUCCESS, "CRA OUT file uploaded successfully"
- )
- return HttpResponseRedirect("/admin")
- else:
- form = UploadFileForm()
- return render(request, "upload.html", {"form": form})
-
- @transaction.atomic
- def download_file(self, request):
- rebates = GoElectricRebateApplication.objects.filter(
- status=GoElectricRebateApplication.Status.VERIFIED
- )
-
- if rebates.count() == 0:
- response = HttpResponse("No income to check.")
- return response
-
- data = []
- cra_env = settings.CRA_ENVIRONMENT
- cra_sequence = get_next_value("cra_sequence")
- program_code = "BCVR"
-
- for rebate in rebates:
- data.append(
- {
- "sin": rebate.sin,
- "years": [rebate.tax_year],
- "given_name": rebate.first_name,
- "family_name": rebate.last_name,
- "birth_date": rebate.date_of_birth.strftime("%Y%m%d"),
- "application_id": rebate.id,
- }
- )
-
- # TODO this should be some kind of enum like the status is.
- if rebate.application_type == "household":
- household_member = rebate.householdmember
- data.append(
- {
- "sin": household_member.sin,
- "years": [rebate.tax_year],
- "given_name": household_member.first_name,
- "family_name": household_member.last_name,
- "birth_date": household_member.date_of_birth.strftime("%Y%m%d"),
- "application_id": rebate.id,
- }
- )
-
- filename = self.get_cra_filename(program_code, cra_env, cra_sequence)
- today = date.today().strftime("%Y%m%d")
- content = cra.write(
- data,
- today=today,
- program_code=program_code,
- cra_env=cra_env,
- cra_sequence=f"{cra_sequence:05}",
- )
-
- if settings.USE_CRYPTO_SERVICE:
- filename = filename + ".p7m"
- encrypted_content = cra.encrypt(content)
- response = HttpResponse(
- encrypted_content, content_type="application/octet-stream"
- )
- else:
- response = HttpResponse(content, content_type="text/plain")
-
- response["Content-Disposition"] = "attachment; filename=" + filename
- return response
-
def refine_app(self, app):
models = app.get("models")
if models is not None:
diff --git a/django/api/tasks.py b/django/api/tasks.py
index e682c583..3c0da580 100644
--- a/django/api/tasks.py
+++ b/django/api/tasks.py
@@ -1,22 +1,32 @@
import requests
import json
+import traceback
from django.utils import timezone
from django.conf import settings
from email.header import Header
from email.utils import formataddr
from requests.auth import HTTPBasicAuth
+from api.models.cra_file_tracker import CraFileTracker
from api.models.go_electric_rebate import GoElectricRebate
from api.models.go_electric_rebate_application import (
GoElectricRebateApplication,
)
-from datetime import timedelta, datetime
+from datetime import timedelta, datetime, date
+from api.services import cra
from api.services.ncda import (
notify,
get_rebates_redeemed_since,
get_rebate_by_id,
delete_rebate,
)
+from api.services.rebate import (
+ get_rebate_data_for_cra,
+ get_applications,
+ save_rebates,
+ update_application_statuses,
+)
+from api.services.calculate_rebate import get_cra_results_individuals_only
from api.constants import (
FOUR_THOUSAND_REBATE,
ONE_THOUSAND_REBATE,
@@ -26,6 +36,7 @@
from django_q.tasks import async_task
from django.db import transaction
from django.db.models import Q
+from sequences import get_next_value
def get_email_service_token() -> str:
@@ -610,3 +621,77 @@ def send_expiry_emails(days_offset=14):
warning_email_application_ids.append(application.id)
print("expiry emails sent for: %s" % expiry_email_application_ids)
print("warning emails sent for: %s" % warning_email_application_ids)
+
+
+def send_to_cra():
+ ssh_client = cra.get_ssh_client()
+ sftp_client = ssh_client.open_sftp()
+ try:
+ file_in_progress = CraFileTracker.objects.all().exists()
+ if file_in_progress:
+ return
+ rebates = get_rebate_data_for_cra()
+ if not rebates:
+ return
+ with transaction.atomic():
+ cra_env = settings.CRA_ENVIRONMENT
+ cra_sequence = get_next_value("cra_sequence")
+ program_code = settings.CRA_PROGRAM_CODE
+ filename = cra.get_to_cra_filename(
+ program_code=program_code,
+ cra_env=cra_env,
+ cra_sequence=cra_sequence,
+ directory=settings.CRA_SFTP_PUT_PATH,
+ )
+ today = date.today().strftime("%Y%m%d")
+ content = cra.write(
+ rebates,
+ today=today,
+ program_code=program_code,
+ cra_env=cra_env,
+ cra_sequence=cra_sequence,
+ )
+ encrypted_content = cra.encrypt(content)
+ CraFileTracker(sequence_number=cra_sequence).save()
+ sftp_file = sftp_client.open(filename, mode="w")
+ sftp_file.write(encrypted_content)
+ sftp_file.close()
+ except Exception:
+ print("Error sending data to CRA")
+ traceback.print_exc()
+ finally:
+ sftp_client.close()
+ ssh_client.close()
+
+
+def retrieve_from_cra():
+ ssh_client = cra.get_ssh_client()
+ sftp_client = ssh_client.open_sftp()
+ try:
+ file_in_progress = CraFileTracker.objects.all().first()
+ if not file_in_progress:
+ return
+ with transaction.atomic():
+ sequence_number = file_in_progress.sequence_number
+ filename = cra.get_from_cra_filename(
+ program_code=settings.CRA_PROGRAM_CODE,
+ cra_env=settings.CRA_ENVIRONMENT,
+ cra_sequence=sequence_number,
+ directory=settings.CRA_SFTP_GET_PATH,
+ )
+ # will raise exception if file does not exist
+ sftp_file = sftp_client.open(filename, mode="r")
+ content = cra.decrypt_file(sftp_file)
+ data = cra.read(content)
+ rebates = get_cra_results_individuals_only(data)
+ associated_applications = get_applications(rebates)
+ save_rebates(rebates, associated_applications)
+ update_application_statuses(rebates, associated_applications)
+ file_in_progress.delete()
+ sftp_file.close()
+ except Exception:
+ print("Error retrieving data from CRA")
+ traceback.print_exc()
+ finally:
+ sftp_client.close()
+ ssh_client.close()
diff --git a/django/requirements.txt b/django/requirements.txt
index c68437a4..c66c200a 100644
--- a/django/requirements.txt
+++ b/django/requirements.txt
@@ -27,6 +27,7 @@ gunicorn==20.1.0
idna==3.3
jmespath==1.0.0
minio==7.1.2
+paramiko==4.0.0
Pillow==9.3.0
psycopg2-binary==2.9.3
pyasn1==0.4.8
diff --git a/django/templates/admin/index.html b/django/templates/admin/index.html
index f8b7831f..07eb7b5f 100644
--- a/django/templates/admin/index.html
+++ b/django/templates/admin/index.html
@@ -55,19 +55,6 @@
{{ app.name }}
{% endfor %}
-
diff --git a/docker-compose.yml b/docker-compose.yml
index c5d5d9ba..da696dbf 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -2,7 +2,6 @@ version: "3.9"
services:
db:
- platform: linux/amd64
image: postgres:14
environment:
- POSTGRES_DB=itvr
@@ -16,8 +15,7 @@ services:
timeout: 5s
retries: 5
minio:
- platform: linux/amd64
- image: minio/minio
+ image: minio/minio:RELEASE.2025-04-22T22-12-26Z
hostname: "minio"
volumes:
- ./minio:/minio_files
@@ -28,7 +26,6 @@ services:
- 9000:9000
- 9001:9001
createbuckets:
- platform: linux/amd64
image: minio/mc
depends_on:
- minio
@@ -68,12 +65,6 @@ services:
- VIRUS_SCANNING_ENABLED=True
- CLAMD_HOST=clamav
- CLAMD_PORT=3310
- - USE_CRYPTO_SERVICE
- - CRYPTO_SERVICE_URL
- - CRA_CERTIFICATE
- - CRA_CERTIFICATE_CRL_DN
- - EPF_FILENAME
- - EPF_PASSWORD
volumes:
- ./django:/api
ports:
@@ -104,6 +95,18 @@ services:
- BCC_EMAIL
- NCDA_CLIENT_SECRET
- RUN_JOBS=True
+ - MINIO_USE_SSL=False
+ - CRA_CERTIFICATE
+ - CRA_CERTIFICATE_CRL_DN
+ - EPF_FILENAME
+ - EPF_PASSWORD
+ - SSH_PKEY_FILENAME
+ - CRA_SFTP_HOST
+ - CRA_SFTP_PORT
+ - CRA_SFTP_USERNAME
+ - CRA_SFTP_GET_PATH
+ - CRA_SFTP_PUT_PATH
+ - CRA_PROGRAM_CODE
volumes:
- ./django:/api
depends_on:
@@ -130,5 +133,4 @@ services:
volumes:
- ./spring:/app
clamav:
- platform: linux/amd64
image: clamav/clamav
diff --git a/frontend/Dockerfile b/frontend/Dockerfile
index ed227f08..d7ea32a9 100644
--- a/frontend/Dockerfile
+++ b/frontend/Dockerfile
@@ -1,4 +1,4 @@
-FROM --platform=linux/amd64 node:16
+FROM node:16
WORKDIR /web
diff --git a/frontend/package.json b/frontend/package.json
index bdeca866..66982181 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,6 +1,6 @@
{
"name": "frontend",
- "version": "1.31.0",
+ "version": "1.32.0",
"private": true,
"dependencies": {
"@date-io/date-fns": "^2.14.0",
diff --git a/minio.env b/minio.env
index 964a3505..706cb618 100644
--- a/minio.env
+++ b/minio.env
@@ -1,4 +1,5 @@
MINIO_ENDPOINT=http://minio:9000
+MINIO_ENDPOINT_INTERNAL=minio:9000
MINIO_ROOT_USER=minioadmin
MINIO_ROOT_PASSWORD=minioadmin
MINIO_BUCKET_NAME=itvr
diff --git a/openshift/templates/programpaused-page/Dockerfile b/openshift/templates/programpaused-page/Dockerfile
new file mode 100644
index 00000000..d0596728
--- /dev/null
+++ b/openshift/templates/programpaused-page/Dockerfile
@@ -0,0 +1,5 @@
+FROM artifacts.developer.gov.bc.ca/docker-remote/httpd:2.4
+COPY ./httpd.conf /usr/local/apache2/conf/httpd.conf
+COPY ./public-html/ /usr/local/apache2/htdocs/
+RUN chgrp -R root /usr/local/apache2/logs \
+ && chmod -R g+w /usr/local/apache2/logs
\ No newline at end of file
diff --git a/openshift/templates/programpaused-page/httpd.conf b/openshift/templates/programpaused-page/httpd.conf
new file mode 100644
index 00000000..d891e310
--- /dev/null
+++ b/openshift/templates/programpaused-page/httpd.conf
@@ -0,0 +1,551 @@
+#
+# This is the main Apache HTTP server configuration file. It contains the
+# configuration directives that give the server its instructions.
+# See
for detailed information.
+# In particular, see
+#
+# for a discussion of each configuration directive.
+#
+# Do NOT simply read the instructions in here without understanding
+# what they do. They're here only as hints or reminders. If you are unsure
+# consult the online docs. You have been warned.
+#
+# Configuration and logfile names: If the filenames you specify for many
+# of the server's control files begin with "/" (or "drive:/" for Win32), the
+# server will use that explicit path. If the filenames do *not* begin
+# with "/", the value of ServerRoot is prepended -- so "logs/access_log"
+# with ServerRoot set to "/usr/local/apache2" will be interpreted by the
+# server as "/usr/local/apache2/logs/access_log", whereas "/logs/access_log"
+# will be interpreted as '/logs/access_log'.
+
+#
+# ServerRoot: The top of the directory tree under which the server's
+# configuration, error, and log files are kept.
+#
+# Do not add a slash at the end of the directory path. If you point
+# ServerRoot at a non-local disk, be sure to specify a local disk on the
+# Mutex directive, if file-based mutexes are used. If you wish to share the
+# same ServerRoot for multiple httpd daemons, you will need to change at
+# least PidFile.
+#
+ServerRoot "/usr/local/apache2"
+
+#
+# Mutex: Allows you to set the mutex mechanism and mutex file directory
+# for individual mutexes, or change the global defaults
+#
+# Uncomment and change the directory if mutexes are file-based and the default
+# mutex file directory is not on a local disk or is not appropriate for some
+# other reason.
+#
+# Mutex default:logs
+
+#
+# Listen: Allows you to bind Apache to specific IP addresses and/or
+# ports, instead of the default. See also the
+# directive.
+#
+# Change this to Listen on specific IP addresses as shown below to
+# prevent Apache from glomming onto all bound IP addresses.
+#
+#Listen 12.34.56.78:80
+Listen 0.0.0.0:8080
+
+#
+# Dynamic Shared Object (DSO) Support
+#
+# To be able to use the functionality of a module which was built as a DSO you
+# have to place corresponding `LoadModule' lines at this location so the
+# directives contained in it are actually available _before_ they are used.
+# Statically compiled modules (those listed by `httpd -l') do not need
+# to be loaded here.
+#
+# Example:
+# LoadModule foo_module modules/mod_foo.so
+#
+LoadModule mpm_event_module modules/mod_mpm_event.so
+#LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
+#LoadModule mpm_worker_module modules/mod_mpm_worker.so
+LoadModule authn_file_module modules/mod_authn_file.so
+#LoadModule authn_dbm_module modules/mod_authn_dbm.so
+#LoadModule authn_anon_module modules/mod_authn_anon.so
+#LoadModule authn_dbd_module modules/mod_authn_dbd.so
+#LoadModule authn_socache_module modules/mod_authn_socache.so
+LoadModule authn_core_module modules/mod_authn_core.so
+LoadModule authz_host_module modules/mod_authz_host.so
+LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
+LoadModule authz_user_module modules/mod_authz_user.so
+#LoadModule authz_dbm_module modules/mod_authz_dbm.so
+#LoadModule authz_owner_module modules/mod_authz_owner.so
+#LoadModule authz_dbd_module modules/mod_authz_dbd.so
+LoadModule authz_core_module modules/mod_authz_core.so
+#LoadModule authnz_ldap_module modules/mod_authnz_ldap.so
+#LoadModule authnz_fcgi_module modules/mod_authnz_fcgi.so
+LoadModule access_compat_module modules/mod_access_compat.so
+LoadModule auth_basic_module modules/mod_auth_basic.so
+#LoadModule auth_form_module modules/mod_auth_form.so
+#LoadModule auth_digest_module modules/mod_auth_digest.so
+#LoadModule allowmethods_module modules/mod_allowmethods.so
+#LoadModule isapi_module modules/mod_isapi.so
+#LoadModule file_cache_module modules/mod_file_cache.so
+#LoadModule cache_module modules/mod_cache.so
+#LoadModule cache_disk_module modules/mod_cache_disk.so
+#LoadModule cache_socache_module modules/mod_cache_socache.so
+#LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
+#LoadModule socache_dbm_module modules/mod_socache_dbm.so
+#LoadModule socache_memcache_module modules/mod_socache_memcache.so
+#LoadModule socache_redis_module modules/mod_socache_redis.so
+#LoadModule watchdog_module modules/mod_watchdog.so
+#LoadModule macro_module modules/mod_macro.so
+#LoadModule dbd_module modules/mod_dbd.so
+#LoadModule bucketeer_module modules/mod_bucketeer.so
+#LoadModule dumpio_module modules/mod_dumpio.so
+#LoadModule echo_module modules/mod_echo.so
+#LoadModule example_hooks_module modules/mod_example_hooks.so
+#LoadModule case_filter_module modules/mod_case_filter.so
+#LoadModule case_filter_in_module modules/mod_case_filter_in.so
+#LoadModule example_ipc_module modules/mod_example_ipc.so
+#LoadModule buffer_module modules/mod_buffer.so
+#LoadModule data_module modules/mod_data.so
+#LoadModule ratelimit_module modules/mod_ratelimit.so
+LoadModule reqtimeout_module modules/mod_reqtimeout.so
+#LoadModule ext_filter_module modules/mod_ext_filter.so
+#LoadModule request_module modules/mod_request.so
+#LoadModule include_module modules/mod_include.so
+LoadModule filter_module modules/mod_filter.so
+#LoadModule reflector_module modules/mod_reflector.so
+#LoadModule substitute_module modules/mod_substitute.so
+#LoadModule sed_module modules/mod_sed.so
+#LoadModule charset_lite_module modules/mod_charset_lite.so
+#LoadModule deflate_module modules/mod_deflate.so
+#LoadModule xml2enc_module modules/mod_xml2enc.so
+#LoadModule proxy_html_module modules/mod_proxy_html.so
+#LoadModule brotli_module modules/mod_brotli.so
+LoadModule mime_module modules/mod_mime.so
+#LoadModule ldap_module modules/mod_ldap.so
+LoadModule log_config_module modules/mod_log_config.so
+#LoadModule log_debug_module modules/mod_log_debug.so
+#LoadModule log_forensic_module modules/mod_log_forensic.so
+#LoadModule logio_module modules/mod_logio.so
+#LoadModule lua_module modules/mod_lua.so
+LoadModule env_module modules/mod_env.so
+#LoadModule mime_magic_module modules/mod_mime_magic.so
+#LoadModule cern_meta_module modules/mod_cern_meta.so
+#LoadModule expires_module modules/mod_expires.so
+LoadModule headers_module modules/mod_headers.so
+#LoadModule ident_module modules/mod_ident.so
+#LoadModule usertrack_module modules/mod_usertrack.so
+#LoadModule unique_id_module modules/mod_unique_id.so
+LoadModule setenvif_module modules/mod_setenvif.so
+LoadModule version_module modules/mod_version.so
+#LoadModule remoteip_module modules/mod_remoteip.so
+#LoadModule proxy_module modules/mod_proxy.so
+#LoadModule proxy_connect_module modules/mod_proxy_connect.so
+#LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
+#LoadModule proxy_http_module modules/mod_proxy_http.so
+#LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
+#LoadModule proxy_scgi_module modules/mod_proxy_scgi.so
+#LoadModule proxy_uwsgi_module modules/mod_proxy_uwsgi.so
+#LoadModule proxy_fdpass_module modules/mod_proxy_fdpass.so
+#LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
+#LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
+#LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
+#LoadModule proxy_express_module modules/mod_proxy_express.so
+#LoadModule proxy_hcheck_module modules/mod_proxy_hcheck.so
+#LoadModule session_module modules/mod_session.so
+#LoadModule session_cookie_module modules/mod_session_cookie.so
+#LoadModule session_crypto_module modules/mod_session_crypto.so
+#LoadModule session_dbd_module modules/mod_session_dbd.so
+#LoadModule slotmem_shm_module modules/mod_slotmem_shm.so
+#LoadModule slotmem_plain_module modules/mod_slotmem_plain.so
+#LoadModule ssl_module modules/mod_ssl.so
+#LoadModule optional_hook_export_module modules/mod_optional_hook_export.so
+#LoadModule optional_hook_import_module modules/mod_optional_hook_import.so
+#LoadModule optional_fn_import_module modules/mod_optional_fn_import.so
+#LoadModule optional_fn_export_module modules/mod_optional_fn_export.so
+#LoadModule dialup_module modules/mod_dialup.so
+#LoadModule http2_module modules/mod_http2.so
+#LoadModule proxy_http2_module modules/mod_proxy_http2.so
+#LoadModule md_module modules/mod_md.so
+#LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so
+#LoadModule lbmethod_bytraffic_module modules/mod_lbmethod_bytraffic.so
+#LoadModule lbmethod_bybusyness_module modules/mod_lbmethod_bybusyness.so
+#LoadModule lbmethod_heartbeat_module modules/mod_lbmethod_heartbeat.so
+LoadModule unixd_module modules/mod_unixd.so
+#LoadModule heartbeat_module modules/mod_heartbeat.so
+#LoadModule heartmonitor_module modules/mod_heartmonitor.so
+#LoadModule dav_module modules/mod_dav.so
+LoadModule status_module modules/mod_status.so
+LoadModule autoindex_module modules/mod_autoindex.so
+#LoadModule asis_module modules/mod_asis.so
+#LoadModule info_module modules/mod_info.so
+#LoadModule suexec_module modules/mod_suexec.so
+
+ #LoadModule cgid_module modules/mod_cgid.so
+
+
+ #LoadModule cgi_module modules/mod_cgi.so
+
+#LoadModule dav_fs_module modules/mod_dav_fs.so
+#LoadModule dav_lock_module modules/mod_dav_lock.so
+#LoadModule vhost_alias_module modules/mod_vhost_alias.so
+#LoadModule negotiation_module modules/mod_negotiation.so
+LoadModule dir_module modules/mod_dir.so
+#LoadModule imagemap_module modules/mod_imagemap.so
+#LoadModule actions_module modules/mod_actions.so
+#LoadModule speling_module modules/mod_speling.so
+#LoadModule userdir_module modules/mod_userdir.so
+LoadModule alias_module modules/mod_alias.so
+#LoadModule rewrite_module modules/mod_rewrite.so
+
+
+#
+# If you wish httpd to run as a different user or group, you must run
+# httpd as root initially and it will switch.
+#
+# User/Group: The name (or #number) of the user/group to run httpd as.
+# It is usually good practice to create a dedicated user and group for
+# running httpd, as with most system services.
+#
+User daemon
+Group daemon
+
+
+
+# 'Main' server configuration
+#
+# The directives in this section set up the values used by the 'main'
+# server, which responds to any requests that aren't handled by a
+# definition. These values also provide defaults for
+# any containers you may define later in the file.
+#
+# All of these directives may appear inside containers,
+# in which case these default settings will be overridden for the
+# virtual host being defined.
+#
+
+#
+# ServerAdmin: Your address, where problems with the server should be
+# e-mailed. This address appears on some server-generated pages, such
+# as error documents. e.g. admin@your-domain.com
+#
+ServerAdmin you@example.com
+
+#
+# ServerName gives the name and port that the server uses to identify itself.
+# This can often be determined automatically, but we recommend you specify
+# it explicitly to prevent problems during startup.
+#
+# If your host doesn't have a registered DNS name, enter its IP address here.
+#
+#ServerName www.example.com:80
+
+#
+# Deny access to the entirety of your server's filesystem. You must
+# explicitly permit access to web content directories in other
+# blocks below.
+#
+
+ AllowOverride none
+ Require all denied
+
+
+#
+# Note that from this point forward you must specifically allow
+# particular features to be enabled - so if something's not working as
+# you might expect, make sure that you have specifically enabled it
+# below.
+#
+
+#
+# DocumentRoot: The directory out of which you will serve your
+# documents. By default, all requests are taken from this directory, but
+# symbolic links and aliases may be used to point to other locations.
+#
+DocumentRoot "/usr/local/apache2/htdocs"
+
+ #
+ # Possible values for the Options directive are "None", "All",
+ # or any combination of:
+ # Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
+ #
+ # Note that "MultiViews" must be named *explicitly* --- "Options All"
+ # doesn't give it to you.
+ #
+ # The Options directive is both complicated and important. Please see
+ # http://httpd.apache.org/docs/2.4/mod/core.html#options
+ # for more information.
+ #
+ Options Indexes FollowSymLinks
+
+ #
+ # AllowOverride controls what directives may be placed in .htaccess files.
+ # It can be "All", "None", or any combination of the keywords:
+ # AllowOverride FileInfo AuthConfig Limit
+ #
+ AllowOverride None
+
+ #
+ # Controls who can get stuff from this server.
+ #
+ Require all granted
+
+
+#
+# DirectoryIndex: sets the file that Apache will serve if a directory
+# is requested.
+#
+
+ DirectoryIndex index.html
+
+
+#
+# The following lines prevent .htaccess and .htpasswd files from being
+# viewed by Web clients.
+#
+
+ Require all denied
+
+
+#
+# ErrorLog: The location of the error log file.
+# If you do not specify an ErrorLog directive within a
+# container, error messages relating to that virtual host will be
+# logged here. If you *do* define an error logfile for a
+# container, that host's errors will be logged there and not here.
+#
+ErrorLog /proc/self/fd/2
+
+#
+# LogLevel: Control the number of messages logged to the error_log.
+# Possible values include: debug, info, notice, warn, error, crit,
+# alert, emerg.
+#
+LogLevel warn
+
+
+ #
+ # The following directives define some format nicknames for use with
+ # a CustomLog directive (see below).
+ #
+ LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+ LogFormat "%h %l %u %t \"%r\" %>s %b" common
+
+
+ # You need to enable mod_logio.c to use %I and %O
+ LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
+
+
+ #
+ # The location and format of the access logfile (Common Logfile Format).
+ # If you do not define any access logfiles within a
+ # container, they will be logged here. Contrariwise, if you *do*
+ # define per- access logfiles, transactions will be
+ # logged therein and *not* in this file.
+ #
+ CustomLog /proc/self/fd/1 common
+
+ #
+ # If you prefer a logfile with access, agent, and referer information
+ # (Combined Logfile Format) you can use the following directive.
+ #
+ #CustomLog "logs/access_log" combined
+
+
+
+ #
+ # Redirect: Allows you to tell clients about documents that used to
+ # exist in your server's namespace, but do not anymore. The client
+ # will make a new request for the document at its new location.
+ # Example:
+ # Redirect permanent /foo http://www.example.com/bar
+
+ #
+ # Alias: Maps web paths into filesystem paths and is used to
+ # access content that does not live under the DocumentRoot.
+ # Example:
+ # Alias /webpath /full/filesystem/path
+ #
+ # If you include a trailing / on /webpath then the server will
+ # require it to be present in the URL. You will also likely
+ # need to provide a section to allow access to
+ # the filesystem path.
+
+ #
+ # ScriptAlias: This controls which directories contain server scripts.
+ # ScriptAliases are essentially the same as Aliases, except that
+ # documents in the target directory are treated as applications and
+ # run by the server when requested rather than as documents sent to the
+ # client. The same rules about trailing "/" apply to ScriptAlias
+ # directives as to Alias.
+ #
+ ScriptAlias /cgi-bin/ "/usr/local/apache2/cgi-bin/"
+
+
+
+
+ #
+ # ScriptSock: On threaded servers, designate the path to the UNIX
+ # socket used to communicate with the CGI daemon of mod_cgid.
+ #
+ #Scriptsock cgisock
+
+
+#
+# "/usr/local/apache2/cgi-bin" should be changed to whatever your ScriptAliased
+# CGI directory exists, if you have that configured.
+#
+
+ AllowOverride None
+ Options None
+ Require all granted
+
+
+
+ #
+ # Avoid passing HTTP_PROXY environment to CGI's on this or any proxied
+ # backend servers which have lingering "httpoxy" defects.
+ # 'Proxy' request header is undefined by the IETF, not listed by IANA
+ #
+ RequestHeader unset Proxy early
+
+
+
+ #
+ # TypesConfig points to the file containing the list of mappings from
+ # filename extension to MIME-type.
+ #
+ TypesConfig conf/mime.types
+
+ #
+ # AddType allows you to add to or override the MIME configuration
+ # file specified in TypesConfig for specific file types.
+ #
+ #AddType application/x-gzip .tgz
+ #
+ # AddEncoding allows you to have certain browsers uncompress
+ # information on the fly. Note: Not all browsers support this.
+ #
+ #AddEncoding x-compress .Z
+ #AddEncoding x-gzip .gz .tgz
+ #
+ # If the AddEncoding directives above are commented-out, then you
+ # probably should define those extensions to indicate media types:
+ #
+ AddType application/x-compress .Z
+ AddType application/x-gzip .gz .tgz
+
+ #
+ # AddHandler allows you to map certain file extensions to "handlers":
+ # actions unrelated to filetype. These can be either built into the server
+ # or added with the Action directive (see below)
+ #
+ # To use CGI scripts outside of ScriptAliased directories:
+ # (You will also need to add "ExecCGI" to the "Options" directive.)
+ #
+ #AddHandler cgi-script .cgi
+
+ # For type maps (negotiated resources):
+ #AddHandler type-map var
+
+ #
+ # Filters allow you to process content before it is sent to the client.
+ #
+ # To parse .shtml files for server-side includes (SSI):
+ # (You will also need to add "Includes" to the "Options" directive.)
+ #
+ #AddType text/html .shtml
+ #AddOutputFilter INCLUDES .shtml
+
+
+#
+# The mod_mime_magic module allows the server to use various hints from the
+# contents of the file itself to determine its type. The MIMEMagicFile
+# directive tells the module where the hint definitions are located.
+#
+#MIMEMagicFile conf/magic
+
+#
+# Customizable error responses come in three flavors:
+# 1) plain text 2) local redirects 3) external redirects
+#
+# Some examples:
+#ErrorDocument 500 "The server made a boo boo."
+#ErrorDocument 404 /missing.html
+#ErrorDocument 404 "/cgi-bin/missing_handler.pl"
+#ErrorDocument 402 http://www.example.com/subscription_info.html
+#
+
+#
+# MaxRanges: Maximum number of Ranges in a request before
+# returning the entire resource, or one of the special
+# values 'default', 'none' or 'unlimited'.
+# Default setting is to accept 200 Ranges.
+#MaxRanges unlimited
+
+#
+# EnableMMAP and EnableSendfile: On systems that support it,
+# memory-mapping or the sendfile syscall may be used to deliver
+# files. This usually improves server performance, but must
+# be turned off when serving from networked-mounted
+# filesystems or if support for these functions is otherwise
+# broken on your system.
+# Defaults: EnableMMAP On, EnableSendfile Off
+#
+#EnableMMAP off
+#EnableSendfile on
+
+# Supplemental configuration
+#
+# The configuration files in the conf/extra/ directory can be
+# included to add extra features or to modify the default configuration of
+# the server, or you may simply copy their contents here and change as
+# necessary.
+
+# Server-pool management (MPM specific)
+#Include conf/extra/httpd-mpm.conf
+
+# Multi-language error messages
+#Include conf/extra/httpd-multilang-errordoc.conf
+
+# Fancy directory listings
+#Include conf/extra/httpd-autoindex.conf
+
+# Language settings
+#Include conf/extra/httpd-languages.conf
+
+# User home directories
+#Include conf/extra/httpd-userdir.conf
+
+# Real-time info on requests and configuration
+#Include conf/extra/httpd-info.conf
+
+# Virtual hosts
+#Include conf/extra/httpd-vhosts.conf
+
+# Local access to the Apache HTTP Server Manual
+#Include conf/extra/httpd-manual.conf
+
+# Distributed authoring and versioning (WebDAV)
+#Include conf/extra/httpd-dav.conf
+
+# Various default settings
+#Include conf/extra/httpd-default.conf
+
+# Configure mod_proxy_html to understand HTML4/XHTML1
+
+Include conf/extra/proxy-html.conf
+
+
+# Secure (SSL/TLS) connections
+#Include conf/extra/httpd-ssl.conf
+#
+# Note: The following must must be present to support
+# starting without SSL on platforms with no /dev/random equivalent
+# but a statically compiled-in mod_ssl.
+#
+
+SSLRandomSeed startup builtin
+SSLRandomSeed connect builtin
+
+
diff --git a/openshift/templates/programpaused-page/programpaused-bc.yaml b/openshift/templates/programpaused-page/programpaused-bc.yaml
new file mode 100644
index 00000000..a4df5dca
--- /dev/null
+++ b/openshift/templates/programpaused-page/programpaused-bc.yaml
@@ -0,0 +1,62 @@
+---
+kind: Template
+apiVersion: template.openshift.io/v1
+metadata:
+ name: programpaused-page
+objects:
+ - kind: ImageStream
+ apiVersion: image.openshift.io/v1
+ metadata:
+ name: programpaused-page
+ creationTimestamp:
+ labels:
+ app: programpaused-page
+ spec:
+ lookupPolicy:
+ local: false
+ status:
+ dockerImageRepository: ""
+ - kind: BuildConfig
+ apiVersion: build.openshift.io/v1
+ metadata:
+ name: programpaused-page
+ creationTimestamp:
+ labels:
+ app: programpaused-page
+ spec:
+ triggers:
+ - type: ConfigChange
+ - type: ImageChange
+ imageChange: {}
+ runPolicy: SerialLatestOnly
+ source:
+ type: Git
+ contextDir: "openshift/templates/programpaused-page"
+ git:
+ uri: https://github.com/bcgov/itvr.git
+ ref: release-1.32.0
+ strategy:
+ dockerStrategy:
+ env:
+ - name: ARTIFACTORY_USER
+ valueFrom:
+ secretKeyRef:
+ name: artifacts-default-pwpgbz
+ key: username
+ - name: ARTIFACTORY_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: artifacts-default-pwpgbz
+ key: password
+ forcePull: true
+ noCache: true
+ type: Docker
+ output:
+ to:
+ kind: ImageStreamTag
+ name: programpaused-page:latest
+ resources: {}
+ postCommit: {}
+ nodeSelector:
+ successfulBuildsHistoryLimit: 5
+ failedBuildsHistoryLimit: 5
diff --git a/openshift/templates/programpaused-page/public-html/index.html b/openshift/templates/programpaused-page/public-html/index.html
new file mode 100644
index 00000000..82f6387f
--- /dev/null
+++ b/openshift/templates/programpaused-page/public-html/index.html
@@ -0,0 +1,30 @@
+
+Program Paused
+
+
+
+
+
+ The CleanBC Go Electric Passenger Vehicle Rebate program is now paused.
+
+
Applications for rebate pre-approvals are no longer being accepted.
+
Thank you for your interest in this program.
+
+ To review other CleanBC Go Electric offerings visit this website:
+
+ https://goelectricbc.gov.bc.ca/
+
+
+
+
diff --git a/spring/Dockerfile b/spring/Dockerfile
index 0de88d3a..c39baf9d 100644
--- a/spring/Dockerfile
+++ b/spring/Dockerfile
@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1
-FROM --platform=linux/amd64 eclipse-temurin:17-jdk-jammy
+FROM eclipse-temurin:17-jdk-jammy
WORKDIR /app