diff --git a/.gitignore b/.gitignore index 048cd4c7..e0b83238 100644 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,7 @@ debug !test/config.yaml !test/config.localhost.yaml !ci/htpasswd -!ci/*.yaml +!ci/**/*.yaml **/manage/config.js frontend/manage/node_modules/* frontend/manage/dist/* diff --git a/ci/docker-compose.yml b/ci/docker-compose.yaml similarity index 100% rename from ci/docker-compose.yml rename to ci/docker-compose.yaml diff --git a/ci/helm-chart/Chart.yaml b/ci/helm-chart/Chart.yaml new file mode 100644 index 00000000..5e7f0eff --- /dev/null +++ b/ci/helm-chart/Chart.yaml @@ -0,0 +1,10 @@ +apiVersion: v2 +name: readium-lcp +description: A Helm chart for Readium LCP server components +type: application +home: https://github.com/notalib/readium-lcp-server +keywords: + - "lcp" + - "readium" +version: "1.0.0" +appVersion: "1.0.0" diff --git a/ci/helm-chart/config/config.yaml.tpl b/ci/helm-chart/config/config.yaml.tpl new file mode 100644 index 00000000..59809bdd --- /dev/null +++ b/ci/helm-chart/config/config.yaml.tpl @@ -0,0 +1,60 @@ +# The usernames and passwords must match the ones in the htpasswd files for each server. +lcp_update_auth: + # login and password used by the Status Server to access the License Server + username: "{{ .Values.auth.username }}" + password: "{{ .Values.auth.password }}" + +lsd_notify_auth: + # login and password used by the License Server to access the Status Server + username: "{{ .Values.auth.username }}" + password: "{{ .Values.auth.password }}" + +# LCP Server + +profile: "basic" +lcp: + host: "127.0.0.1" + # the public url a client app will use to access the License Server (optional) + public_base_url: "{{ .Values.lcp.public_base_url }}" + # the port on which the License Server will be running + port: 8989 + # replace this dsn if you're not using SQLite + database: "{{ .Values.lcp.database }}" + # authentication file of the License Server. Here we use the same file for the License Server and Status Server + auth_file: "/app/htpasswd" +{{- if .Values.storage.enabled }} +storage: + filesystem: + directory: "/data/files/storage" +{{- end }} +certificate: + # theses test certificates are provided in the test/cert folder of the codebase + cert: "/app/cert/cert.pem" + private_key: "/app/cert/privkey.pem" +license: + links: + # leave the url as-is (after has been resolved) + status: {{ default ( tpl "{{ .Values.lsd.public_base_url }}/licenses/{license_id}/status" . ) .Values.links.status | quote }} + # the url of a REAL html page, that indicates how the user can get back his passphrase if forgotten + hint: "{{ .Values.links.hint }}" + + +# LSD Server + +lsd: + host: "127.0.0.1" + # the public url a client app will use to access the Status Server + public_base_url: "{{ .Values.lsd.public_base_url }}" + # the port on which the Status Server will be running + port: 8990 + # replace this dsn if you're not using SQLite + database: "{{ .Values.lsd.database }}" + # authentication file of the Status Server. Here we use the same file for the License Server and Status Server + auth_file: "/app/htpasswd" + # in this example, the License Gateway is developed so that adding a license id + # to the host name gives access to a fresh license. + # Keep {license_id} as-is; this is a template. + # Read the doc to know more about how to develop a License Gateway. + license_link_url: {{ default ( tpl "{{ .Values.lsd.public_base_url }}/{license_id}" . ) .Values.links.license | quote }} + +{{ toYaml .Values.license_status }} diff --git a/ci/helm-chart/templates/_helpers.tpl b/ci/helm-chart/templates/_helpers.tpl new file mode 100644 index 00000000..7904ecc9 --- /dev/null +++ b/ci/helm-chart/templates/_helpers.tpl @@ -0,0 +1,11 @@ +{{- define "lcp.get-certs" -}} +{{- $certs := lookup "v1" "Secret" .Release.Namespace "lcp-certs" -}} +{{- if $certs -}} +cert.pem: {{ index $certs.data "cert.pem" }} +privkey.pem: {{ index $certs.data "privkey.pem" }} +{{- else -}} +{{- $cert := genSelfSignedCert "lcp" nil nil 365 -}} +cert.pem: {{ $cert.Cert | toString | b64enc }} +privkey.pem: {{ $cert.Key | toString | b64enc }} +{{- end -}} +{{- end -}} diff --git a/ci/helm-chart/templates/deployment-lcp.yaml b/ci/helm-chart/templates/deployment-lcp.yaml new file mode 100644 index 00000000..6671d68b --- /dev/null +++ b/ci/helm-chart/templates/deployment-lcp.yaml @@ -0,0 +1,60 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + workload.user.cattle.io/workloadselector: apps.deployment-{{ .Release.Namespace }}-lcpserver + name: lcpserver + namespace: {{ .Release.Namespace }} +spec: + replicas: 1 + selector: + matchLabels: + workload.user.cattle.io/workloadselector: apps.deployment-{{ .Release.Namespace }}-lcpserver + template: + metadata: + labels: + workload.user.cattle.io/workloadselector: apps.deployment-{{ .Release.Namespace }}-lcpserver + namespace: {{ .Release.Namespace }} + spec: + containers: + - name: lcpserver + image: ghcr.io/notalib/readium-lcp-server/lcpserver:latest + imagePullPolicy: Always + ports: + - containerPort: 8989 + name: http + protocol: TCP + volumeMounts: + - mountPath: /app/config.yaml + name: lcp-config + readOnly: true + subPath: config.yaml + - mountPath: /app/htpasswd + name: lcp-config + subPath: htpasswd + readOnly: true + - mountPath: /app/cert + name: lcp-certs + readOnly: true + - mountPath: /data/db + name: lcp-data + subPath: db + - mountPath: /data/files + name: lcp-data + subPath: files + imagePullSecrets: + - name: github-container-registry + volumes: + - name: lcp-config + secret: + defaultMode: 420 + optional: false + secretName: lcp-config + - name: lcp-certs + secret: + defaultMode: 420 + optional: false + secretName: lcp-certs + - name: lcp-data + persistentVolumeClaim: + claimName: pvc-lcp-data diff --git a/ci/helm-chart/templates/deployment-lsd.yaml b/ci/helm-chart/templates/deployment-lsd.yaml new file mode 100644 index 00000000..88ea571d --- /dev/null +++ b/ci/helm-chart/templates/deployment-lsd.yaml @@ -0,0 +1,56 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + workload.user.cattle.io/workloadselector: apps.deployment-{{ .Release.Namespace }}-lsdserver + name: lsdserver + namespace: {{ .Release.Namespace }} +spec: + replicas: 1 + selector: + matchLabels: + workload.user.cattle.io/workloadselector: apps.deployment-{{ .Release.Namespace }}-lsdserver + template: + metadata: + labels: + workload.user.cattle.io/workloadselector: apps.deployment-{{ .Release.Namespace }}-lsdserver + namespace: {{ .Release.Namespace }} + spec: + containers: + - name: lsdserver + image: ghcr.io/notalib/readium-lcp-server/lsdserver:latest + imagePullPolicy: Always + ports: + - containerPort: 8990 + name: http + protocol: TCP + volumeMounts: + - mountPath: /app/config.yaml + name: lcp-config + readOnly: true + subPath: config.yaml + - mountPath: /app/cert + name: lcp-certs + readOnly: true + - mountPath: /app/htpasswd + name: lcp-config + subPath: htpasswd + - mountPath: /data/db + name: lcp-data + subPath: db + imagePullSecrets: + - name: github-container-registry + volumes: + - name: lcp-config + secret: + defaultMode: 420 + optional: false + secretName: lcp-config + - name: lcp-certs + secret: + defaultMode: 420 + optional: false + secretName: lcp-certs + - name: lcp-data + persistentVolumeClaim: + claimName: pvc-lcp-data diff --git a/ci/helm-chart/templates/pvc-lcp.yaml b/ci/helm-chart/templates/pvc-lcp.yaml new file mode 100644 index 00000000..c63d8b3f --- /dev/null +++ b/ci/helm-chart/templates/pvc-lcp.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: pvc-lcp-data + namespace: lcp +spec: + accessModes: +{{ .Values.storage.accessModes | toYaml | indent 4 }} + resources: + requests: + storage: {{ .Values.storage.requestSize }} + storageClassName: {{ .Values.storage.storageClass }} diff --git a/ci/helm-chart/templates/secret-lcp-certs.yaml b/ci/helm-chart/templates/secret-lcp-certs.yaml new file mode 100644 index 00000000..6f5a1ed7 --- /dev/null +++ b/ci/helm-chart/templates/secret-lcp-certs.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Secret +metadata: + name: lcp-certs + namespace: {{ .Release.Namespace }} +type: Opaque +data: +{{ ( include "lcp.get-certs" . ) | indent 2 }} diff --git a/ci/helm-chart/templates/secret-lcp-config.yaml b/ci/helm-chart/templates/secret-lcp-config.yaml new file mode 100644 index 00000000..7847cf76 --- /dev/null +++ b/ci/helm-chart/templates/secret-lcp-config.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Secret +metadata: + name: lcp-config + namespace: {{ .Release.Namespace }} +type: Opaque +data: + htpasswd: {{ htpasswd .Values.auth.username .Values.auth.password }} + config.yaml: {{ tpl (.Files.Get "config/config.yaml.tpl") . | b64enc }} diff --git a/ci/helm-chart/templates/service-lcp.yaml b/ci/helm-chart/templates/service-lcp.yaml new file mode 100644 index 00000000..936affaf --- /dev/null +++ b/ci/helm-chart/templates/service-lcp.yaml @@ -0,0 +1,31 @@ +apiVersion: v1 +kind: Service +metadata: + name: lcpserver + namespace: lcp +spec: + ports: + - name: http + port: 8989 + protocol: TCP + targetPort: 8989 + selector: + workload.user.cattle.io/workloadselector: apps.deployment-{{ .Release.Namespace }}-lcpserver + sessionAffinity: None + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + name: lsdserver + namespace: lcp +spec: + ports: + - name: http + port: 8990 + protocol: TCP + targetPort: 8990 + selector: + workload.user.cattle.io/workloadselector: apps.deployment-{{ .Release.Namespace }}-lsdserver + sessionAffinity: None + type: ClusterIP diff --git a/ci/helm-chart/values.yaml b/ci/helm-chart/values.yaml new file mode 100644 index 00000000..b2ec46d9 --- /dev/null +++ b/ci/helm-chart/values.yaml @@ -0,0 +1,34 @@ +lcp: + public_base_url: "https://lcp.localhost" + database: "sqlite3://file:/data/db/lcp.sqlite?cache=shared&mode=rwc" + handle_storage: false + +lsd: + public_base_url: "https://lsd.localhost" + database: "sqlite3://file:/data/db/lsd.sqlite?cache=shared&mode=rwc" + license_link_url: + +auth: + username: "admin" + password: "Test1234" + +links: + hint: https://localhost/lcp-hint + # defaults to LSD endpoints if nothing provided + license: + status: + +storage: + enabled: true + requestSize: 1Gi + storageClass: local-path + accessModes: + - ReadWriteOnce + +license_status: + register: true + # uncomment the lines below if you're allowing e-lending + # renew: true + # return: true + # renting_days: 30 + # renew_days: 7 diff --git a/test/config.localhost.yaml b/test/config.localhost.yaml index 77ac9bf5..a6d6ba57 100644 --- a/test/config.localhost.yaml +++ b/test/config.localhost.yaml @@ -57,7 +57,7 @@ lsd: # the port on which the Status Server will be running port: 8990 # replace this dsn if you're not using SQLite - database: "sqlite3:///data/db/lsd.sqlite?cache=shared&mode=rwc" + database: "sqlite3://file:/data/db/lsd.sqlite?cache=shared&mode=rwc" # authentication file of the Status Server. Here we use the same file for the License Server and Status Server auth_file: "/app/htpasswd" # in this example, the License Gateway is developed so that adding a license id