diff --git a/Makefile b/Makefile index b6f5374..d9692c6 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,8 @@ clean: kind delete cluster lint: - helm template charts/firefly --set "erc20erc721.enabled=true" --set "erc1155.enabled=true" --set "ethconnect.enabled=true" + helm dep up charts/firefly + helm template charts/firefly --set "erc20erc721.enabled=true" --set "erc1155.enabled=true" --set "ethconnect.enabled=true" --set "evmconnect.enabled=true" ct lint \ --target-branch=main \ --exclude-deprecated \ diff --git a/charts/firefly-evmconnect/.helmignore b/charts/firefly-evmconnect/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/charts/firefly-evmconnect/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/charts/firefly-evmconnect/Chart.yaml b/charts/firefly-evmconnect/Chart.yaml new file mode 100644 index 0000000..3dc40a2 --- /dev/null +++ b/charts/firefly-evmconnect/Chart.yaml @@ -0,0 +1,19 @@ +apiVersion: v2 +name: firefly-evmconnect +description: | + A Helm chart for deploying the FireFly EVMConnect microservice to Kubernetes. + Requires a running instance of FireFly and a persistent volume for managing its + transaction state. +type: application +version: 0.6.0 +appVersion: "0.1.2" + +maintainers: + - name: hfuss + email: hayden.fuss@kaleido.io + - name: drewmarshburn + email: drew.marshburn@kaleido.io + - name: peterbroadhurst + email: peter.broadhurst@kaleido.io + - name: calbritt + email: cari.albritton@kaleido.io diff --git a/charts/firefly-evmconnect/ci/gasless-sidechain-values.yaml b/charts/firefly-evmconnect/ci/gasless-sidechain-values.yaml new file mode 100644 index 0000000..57494e9 --- /dev/null +++ b/charts/firefly-evmconnect/ci/gasless-sidechain-values.yaml @@ -0,0 +1,11 @@ +fullnameOverride: "evmconnect-nogas" + +config: + jsonRpcUrl: "http://geth.local:8545" + + policyEngine: | + policyengine.simple: + fixedGasPrice: "0" + resubmitInterval: 5m + gasOracle: + mode: fixed \ No newline at end of file diff --git a/charts/firefly-evmconnect/ci/goerli-values.yaml b/charts/firefly-evmconnect/ci/goerli-values.yaml new file mode 100644 index 0000000..f06ea44 --- /dev/null +++ b/charts/firefly-evmconnect/ci/goerli-values.yaml @@ -0,0 +1,11 @@ +fullnameOverride: "evmconnect-public" + +config: + jsonRpcUrl: "https://goerli.infura.io/v3/apikey" + + confirmations: + required: 20 + + connector: | + url: {{ .Values.config.jsonRpcUrl | quote }} + pollingInterval: 10s diff --git a/charts/firefly-evmconnect/templates/_helpers.tpl b/charts/firefly-evmconnect/templates/_helpers.tpl new file mode 100644 index 0000000..c63bccf --- /dev/null +++ b/charts/firefly-evmconnect/templates/_helpers.tpl @@ -0,0 +1,52 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "firefly-evmconnect.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "firefly-evmconnect.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "firefly-evmconnect.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "firefly-evmconnect.labels" -}} +helm.sh/chart: {{ include "firefly-evmconnect.chart" . }} +{{ include "firefly-evmconnect.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "firefly-evmconnect.selectorLabels" -}} +app.kubernetes.io/name: {{ include "firefly-evmconnect.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/component: evmconnect +{{- end }} diff --git a/charts/firefly-evmconnect/templates/secret.yaml b/charts/firefly-evmconnect/templates/secret.yaml new file mode 100644 index 0000000..409014e --- /dev/null +++ b/charts/firefly-evmconnect/templates/secret.yaml @@ -0,0 +1,76 @@ +{{/* + Copyright © 2022 Kaleido, Inc. + + SPDX-License-Identifier: Apache-2.0 + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://swww.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/}} + +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "firefly-evmconnect.fullname" . }}-config + labels: + {{- include "firefly-evmconnect.labels" . | nindent 4 }} +stringData: + config.yaml: |- + {{- with .Values.config.confirmations }} + confirmations: + {{- toYaml . | nindent 6 }} + {{- end }} + + {{- with .Values.config.eventstreams }} + eventstreams: + {{- toYaml . | nindent 6 }} + {{- end }} + + {{- with .Values.config.webhooks }} + webhooks: + {{- toYaml . | nindent 6 }} + {{- end }} + + {{- with .Values.config.policyLoop }} + policyloop: + {{- toYaml . | nindent 6 }} + {{- end }} + + {{- with .Values.config.transactions }} + transactions: + {{- toYaml . | nindent 6 }} + {{- end }} + + {{- tpl .Values.config.policyEngine . | nindent 4 }} + + log: + level: {{ .Values.config.log.level | quote }} + json: + enabled: {{ .Values.config.log.jsonEnabled }} + + persistence: + {{- if eq .Values.config.persistence.type "leveldb" }} + type: leveldb + leveldb: + maxHandles: {{ .Values.config.persistence.leveldb.maxHandles | int }} + path: /var/run/leveldb + syncWrites: {{ .Values.config.persistence.leveldb.syncWrites }} + {{- else if .Values.config.persistence.templateOverride }} + {{ tpl .Values.config.persistence.templateOverride . | nindent 8 }} + {{- end }} + + connector: + {{- tpl .Values.config.connector . | nindent 6 }} + + api: + port: {{ .Values.service.port }} + address: 0.0.0.0 + publicURL: "http://{{ include "firefly-evmconnect.fullname" . }}:{{ .Values.service.port }}" diff --git a/charts/firefly-evmconnect/templates/service.yaml b/charts/firefly-evmconnect/templates/service.yaml new file mode 100644 index 0000000..aaaff24 --- /dev/null +++ b/charts/firefly-evmconnect/templates/service.yaml @@ -0,0 +1,33 @@ +{{/* + Copyright © 2022 Kaleido, Inc. + + SPDX-License-Identifier: Apache-2.0 + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://swww.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/}} + +apiVersion: v1 +kind: Service +metadata: + name: {{ include "firefly-evmconnect.fullname" . }} + labels: + {{- include "firefly-evmconnect.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "firefly-evmconnect.selectorLabels" . | nindent 4 }} diff --git a/charts/firefly-evmconnect/templates/statefulset.yaml b/charts/firefly-evmconnect/templates/statefulset.yaml new file mode 100644 index 0000000..aa27638 --- /dev/null +++ b/charts/firefly-evmconnect/templates/statefulset.yaml @@ -0,0 +1,131 @@ +{{/* + Copyright © 2022 Kaleido, Inc. + + SPDX-License-Identifier: Apache-2.0 + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://swww.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/}} + +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "firefly-evmconnect.fullname" . }} + labels: + {{- include "firefly-evmconnect.labels" . | nindent 4 }} +spec: + replicas: 1 + serviceName: {{ include "firefly-evmconnect.fullname" . }} + updateStrategy: + type: RollingUpdate + selector: + matchLabels: + {{- include "firefly-evmconnect.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + checksum/config: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} + {{- with .Values.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "firefly-evmconnect.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- if .Values.initContainers }} + initContainers: + {{- tpl .Values.initContainers . | nindent 8 }} + {{- end }} + containers: + - name: evmconnect + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default (printf "v%s" .Chart.AppVersion) }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + args: + - -f + - /etc/evmconnect/config.yaml + {{- if .Values.extraEnv }} + env: + {{- toYaml .Values.extraEnv | nindent 12 }} + {{- end }} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + livenessProbe: + tcpSocket: + port: http + initialDelaySeconds: 5 + failureThreshold: 5 + successThreshold: 1 + periodSeconds: 5 + readinessProbe: + tcpSocket: + port: http + initialDelaySeconds: 5 + failureThreshold: 10 + successThreshold: 3 + periodSeconds: 3 + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumeMounts: + - mountPath: /var/run/leveldb + name: evmconnect + - mountPath: /etc/evmconnect/config.yaml + name: config + subPath: config.yaml + {{- if .Values.extraContainers }} + {{- tpl .Values.extraContainers . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: config + secret: + secretName: "{{ include "firefly-evmconnect.fullname" . }}-config" + volumeClaimTemplates: + {{- if eq .Values.config.persistence.type "leveldb" }} + - metadata: + name: evmconnect + {{- with .Values.persistentVolume }} + {{- with .annotations }} + annotations: + {{- toYaml . | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- toYaml .accessModes | nindent 10 }} + storageClassName: {{ .storageClass }} + resources: + requests: + storage: {{ .size }} + {{- end }} + {{- end }} + {{- if .Values.extraVolumeClaimTemplates }} + {{- tpl .Values.extraVolumeClaimTemplates . | nindent 4 }} + {{- end }} diff --git a/charts/firefly-evmconnect/values.yaml b/charts/firefly-evmconnect/values.yaml new file mode 100644 index 0000000..6c562b7 --- /dev/null +++ b/charts/firefly-evmconnect/values.yaml @@ -0,0 +1,73 @@ +fullnameOverride: "" + +service: + type: ClusterIP + port: 5000 + +podAnnotations: {} + +imagePullSecrets: [] + +podSecurityContext: {} + +securityContext: {} + +extraEnv: [] + +initContainers: "" +extraContainers: "" +extraVolumeClaimTemplates: "" + +resources: {} + +nodeSelector: {} + +affinity: {} + +tolerations: {} + +persistentVolume: + accessModes: + - ReadWriteOnce + annotations: {} + size: 2Gi + storageClass: "" + +image: + repository: ghcr.io/hyperledger/firefly-evmconnect + pullPolicy: IfNotPresent + # tag: "" + +# see https://github.com/hyperledger/firefly-evmconnect/blob/main/config.md for more info +config: + jsonRpcUrl: "" + + log: + level: debug + jsonEnabled: false + + confirmations: + required: 0 + # blockQueueLength: 50 + # staleReceiptTimeout: 1m + # notificationQueueLength: 50 + + persistence: + type: leveldb + leveldb: + maxHandles: 100 + syncWrites: false + templateOverride: "" + + connector: | + url: {{ .Values.config.jsonRpcUrl | quote }} + + policyEngine: "" + + policyLoop: {} + + transactions: {} + + webhooks: {} + + eventstreams: {} diff --git a/charts/firefly/Chart.lock b/charts/firefly/Chart.lock new file mode 100644 index 0000000..76b81f1 --- /dev/null +++ b/charts/firefly/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: firefly-evmconnect + repository: file://../firefly-evmconnect + version: 0.6.0 +digest: sha256:b99b626107ed5cdd1c1e5a67ed5c138bf02a7882cb5a266306946b0cc1de9d62 +generated: "2022-08-23T09:06:26.833062-04:00" diff --git a/charts/firefly/Chart.yaml b/charts/firefly/Chart.yaml index 8a86a72..8729b65 100644 --- a/charts/firefly/Chart.yaml +++ b/charts/firefly/Chart.yaml @@ -16,10 +16,13 @@ apiVersion: v2 name: firefly -description: A Helm chart for deploying FireFly and FireFly HTTPS Dataexchange onto Kubernetes. +description: | + A Helm chart for deploying FireFly and its various plugin microservices onto Kubernetes. + By default allows the user to deploy FireFly with a single multi-party namespace, with the + ability to template additional multi-party or gateway namespaces. type: application -appVersion: "1.0.4" -version: "0.5.6" +appVersion: "1.1.0" +version: "0.6.0" maintainers: - name: hfuss @@ -30,3 +33,10 @@ maintainers: email: peter.broadhurst@kaleido.io - name: calbritt email: cari.albritton@kaleido.io + +dependencies: + - name: firefly-evmconnect + repository: "file://../firefly-evmconnect" + alias: evmconnect + condition: evmconnect.enabled + version: "0.6.0" diff --git a/charts/firefly/README.md b/charts/firefly/README.md index 1e65dfe..7d4550f 100644 --- a/charts/firefly/README.md +++ b/charts/firefly/README.md @@ -64,7 +64,7 @@ helm registry login ghcr.io ## Install Chart ```shell -helm install [RELEASE_NAME] --version 0.2.0 oci://ghcr.io/hyperledger/helm/firefly +helm install [RELEASE_NAME] --version 0.6.0 oci://ghcr.io/hyperledger/helm/firefly ``` _See [configuration](#Configuration) below._ @@ -82,7 +82,7 @@ _See [helm uninstall](https://helm.sh/docs/helm/helm_uninstall/) for command doc ## Upgrading Chart ```shell -helm upgrade [RELEASE_NAME] --install --version 0.2.0 oci://ghcr.io/hyperledger/helm/firefly +helm upgrade [RELEASE_NAME] --install --version 0.6.0 oci://ghcr.io/hyperledger/helm/firefly ``` _See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command documentation._ @@ -96,7 +96,7 @@ dependencies: # ... - name: firefly repository: "oci://ghcr.io/hyperledger/helm/" - version: 0.2.0 + version: 0.6.0 ``` Then download the chart dependency into your parent chart: @@ -131,14 +131,15 @@ has several infrastructural dependencies: As depicted above, the chart only aims to provide a means for deploying the following components: -| Component | Status | Optional | Enabled by Default | -|------------------------------------------------------------------------------------------|------------------|----------|--------------------| -| [FireFly Core]( https://github.com/hyperledger/firefly) | βeta | ❌ | N/A | -| [FireFly Ethconnect]( https://github.com/hyperledger/firefly-ethconnect) | ⍺lpha ⚠️ | ✅ | ❌ | -| [FireFly Fabconnect]( https://github.com/hyperledger/firefly-fabconnect) | Unimplemented 🙈 | N/A | N/A | -| [FireFly DataExchange HTTPS]( https://github.com/hyperledger/firefly-dataexchange-https) | βeta | ✅ | ✅ | -| [FireFly Tokens ERC1155]( https://github.com/hyperledger/firefly-tokens-erc1155) | βeta | ✅ | ❌ | -| [FireFly Tokens ERC20 / ERC721]( https://github.com/hyperledger/firefly-tokens-erc20-erc721) | ⍺lpha ⚠️ | ✅ | ❌ | +| Component | Status | Optional | Enabled by Default | +|----------------------------------------------------------------------------------------------|------------------|----------|--------------------| +| [FireFly Core]( https://github.com/hyperledger/firefly) | GA | ❌ | N/A | +| [FireFly Ethconnect]( https://github.com/hyperledger/firefly-ethconnect) | Deprecated | ✅ | ❌ | +| [FireFly EVMConnect]( https://github.com/hyperledger/firefly-evmconnect) | ⍺lpha ⚠️ | ✅ | ❌ | +| [FireFly Fabconnect]( https://github.com/hyperledger/firefly-fabconnect) | Unimplemented 🙈 | N/A | N/A | +| [FireFly DataExchange HTTPS]( https://github.com/hyperledger/firefly-dataexchange-https) | GA | ✅ | ✅ | +| [FireFly Tokens ERC1155]( https://github.com/hyperledger/firefly-tokens-erc1155) | βeta | ✅ | ❌ | +| [FireFly Tokens ERC20 / ERC721]( https://github.com/hyperledger/firefly-tokens-erc20-erc721) | βeta | ✅ | ❌ | > **NOTE**: "Status" is meant to indicate the level of stability of the _chart's_ support for the particular component. @@ -634,12 +635,13 @@ metadata: name: firefly-helm spec: interval: 10m - url: "https://github.com/hyperledger/firefly" + url: "https://github.com/hyperledger/firefly-helm-charts" ref: - tag: helm-v0.1.0 + tag: v0.6.0 ignore: | /* !/charts/firefly + !/charts/firefly-evmconnect ``` then within a [`HelmRelease`](https://fluxcd.io/docs/components/helm/helmreleases/) resource you can refer to the chart via the `GitRepostiory`: @@ -692,7 +694,7 @@ As a result, you can configure Terraform to use the FireFly chart by either: ```hcl resource "helm_release" "firefly" { name = "firefly" - chart = "firefly-0.0.1.tgz" + chart = "firefly-0.6.0.tgz" // ... } ``` \ No newline at end of file diff --git a/charts/firefly/scripts/ff-registration.sh b/charts/firefly/scripts/ff-registration.sh index 5bf529a..0b7562f 100644 --- a/charts/firefly/scripts/ff-registration.sh +++ b/charts/firefly/scripts/ff-registration.sh @@ -16,37 +16,43 @@ # See the License for the specific language governing permissions and # limitations under the License. -until STATUS=$(curl ${FF_URL}/api/v1/status); do - echo "Waiting for FireFly..." - sleep 5 -done +for n in $FF_NAMESPACES; do + until STATUS=$(curl ${FF_URL}/api/v1/namespaces/${n}/status -s); do + echo "Waiting for FireFly..." + sleep 5 + done -if [ `echo $STATUS | jq -r .org.registered` != "true" ]; then + if [ `echo $STATUS | jq -r .org.registered` != "true" ]; then - echo "Registering organization" - HTTP_CODE=`curl --silent --output /dev/stderr --write-out "%{http_code}" \ - -X POST -d '{}' -H 'Content-Type: application/json' \ - "${FF_URL}/api/v1/network/organizations/self?confirm"` - if [ "$HTTP_CODE" -ne 200 ]; then - echo "Failed to register with code ${HTTP_CODE}" - exit 1 - fi + echo "Registering organization" + HTTP_CODE=`curl --silent --output /dev/stderr --write-out "%{http_code}" \ + -X POST -d '{}' -H 'Content-Type: application/json' \ + "${FF_URL}/api/v1/namespaces/${n}/network/organizations/self?confirm"` + if [ "$HTTP_CODE" -ne 200 ]; then + echo "Failed to register with code ${HTTP_CODE}" + exit 1 + fi -fi + else -if [ `echo $STATUS | jq -r .node.registered` != "true" ]; then + echo "Org already registered." - echo "Registering node" - HTTP_CODE=`curl --silent --output /dev/stderr --write-out "%{http_code}" \ - -X POST -d '{}' -H 'Content-Type: application/json' \ - "${FF_URL}/api/v1/network/nodes/self?confirm"` - if [ "$HTTP_CODE" -ne 200 ]; then - echo "Failed to register with code ${HTTP_CODE}" - exit 1 fi -else + if [ `echo $STATUS | jq -r .node.registered` != "true" ]; then + + echo "Registering node" + HTTP_CODE=`curl --silent --output /dev/stderr --write-out "%{http_code}" \ + -X POST -d '{}' -H 'Content-Type: application/json' \ + "${FF_URL}/api/v1/namespaces/${n}/network/nodes/self?confirm"` + if [ "$HTTP_CODE" -ne 200 ]; then + echo "Failed to register with code ${HTTP_CODE}" + exit 1 + fi - echo "Already registered. Nothing to do" + else -fi + echo "Node already registered." + + fi +done diff --git a/charts/firefly/templates/_helpers.tpl b/charts/firefly/templates/_helpers.tpl index b5cf985..d68dd13 100644 --- a/charts/firefly/templates/_helpers.tpl +++ b/charts/firefly/templates/_helpers.tpl @@ -113,9 +113,6 @@ app.kubernetes.io/managed-by: {{ .Release.Service }} app.kubernetes.io/part-of: {{ .Chart.Name }} {{- end }} -{{/* -Common labels -*/}} {{- define "firefly.ethconnectLabels" -}} helm.sh/chart: {{ include "firefly.chart" . }} {{ include "firefly.ethconnectSelectorLabels" . }} @@ -230,138 +227,254 @@ metrics: {{- end }} ui: path: ./frontend -org: - name: {{ .Values.config.organizationName }} - key: {{ .Values.config.organizationKey }} -{{- if .Values.config.blockchainOverride }} -blockchain: - {{- tpl .Values.config.blockchainOverride . | nindent 2 }} -{{- else if or .Values.config.ethconnectUrl .Values.ethconnect.enabled }} -blockchain: - type: ethereum - ethereum: - ethconnect: - {{ if .Values.ethconnect.enabled }} - url: http://{{ include "firefly.fullname" . }}-ethconnect.{{ .Release.Namespace }}.svc:{{ .Values.ethconnect.service.apiPort }} - {{ else }} - url: {{ tpl .Values.config.ethconnectUrl . }} - {{ end }} - instance: {{ .Values.config.fireflyContractAddress }} - topic: {{ .Values.config.ethconnectTopic | quote }} - retry: - enable: {{ .Values.config.ethconnectRetry }} - {{- if and .Values.config.ethconnectUsername .Values.config.ethconnectPassword }} - auth: - username: {{ .Values.config.ethconnectUsername | quote }} - password: {{ .Values.config.ethconnectPassword | quote }} - {{- end }} - {{- if .Values.config.ethconnectPrefixShort }} - prefixShort: {{ .Values.config.ethconnectPrefixShort }} - {{- end }} - {{- if .Values.config.ethconnectPrefixLong }} - prefixLong: {{ .Values.config.ethconnectPrefixLong }} - {{- end }} - {{- if .Values.config.addresssResolverUrlTemplate }} - addressResolver: - urlTemplate: {{ .Values.config.addresssResolverUrlTemplate }} + +plugins: + {{- if .Values.config.blockchainOverride }} + blockchain: + {{- tpl .Values.config.blockchainOverride . | nindent 4 }} + {{- else }}{{/* if not overridden */}} + blockchain: + {{- if or .Values.config.ethconnectUrl .Values.ethconnect.enabled }} + - name: eth0 + type: ethereum + ethereum: + ethconnect: + {{ if .Values.ethconnect.enabled }} + url: http://{{ include "firefly.fullname" . }}-ethconnect.{{ .Release.Namespace }}.svc:{{ .Values.ethconnect.service.apiPort }} + {{ else }} + url: {{ tpl .Values.config.ethconnectUrl . }} + {{ end }} + topic: {{ .Values.config.ethconnectTopic | quote }} + retry: + enable: {{ .Values.config.ethconnectRetry }} + {{- if and .Values.config.ethconnectUsername .Values.config.ethconnectPassword }} + auth: + username: {{ .Values.config.ethconnectUsername | quote }} + password: {{ .Values.config.ethconnectPassword | quote }} + {{- end }} + {{- if .Values.config.ethconnectPrefixShort }} + prefixShort: {{ .Values.config.ethconnectPrefixShort }} + {{- end }} + {{- if .Values.config.ethconnectPrefixLong }} + prefixLong: {{ .Values.config.ethconnectPrefixLong }} + {{- end }} + {{- if .Values.config.addresssResolverUrlTemplate }} + addressResolver: + urlTemplate: {{ .Values.config.addresssResolverUrlTemplate }} + {{- end }} + {{- else if .Values.evmconnect.enabled }} + - name: eth0 + type: ethereum + ethereum: + ethconnect: + {{- if .Values.evmconnect.enabled }} + url: http://{{ include "firefly.fullname" . }}-evmconnect.{{ .Release.Namespace }}.svc:{{ .Values.evmconnect.service.port }} + {{- end }} + topic: {{ .Values.config.evmconnectTopic | quote }} + retry: + enable: {{ .Values.config.evmconnectRetry }} + {{- if .Values.config.addresssResolverUrlTemplate }} + addressResolver: + urlTemplate: {{ .Values.config.addresssResolverUrlTemplate }} + {{- end }} + {{- end }} + {{- if .Values.config.fabconnectUrl }} + - name: fabric0 + type: fabric + fabric: + fabconnect: + url: {{ tpl .Values.config.fabconnectUrl . }} + {{- if and .Values.config.fabconnectUsername .Values.config.fabconnectPassword }} + auth: + username: {{ .Values.config.fabconnectUsername | quote }} + password: {{ .Values.config.fabconnectPassword | quote }} + {{- end }} + retry: + enable: {{ .Values.config.fabconnectRetry }} + channel: {{ .Values.config.fabconnectChannel | quote }} + chaincode: {{ .Values.config.fireflyChaincode | quote }} + topic: {{ .Values.config.fabconnectTopic | quote }} + signer: {{ .Values.config.fabconnectSigner | quote }} + {{- end }} + {{- if .Values.config.extraBlockchains }} + {{- tpl .Values.config.extraBlockchains . | nindent 4 }} + {{- end }} + {{- end }} + {{- if .Values.config.databaseOverride }} + database: + {{- tpl .Values.config.databaseOverride . | nindent 4 }} + {{- else }} + database: + {{- if .Values.config.postgresUrl }} + - name: database0 + type: postgres + postgres: + url: {{ tpl .Values.config.postgresUrl . }} + migrations: + auto: {{ .Values.config.postgresAutomigrate }} + {{- end }} + {{- if .Values.config.extraDatabases }} + {{- tpl .Values.config.extraDatabases . | nindent 4 }} + {{- end }} + {{- end }} + {{- if .Values.config.sharedstorageOverride }} + sharedstorage: + {{- tpl .Values.config.sharedstorageOverride . | nindent 4 }} + {{- else }} + sharedstorage: + {{- if and .Values.config.ipfsApiUrl .Values.config.ipfsGatewayUrl }} + - name: sharedstorage0 + type: ipfs + ipfs: + api: + url: {{ tpl .Values.config.ipfsApiUrl . }} + {{- if and .Values.config.ipfsApiUsername .Values.config.ipfsApiPassword }} + auth: + username: {{ .Values.config.ipfsApiUsername |quote }} + password: {{ .Values.config.ipfsApiPassword | quote }} + {{- end }} + gateway: + url: {{ tpl .Values.config.ipfsGatewayUrl . }} + {{- if and .Values.config.ipfsGatewayUsername .Values.config.ipfsGatewayPassword }} + auth: + username: {{ .Values.config.ipfsGatewayUsername | quote }} + password: {{ .Values.config.ipfsGatewayPassword | quote }} + {{- end }} + {{- end }} + {{- if .Values.config.extraSharedstorage }} + {{- tpl .Values.config.extraSharedstorage . | nindent 4 }} + {{- end }} + {{- end }} + {{- if and .Values.config.dataexchangeOverride (not .Values.dataexchange.enabled) }} + dataexchange: + {{- tpl .Values.config.dataexchangeOverride . | nindent 4 }} + {{- else }} + dataexchange: + {{- if .Values.dataexchange.enabled }} + - type: ffdx + name: dataexchange0 + ffdx: + url: http://{{ include "firefly.fullname" . }}-dx.{{ .Release.Namespace }}.svc:{{ .Values.dataexchange.service.apiPort }} + {{- if .Values.dataexchange.apiKey }} + headers: + x-api-key: {{ .Values.dataexchange.apiKey | quote }} + {{- end }} + {{- else }} + - type: ffdx + name: dataexchange0 + ffdx: + url: {{ tpl .Values.config.dataexchangeUrl . }} + {{- if .Values.config.dataexchangeAPIKey }} + headers: + x-api-key: {{ .Values.config.dataexchangeAPIKey | quote }} + {{- end }} {{- end }} -{{- else if .Values.config.fabconnectUrl }} -blockchain: - type: fabric - fabric: - fabconnect: - url: {{ tpl .Values.config.fabconnectUrl . }} - {{- if and .Values.config.fabconnectUsername .Values.config.fabconnectPassword }} - auth: - username: {{ .Values.config.fabconnectUsername | quote }} - password: {{ .Values.config.fabconnectPassword | quote }} - {{- end }} - retry: - enable: {{ .Values.config.fabconnectRetry }} - channel: {{ .Values.config.fabconnectChannel | quote }} - chaincode: {{ .Values.config.fireflyChaincode | quote }} - topic: {{ .Values.config.fabconnectTopic | quote }} - signer: {{ .Values.config.fabconnectSigner | quote }} -{{- end }} -{{- if .Values.config.databaseOverride }} -database: - {{- tpl .Values.config.databaseOverride . | nindent 2 }} -{{- else if .Values.config.postgresUrl }} -database: - type: postgres - postgres: - url: {{ tpl .Values.config.postgresUrl . }} - migrations: - auto: {{ .Values.config.postgresAutomigrate }} -{{- end }} -{{- if .Values.config.sharedstorageOverride }} -sharedstorage: - {{- tpl .Values.config.sharedstorageOverride . | nindent 2 }} -{{- else if and .Values.config.ipfsApiUrl .Values.config.ipfsGatewayUrl }} -sharedstorage: - type: ipfs - ipfs: - api: - url: {{ tpl .Values.config.ipfsApiUrl . }} - {{- if and .Values.config.ipfsApiUsername .Values.config.ipfsApiPassword }} - auth: - username: {{ .Values.config.ipfsApiUsername |quote }} - password: {{ .Values.config.ipfsApiPassword | quote }} - {{- end }} - gateway: - url: {{ tpl .Values.config.ipfsGatewayUrl . }} - {{- if and .Values.config.ipfsGatewayUsername .Values.config.ipfsGatewayPassword }} - auth: - username: {{ .Values.config.ipfsGatewayUsername | quote }} - password: {{ .Values.config.ipfsGatewayPassword | quote }} - {{- end }} -{{- end }} -{{- if and .Values.config.dataexchangeOverride (not .Values.dataexchange.enabled) }} -dataexchange: - {{- tpl .Values.config.dataexchangeOverride . | nindent 2 }} -{{- else }} -dataexchange: - {{- if .Values.dataexchange.enabled }} - type: ffdx - ffdx: - url: http://{{ include "firefly.fullname" . }}-dx.{{ .Release.Namespace }}.svc:{{ .Values.dataexchange.service.apiPort }} - {{- if .Values.dataexchange.apiKey }} - headers: - x-api-key: {{ .Values.dataexchange.apiKey | quote }} + {{- if .Values.config.extraDataexchanges }} + {{- tpl .Values.config.extraDataexchanges . | nindent 4 }} {{- end }} + {{- end }} + {{- if .Values.config.tokensOverride }} + tokens: + {{- tpl .Values.config.tokensOverride . | nindent 4 }} {{- else }} - type: ffdx - ffdx: - url: {{ tpl .Values.config.dataexchangeUrl . }} - {{- if .Values.config.dataexchangeAPIKey }} - headers: - x-api-key: {{ .Values.config.dataexchangeAPIKey | quote }} + {{- if or .Values.erc1155.enabled .Values.erc20erc721.enabled .Values.config.extraTokens }} + tokens: + {{- if .Values.erc1155.enabled }} + - type: fftokens + name: erc1155 + remoteName: erc1155 + fftokens: + url: http://{{ include "firefly.fullname" . }}-erc1155.{{ .Release.Namespace }}.svc:{{ .Values.erc1155.service.port }} + {{- end }} + {{- if .Values.erc20erc721.enabled }} + - type: fftokens + name: erc20-erc721 + remoteName: erc20-erc721 + fftokens: + url: http://{{ include "firefly.fullname" . }}-erc20-erc721.{{ .Release.Namespace }}.svc:{{ .Values.erc20erc721.service.port }} {{- end }} {{- end }} -{{- end }} -{{- if .Values.config.tokensOverride }} -tokens: - {{- tpl .Values.config.tokensOverride . | nindent 2 }} -{{- else if or .Values.erc1155.enabled .Values.erc20erc721.enabled }} -tokens: - {{- if .Values.erc1155.enabled }} - - plugin: fftokens - name: erc1155 - url: http://{{ include "firefly.fullname" . }}-erc1155.{{ .Release.Namespace }}.svc:{{ .Values.erc1155.service.port }} - {{- end }} - {{- if .Values.erc20erc721.enabled }} - - plugin: fftokens - name: erc20-erc721 - url: http://{{ include "firefly.fullname" . }}-erc20-erc721.{{ .Release.Namespace }}.svc:{{ .Values.erc20erc721.service.port }} {{- end }} -{{- end }} + +namespaces: + default: default + predefined: + {{- if .Values.config.extraNamespaces }} + {{- tpl .Values.config.extraNamespaces . | nindent 4 }} + {{- end }} + - name: default + remoteName: default + description: Default predefined namespace + {{- if and (eq .Values.config.defaultBlockchainType "ethereum") (or .Values.config.evmconnectUrl .Values.evmconnect.enabled .Values.config.ethconnectUrl .Values.ethconnect.enabled) }} + defaultKey: {{ .Values.config.organizationKey }} + {{- else if .Values.config.fabconnectUrl }} + defaultKey: {{ .Values.config.fabconnectSigner }} + {{- end }} + plugins: + - database0 + {{- if and (eq .Values.config.defaultBlockchainType "ethereum") (or .Values.config.evmconnectUrl .Values.evmconnect.enabled .Values.config.ethconnectUrl .Values.ethconnect.enabled) }} + - eth0 + {{- else if .Values.config.fabconnectUrl }} + - fabric0 + {{- end }} + - dataexchange0 + - sharedstorage0 + {{- if .Values.erc1155.enabled }} + - erc1155 + {{- end }} + {{- if .Values.erc20erc721.enabled }} + - erc20-erc721 + {{- end }} + multiparty: + enabled: true + org: + name: {{ .Values.config.organizationName }} + description: The {{ .Values.config.organizationName }} organization + {{- if and (eq .Values.config.defaultBlockchainType "ethereum") (or .Values.config.evmconnectUrl .Values.evmconnect.enabled .Values.config.ethconnectUrl .Values.ethconnect.enabled) }} + key: {{ .Values.config.organizationKey }} + {{- else if .Values.config.fabconnectUrl }} + key: {{ .Values.config.fabconnectSigner }} + {{- end }} + node: + name: {{ include "firefly.nodeName" . }} + description: {{ include "firefly.nodeName" . }} + contract: + {{- if and (eq .Values.config.defaultBlockchainType "ethereum") (or .Values.config.evmconnectUrl .Values.evmconnect.enabled .Values.config.ethconnectUrl .Values.ethconnect.enabled) }} + - location: + address: {{ .Values.config.fireflyContractAddress }} + firstEvent: {{ .Values.config.fireflyContractFirstEvent }} + {{- if .Values.config.fireflyContracts }} + {{- range .Values.config.fireflyContracts }} + - location: + address: {{ .address | quote }} + firstEvent: {{ .firstEvent }} + {{- end }} + {{- end }} + {{- else if .Values.config.fabconnectUrl }} + - location: + chaincode: {{ .Values.config.fireflyChaincode }} + channel: {{ .Values.config.fabconnectChannel }} + firstEvent: "" + {{- if .Values.config.fireflyContracts }} + {{- range .Values.config.fireflyContracts }} + - location: + channel: {{ .channel | quote }} + chaincode: {{ .chaincode | quote }} + firstEvent: {{ .firstEvent }} + {{- end }} + {{- end }} + {{- end }} {{- end }} {{- define "firefly.ethconnectUrlEnvVar" -}} - name: ETHCONNECT_URL {{- if .Values.ethconnect.enabled }} value: "http://{{ include "firefly.fullname" . }}-ethconnect.{{ .Release.Namespace }}.svc:{{ .Values.ethconnect.service.apiPort }}" -{{- else }} +{{- else if .Values.evmconnect.enabled }} + value: "http://{{ include "firefly.fullname" . }}-evmconnect.{{ .Release.Namespace }}.svc:{{ .Values.evmconnect.service.port }}" +{{- else if .Values.config.ethconnectUrl }} value: {{ tpl .Values.config.ethconnectUrl . }} +{{- else }} + value: {{ tpl .Values.config.evmconnectUrl . }} {{- end }} {{- end }} \ No newline at end of file diff --git a/charts/firefly/templates/core/job-registration.yaml b/charts/firefly/templates/core/job-registration.yaml index 127d5dc..4452d62 100644 --- a/charts/firefly/templates/core/job-registration.yaml +++ b/charts/firefly/templates/core/job-registration.yaml @@ -48,5 +48,7 @@ spec: - name: FF_URL value: "http://{{ include "firefly.fullname" . }}:{{ .Values.core.service.httpPort }}" {{- end }} + - name: FF_NAMESPACES + value: {{ join " " .Values.core.jobs.registration.ffNamespaces | quote }} restartPolicy: Never {{- end }} diff --git a/charts/firefly/templates/core/servicemonitor.yaml b/charts/firefly/templates/core/servicemonitor.yaml index 73b27e2..117ba8a 100644 --- a/charts/firefly/templates/core/servicemonitor.yaml +++ b/charts/firefly/templates/core/servicemonitor.yaml @@ -48,7 +48,7 @@ spec: targetLabels: {{- range .Values.core.metrics.serviceMonitor.targetLabels }} - {{ . }} - {{- end }} + {{- end }} {{- end }} selector: matchLabels: diff --git a/charts/firefly/templates/core/statefulset.yaml b/charts/firefly/templates/core/statefulset.yaml index 6233f3e..c072d74 100644 --- a/charts/firefly/templates/core/statefulset.yaml +++ b/charts/firefly/templates/core/statefulset.yaml @@ -57,8 +57,6 @@ spec: image: "{{ .Values.core.image.repository }}:{{ .Values.core.image.tag | default (printf "v%s" .Chart.AppVersion) }}" imagePullPolicy: {{ .Values.core.image.pullPolicy }} env: - - name: FIREFLY_NODE_NAME - value: {{ include "firefly.nodeName" . }} {{- if .Values.core.extraEnv }} {{- toYaml .Values.core.extraEnv | nindent 12 }} {{- end }} diff --git a/charts/firefly/templates/dataexchange/statefulset.yaml b/charts/firefly/templates/dataexchange/statefulset.yaml index 487deca..79c5032 100644 --- a/charts/firefly/templates/dataexchange/statefulset.yaml +++ b/charts/firefly/templates/dataexchange/statefulset.yaml @@ -90,6 +90,9 @@ spec: - mountPath: /data/peers subPath: peers name: dx-peers + - mountPath: /data/destinations + subPath: destinations + name: dx-peers - mountPath: /data/config.json name: config subPath: config.json diff --git a/charts/firefly/templates/ethconnect/secret.yaml b/charts/firefly/templates/ethconnect/secret.yaml index 4ba68b6..dfbde6e 100644 --- a/charts/firefly/templates/ethconnect/secret.yaml +++ b/charts/firefly/templates/ethconnect/secret.yaml @@ -40,4 +40,5 @@ stringData: maxTXWaitTime: {{ .Values.ethconnect.config.maxTXWaitTimeSec }} maxInFlight: {{ .Values.ethconnect.config.maxInFlight }} gasEstimationFactor: {{ .Values.ethconnect.config.gasEstimationFactor }} + alwaysManageNonce: true {{- end }} diff --git a/charts/firefly/values.yaml b/charts/firefly/values.yaml index 47b851f..a504aff 100644 --- a/charts/firefly/values.yaml +++ b/charts/firefly/values.yaml @@ -59,9 +59,22 @@ config: # The URL + URI Go template of an address resolver connector addresssResolverUrlTemplate: "" - # The Ethereum address of the pre-deployed FireFly smart contract + # The Ethereum address of the _original_, pre-deployed FireFly smart contract fireflyContractAddress: "contractAddress" + # The block number of when the first event of the FireFly smart contract occurs + fireflyContractFirstEvent: 0 + + # The Ethereum address(es) or Fabric chaincode(s) of the additional FireFly smart contract instances + fireflyContracts: [] + # for ethereum + # - address: "contractAddress" + # firstEvent: 1000 + # for fabric + # - chaincode: "chaincode" + # channel: "default" + # firstEvent: "" + # The name of the Fabric chaincode deployment for the FireFly chaincode fireflyChaincode: firefly_go @@ -95,27 +108,46 @@ config: # The basic auth password to use for authenticating to the IPFS Gateway server ipfsGatewayPassword: "" - # The URL of the Ethconnect API and WS server to use for the blockchain plugin of type `ethereum` + # If both fabconnect* and ethconnect* / evmconnect* config is provided, determines which plugin to use with the default namespace + # Allowed values are 'ethereum' and 'fabric' + defaultBlockchainType: ethereum + + # Deprecated: The URL of the Ethconnect API and WS server to use for the blockchain plugin of type `ethereum` ethconnectUrl: "" - # The basic auth username to use for authenticating to Ethconnect + # Deprecated: The basic auth username to use for authenticating to Ethconnect ethconnectUsername: "" - # The basic auth password to use for authenticating to Ethconnect + # Deprecated: The basic auth password to use for authenticating to Ethconnect ethconnectPassword: "" - # Enables retries when communicating with Ethconnect + # Deprecated: Enables retries when communicating with Ethconnect ethconnectRetry: true - # The Ethconnect topic to use for blockchain event subscriptions + # Deprecated: The Ethconnect topic to use for blockchain event subscriptions ethconnectTopic: 0 - # The short prefix FireFly will prepend to certain headers it sends to Ethconnect i.e. fly or kld + # Deprecated: The short prefix FireFly will prepend to certain headers it sends to Ethconnect i.e. fly or kld ethconnectPrefixShort: "" - # The long prefix FireFly will prepend to certain headers it sends to Ethconnect i.e. firefly or kaleido + # Deprecated: The long prefix FireFly will prepend to certain headers it sends to Ethconnect i.e. firefly or kaleido ethconnectPrefixLong: "" + # The URL of the EVMConnect API and WS server to use for the blockchain plugin of type `ethereum` + evmconnectUrl: "" + + # The basic auth username to use for authenticating to EVMConnect + evmconnectUsername: "" + + # The basic auth password to use for authenticating to EVMConnect + evmconnectPassword: "" + + # Enables retries when communicating with EVMConnect + evmconnectRetry: true + + # The EVMConnect topic to use for blockchain event subscriptions + evmconnectTopic: 0 + # The URL of the Fabconnect API and WS server to use for the blockchain plugin of type `fabric` fabconnectUrl: "" @@ -142,12 +174,16 @@ config: # want to use other plugin types i.e. `fabric` which currently do not exist at the time of writing. dataexchangeOverride: "" + extraDataexchanges: "" databaseOverride: "" + extraDatabases: "" sharedstorageOverride: "" + extraSharedstorage: "" tokensOverride: "" + extraTokens: "" blockchainOverride: "" # type: ethereum @@ -156,6 +192,9 @@ config: # url: http://ethconnect_0:8080 # instance: /contracts/firefly # topic: "0" + extraBlockchains: "" + + extraNamespaces: "" # Instead of using the provided config template from _helpers.tpl, users can use to customize the config using their own global values, etc. # See the firefly.coreConfig helper for an example of a Go-templated config file that could be provided here as a multiline string. @@ -256,6 +295,8 @@ core: registration: enabled: false ffUrl: "" + ffNamespaces: + - default # Configures the properties of the StatefulSet, Service, and optionally Ingress used to deploy and expose FireFly HTTPS DataExchange dataexchange: @@ -287,7 +328,7 @@ dataexchange: image: repository: ghcr.io/hyperledger/firefly-dataexchange-https pullPolicy: IfNotPresent - tag: v1.0.0 + tag: v1.1.0 imagePullSecrets: [] nameOverride: "" @@ -370,7 +411,7 @@ erc1155: image: repository: ghcr.io/hyperledger/firefly-tokens-erc1155 pullPolicy: IfNotPresent - tag: v1.0.3 + tag: v1.1.5 imagePullSecrets: [] @@ -444,7 +485,7 @@ erc20erc721: image: repository: ghcr.io/hyperledger/firefly-tokens-erc20-erc721 pullPolicy: IfNotPresent - tag: v1.0.2 + tag: v1.1.4 imagePullSecrets: [] @@ -527,7 +568,7 @@ ethconnect: image: repository: ghcr.io/hyperledger/firefly-ethconnect pullPolicy: Always - tag: v3.2.0 + tag: v3.2.7 extraEnv: [] # - name: LOG_LEVEL @@ -572,7 +613,6 @@ ethconnect: size: 2Gi storageClass: "" - sandbox: enabled: true @@ -586,7 +626,7 @@ sandbox: image: repository: ghcr.io/hyperledger/firefly-sandbox pullPolicy: IfNotPresent - tag: v0.1.10 + tag: v1.1.1 resources: {} @@ -612,4 +652,7 @@ sandbox: tolerations: [] - affinity: {} \ No newline at end of file + affinity: {} + +evmconnect: + enabled: false diff --git a/hack/enforce-chart-conventions.sh b/hack/enforce-chart-conventions.sh index f310628..e02cb43 100755 --- a/hack/enforce-chart-conventions.sh +++ b/hack/enforce-chart-conventions.sh @@ -1,7 +1,7 @@ #!/bin/bash failed=0 -for yamlTemplate in $(find ./charts -regex '^\.\/charts\/.*\/templates\/[^\/]*.*\/*.*\.yaml' | grep -v appcloud-crds); do +for yamlTemplate in $(find ./charts -regex '^\.\/charts\/.*\/templates\/[^\/]*.*\/*.*\.yaml'); do kind=$(cat $yamlTemplate | grep -e '^kind:' | awk '{ printf("%s\n", $2) }' | tr '[:upper:]' '[:lower:]') if ! basename "$yamlTemplate" | grep -E "^${kind}[s]?\-?[a-z\-]*\.yaml$" > /dev/null; then echo "ERROR: $yamlTemplate filename does not start with $kind"