Compare commits
19
Commits
v1.15.1
...
v1.16.0-rc1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8110f9ac13 | ||
|
|
4f8a60b498 | ||
|
|
667629d265 | ||
|
|
b06ff625e0 | ||
|
|
8ee74161fc | ||
|
|
e1fb5a7411 | ||
|
|
e8ff79e448 | ||
|
|
5cb3ebf262 | ||
|
|
3ac188124e | ||
|
|
590eefaa52 | ||
|
|
4b307be939 | ||
|
|
260de05a63 | ||
|
|
e06aa25245 | ||
|
|
353453e9a7 | ||
|
|
85084249cf | ||
|
|
89aeddaf3a | ||
|
|
89f80c6f25 | ||
|
|
b27043518f | ||
|
|
f54bd6a703 |
+7
-2
@@ -5,9 +5,14 @@ pull_request_rules:
|
|||||||
- "#approved-reviews-by>=1"
|
- "#approved-reviews-by>=1"
|
||||||
- label=ready-to-merge
|
- label=ready-to-merge
|
||||||
- label!=hold-off-merging
|
- label!=hold-off-merging
|
||||||
- status-success=build
|
- check-success=CodeQL-Build
|
||||||
|
- check-success=CodeQL
|
||||||
|
- check-success=lint
|
||||||
|
- check-success=upgrade-test (kindest/node:v1.19.11, ubuntu-latest)
|
||||||
|
- check-success=integration-test (v1.19.11, ubuntu-latest)
|
||||||
|
- check-success=integration-test (v1.20.7, ubuntu-latest)
|
||||||
|
- check-success=integration-test (v1.21.1, ubuntu-latest)
|
||||||
actions:
|
actions:
|
||||||
merge:
|
merge:
|
||||||
method: squash
|
method: squash
|
||||||
commit_message: title+body
|
commit_message: title+body
|
||||||
strict: smart
|
|
||||||
|
|||||||
@@ -1,5 +1,18 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [v1.15.1](https://github.com/fission/fission/tree/v1.15.1) (2021-12-28)
|
||||||
|
|
||||||
|
[Full Changelog](https://github.com/fission/fission/compare/v1.15.0...v1.15.1)
|
||||||
|
|
||||||
|
**Merged pull requests:**
|
||||||
|
|
||||||
|
- MQT Kafka: Use Sarama Group Consumer instead of bsm/sarama-cluster library [\#2286](https://github.com/fission/fission/pull/2286) ([sanketsudake](https://github.com/sanketsudake))
|
||||||
|
- Capture error from schema check in preupgrade verification [\#2285](https://github.com/fission/fission/pull/2285) ([sanketsudake](https://github.com/sanketsudake))
|
||||||
|
- chore: Update dependency opencontainers/runc v1.0.3 [\#2281](https://github.com/fission/fission/pull/2281) ([sanketsudake](https://github.com/sanketsudake))
|
||||||
|
- Allow user to use existing bucket with same name via fission storage service [\#2275](https://github.com/fission/fission/pull/2275) ([YachikaRalhan](https://github.com/YachikaRalhan))
|
||||||
|
- Retry pod choose if we get terminated or deleted pod from ready pod controller [\#2274](https://github.com/fission/fission/pull/2274) ([sanketsudake](https://github.com/sanketsudake))
|
||||||
|
- Add support for generating CRD docs [\#2273](https://github.com/fission/fission/pull/2273) ([sanketsudake](https://github.com/sanketsudake))
|
||||||
|
|
||||||
## [v1.15.0](https://github.com/fission/fission/tree/v1.15.0) (2021-11-23)
|
## [v1.15.0](https://github.com/fission/fission/tree/v1.15.0) (2021-11-23)
|
||||||
|
|
||||||
[Full Changelog](https://github.com/fission/fission/compare/v1.15.0-rc2...v1.15.0)
|
[Full Changelog](https://github.com/fission/fission/compare/v1.15.0-rc2...v1.15.0)
|
||||||
|
|||||||
@@ -80,14 +80,14 @@ generate-swagger-doc:
|
|||||||
@./hack/update-swagger-docs.sh
|
@./hack/update-swagger-docs.sh
|
||||||
|
|
||||||
generate-cli-docs:
|
generate-cli-docs:
|
||||||
go run tools/cmd-docs/main.go -o "../fission.io/content/en/docs/fission-cli"
|
go run tools/cmd-docs/main.go -o "../fission.io/content/en/docs/reference/fission-cli"
|
||||||
|
|
||||||
generate-crd-ref-docs:
|
generate-crd-ref-docs:
|
||||||
# crd-ref-docs: https://github.com/elastic/crd-ref-docs
|
# crd-ref-docs: https://github.com/elastic/crd-ref-docs
|
||||||
crd-ref-docs --source-path=pkg/apis/core/v1 --config=tools/crd-ref-docs/config.yaml --renderer markdown
|
crd-ref-docs --source-path=pkg/apis/core/v1 --config=tools/crd-ref-docs/config.yaml --renderer markdown
|
||||||
cp tools/crd-ref-docs/header.md crd_docs.md
|
cp tools/crd-ref-docs/header.md crd_docs.md
|
||||||
cat out.md >> crd_docs.md && rm out.md
|
cat out.md >> crd_docs.md && rm out.md
|
||||||
cp crd_docs.md ../fission.io/content/en/docs/crd/_index.md
|
mv crd_docs.md ../fission.io/content/en/docs/reference/crd-reference.md
|
||||||
|
|
||||||
all-generators: codegen generate-crds generate-swagger-doc
|
all-generators: codegen generate-crds generate-swagger-doc
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
name: fission-all
|
name: fission-all
|
||||||
version: v1.15.1
|
version: v1.16.0-rc1
|
||||||
appVersion: v1.15.1
|
appVersion: v1.16.0-rc1
|
||||||
description: Fission is a fast serverless framework for Kubernetes.
|
description: Fission is a fast serverless framework for Kubernetes.
|
||||||
home: https://fission.io/
|
home: https://fission.io/
|
||||||
icon: https://fission.io/images/fission-logo-white.svg
|
icon: https://fission.io/images/fission-logo-white.svg
|
||||||
|
|||||||
@@ -20,6 +20,15 @@ Windows:
|
|||||||
# Register this function with Fission
|
# Register this function with Fission
|
||||||
$ fission function create --name hello --env nodejs --code hello.js
|
$ fission function create --name hello --env nodejs --code hello.js
|
||||||
|
|
||||||
|
{{- if .Values.authentication.enabled }}
|
||||||
|
|
||||||
|
# Create token
|
||||||
|
$ FISSION_USERNAME=$(kubectl get secrets/router --template={{`{{.data.username}}`}} -n fission | base64 -d)
|
||||||
|
$ FISSION_PASSWORD=$(kubectl get secrets/router --template={{`{{.data.password}}`}} -n fission | base64 -d)
|
||||||
|
$ export FISSION_AUTH_TOKEN=$(fission token create --username $FISSION_USERNAME --password $FISSION_PASSWORD)
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
# Run this function
|
# Run this function
|
||||||
$ fission function test --name hello
|
$ fission function test --name hello
|
||||||
Hello, world!
|
Hello, world!
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,13 @@ canary:
|
|||||||
prometheusSvc: {{ .Values.prometheus.serviceEndpoint | default "" | quote }}
|
prometheusSvc: {{ .Values.prometheus.serviceEndpoint | default "" | quote }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- printf "\n" -}}
|
{{- printf "\n" -}}
|
||||||
|
auth:
|
||||||
|
enabled: {{ .Values.authentication.enabled | default false }}
|
||||||
|
{{- if .Values.authentication.enabled }}
|
||||||
|
authUriPath: {{ .Values.authentication.authUriPath | default "/auth/login" | quote}}
|
||||||
|
jwtExpiryTime: {{ .Values.authentication.jwtExpiryTime | default 120 }}
|
||||||
|
jwtIssuer: {{ .Values.authentication.jwtIssuer | default "fission" | quote }}
|
||||||
|
{{- end }}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|
||||||
{{/*
|
{{/*
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ spec:
|
|||||||
value: {{ .Values.debugEnv | quote }}
|
value: {{ .Values.debugEnv | quote }}
|
||||||
- name: PPROF_ENABLED
|
- name: PPROF_ENABLED
|
||||||
value: {{ .Values.pprof.enabled | quote }}
|
value: {{ .Values.pprof.enabled | quote }}
|
||||||
|
- name: HELM_RELEASE_NAME
|
||||||
|
value: {{ .Release.Name | quote }}
|
||||||
{{- include "opentracing.envs" . | indent 8 }}
|
{{- include "opentracing.envs" . | indent 8 }}
|
||||||
{{- include "opentelemtry.envs" . | indent 8 }}
|
{{- include "opentelemtry.envs" . | indent 8 }}
|
||||||
{{- if .Values.terminationMessagePath }}
|
{{- if .Values.terminationMessagePath }}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: ClusterRole
|
kind: ClusterRole
|
||||||
metadata:
|
metadata:
|
||||||
name: fission-cr-admin
|
name: {{ .Release.Name }}-fission-cr-admin
|
||||||
rules:
|
rules:
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- ""
|
- ""
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
kind: ClusterRoleBinding
|
kind: ClusterRoleBinding
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: fission-cr-admin
|
name: {{ .Release.Name }}-fission-cr-admin
|
||||||
subjects:
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: fission-svc
|
name: fission-svc
|
||||||
namespace: {{ .Release.Namespace }}
|
namespace: {{ .Release.Namespace }}
|
||||||
roleRef:
|
roleRef:
|
||||||
kind: ClusterRole
|
kind: ClusterRole
|
||||||
name: fission-cr-admin
|
name: {{ .Release.Name }}-fission-cr-admin
|
||||||
apiGroup: rbac.authorization.k8s.io
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
|||||||
@@ -54,6 +54,8 @@ spec:
|
|||||||
value: {{ .Values.debugEnv | quote }}
|
value: {{ .Values.debugEnv | quote }}
|
||||||
- name: PPROF_ENABLED
|
- name: PPROF_ENABLED
|
||||||
value: {{ .Values.pprof.enabled | quote }}
|
value: {{ .Values.pprof.enabled | quote }}
|
||||||
|
- name: HELM_RELEASE_NAME
|
||||||
|
value: {{ .Release.Name | quote }}
|
||||||
{{- include "opentracing.envs" . | indent 8 }}
|
{{- include "opentracing.envs" . | indent 8 }}
|
||||||
{{- include "opentelemtry.envs" . | indent 8 }}
|
{{- include "opentelemtry.envs" . | indent 8 }}
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: ClusterRole
|
kind: ClusterRole
|
||||||
metadata:
|
metadata:
|
||||||
name: secret-configmap-getter
|
name: {{ .Release.Name }}-secret-configmap-getter
|
||||||
rules:
|
rules:
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- "*"
|
- "*"
|
||||||
@@ -17,7 +17,7 @@ rules:
|
|||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: ClusterRole
|
kind: ClusterRole
|
||||||
metadata:
|
metadata:
|
||||||
name: package-getter
|
name: {{ .Release.Name }}-package-getter
|
||||||
rules:
|
rules:
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- "*"
|
- "*"
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: Role
|
kind: Role
|
||||||
metadata:
|
metadata:
|
||||||
name: fission-fetcher
|
name: {{ .Release.Name }}-fission-fetcher
|
||||||
namespace: default
|
namespace: {{ .Values.defaultNamespace }}
|
||||||
rules:
|
rules:
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- ""
|
- ""
|
||||||
@@ -38,8 +38,8 @@ rules:
|
|||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: Role
|
kind: Role
|
||||||
metadata:
|
metadata:
|
||||||
name: fission-builder
|
name: {{ .Release.Name }}-fission-builder
|
||||||
namespace: default
|
namespace: {{ .Values.defaultNamespace }}
|
||||||
rules:
|
rules:
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- fission.io
|
- fission.io
|
||||||
@@ -60,7 +60,7 @@ apiVersion: rbac.authorization.k8s.io/v1
|
|||||||
kind: Role
|
kind: Role
|
||||||
metadata:
|
metadata:
|
||||||
namespace: {{ .Values.functionNamespace }}
|
namespace: {{ .Values.functionNamespace }}
|
||||||
name: event-fetcher
|
name: {{ .Release.Name }}-event-fetcher
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""] # "" indicates the core API group
|
- apiGroups: [""] # "" indicates the core API group
|
||||||
resources: ["pods"]
|
resources: ["pods"]
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: RoleBinding
|
kind: RoleBinding
|
||||||
metadata:
|
metadata:
|
||||||
name: fission-fetcher
|
name: {{ .Release.Name }}-fission-fetcher
|
||||||
namespace: default
|
namespace: {{ .Values.defaultNamespace }}
|
||||||
roleRef:
|
roleRef:
|
||||||
apiGroup: rbac.authorization.k8s.io
|
apiGroup: rbac.authorization.k8s.io
|
||||||
kind: Role
|
kind: Role
|
||||||
name: fission-fetcher
|
name: {{ .Release.Name }}-fission-fetcher
|
||||||
subjects:
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: fission-fetcher
|
name: fission-fetcher
|
||||||
@@ -16,12 +16,12 @@ subjects:
|
|||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: RoleBinding
|
kind: RoleBinding
|
||||||
metadata:
|
metadata:
|
||||||
name: fission-builder
|
name: {{ .Release.Name }}-fission-builder
|
||||||
namespace: default
|
namespace: {{ .Values.defaultNamespace }}
|
||||||
roleRef:
|
roleRef:
|
||||||
apiGroup: rbac.authorization.k8s.io
|
apiGroup: rbac.authorization.k8s.io
|
||||||
kind: Role
|
kind: Role
|
||||||
name: fission-builder
|
name: {{ .Release.Name }}-fission-builder
|
||||||
subjects:
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: fission-builder
|
name: fission-builder
|
||||||
@@ -31,12 +31,12 @@ subjects:
|
|||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: RoleBinding
|
kind: RoleBinding
|
||||||
metadata:
|
metadata:
|
||||||
name: fission-fetcher-pod-reader
|
name: {{ .Release.Name }}-fission-fetcher-pod-reader
|
||||||
namespace: {{ .Values.functionNamespace }}
|
namespace: {{ .Values.functionNamespace }}
|
||||||
roleRef:
|
roleRef:
|
||||||
apiGroup: rbac.authorization.k8s.io
|
apiGroup: rbac.authorization.k8s.io
|
||||||
kind: Role
|
kind: Role
|
||||||
name: event-fetcher
|
name: {{ .Release.Name }}-event-fetcher
|
||||||
subjects:
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: fission-fetcher
|
name: fission-fetcher
|
||||||
|
|||||||
@@ -35,6 +35,23 @@ spec:
|
|||||||
command: ["/fission-bundle"]
|
command: ["/fission-bundle"]
|
||||||
args: ["--routerPort", "8888", "--executorUrl", "http://executor.{{ .Release.Namespace }}"]
|
args: ["--routerPort", "8888", "--executorUrl", "http://executor.{{ .Release.Namespace }}"]
|
||||||
env:
|
env:
|
||||||
|
{{- if .Values.authentication.enabled }}
|
||||||
|
- name: AUTH_USERNAME
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: router
|
||||||
|
key: username
|
||||||
|
- name: AUTH_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: router
|
||||||
|
key: password
|
||||||
|
- name: JWT_SIGNING_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: router
|
||||||
|
key: jwtSigningKey
|
||||||
|
{{- end }}
|
||||||
- name: POD_NAMESPACE
|
- name: POD_NAMESPACE
|
||||||
valueFrom:
|
valueFrom:
|
||||||
fieldRef:
|
fieldRef:
|
||||||
@@ -80,6 +97,10 @@ spec:
|
|||||||
port: 8888
|
port: 8888
|
||||||
initialDelaySeconds: 35
|
initialDelaySeconds: 35
|
||||||
periodSeconds: 5
|
periodSeconds: 5
|
||||||
|
volumeMounts:
|
||||||
|
- name: config-volume
|
||||||
|
mountPath: /etc/config/config.yaml
|
||||||
|
subPath: config.yaml
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 8080
|
- containerPort: 8080
|
||||||
name: metrics
|
name: metrics
|
||||||
@@ -100,6 +121,10 @@ spec:
|
|||||||
terminationMessagePolicy: {{ .Values.terminationMessagePolicy }}
|
terminationMessagePolicy: {{ .Values.terminationMessagePolicy }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
serviceAccountName: fission-svc
|
serviceAccountName: fission-svc
|
||||||
|
volumes:
|
||||||
|
- name: config-volume
|
||||||
|
configMap:
|
||||||
|
name: feature-config
|
||||||
{{- if .Values.router.priorityClassName }}
|
{{- if .Values.router.priorityClassName }}
|
||||||
priorityClassName: {{ .Values.router.priorityClassName }}
|
priorityClassName: {{ .Values.router.priorityClassName }}
|
||||||
{{- else if .Values.priorityClassName }}
|
{{- else if .Values.priorityClassName }}
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{{- if .Values.authentication.enabled }}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: router
|
||||||
|
labels:
|
||||||
|
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
||||||
|
annotations:
|
||||||
|
"helm.sh/hook": pre-install
|
||||||
|
data:
|
||||||
|
username: {{ .Values.authentication.authUsername | b64enc | quote }}
|
||||||
|
password: {{ randAlphaNum 20 | b64enc | quote }}
|
||||||
|
jwtSigningKey: {{ .Values.authentication.jwtSigningKey | b64enc | quote }}
|
||||||
|
{{- end }}
|
||||||
@@ -25,7 +25,7 @@ image: fission/fission-bundle
|
|||||||
## It is also used by the chart to identify version of the few more images apart from fission-bundle.
|
## It is also used by the chart to identify version of the few more images apart from fission-bundle.
|
||||||
## Keep it empty for using latest tag.
|
## Keep it empty for using latest tag.
|
||||||
##
|
##
|
||||||
imageTag: v1.15.1
|
imageTag: v1.16.0-rc1
|
||||||
|
|
||||||
## pullPolicy represents the pull policy to use for images in the chart.
|
## pullPolicy represents the pull policy to use for images in the chart.
|
||||||
##
|
##
|
||||||
@@ -68,6 +68,10 @@ functionNamespace: fission-function
|
|||||||
##
|
##
|
||||||
builderNamespace: fission-builder
|
builderNamespace: fission-builder
|
||||||
|
|
||||||
|
## defaultNamespace represents the default namespace in Kubernetes.
|
||||||
|
##
|
||||||
|
defaultNamespace: default
|
||||||
|
|
||||||
## createNamespace decides to create namespaces by the chart.
|
## createNamespace decides to create namespaces by the chart.
|
||||||
## If set to true, functionNamespace and builderNamespace namespaces mentioned above will be created by the chart.
|
## If set to true, functionNamespace and builderNamespace namespaces mentioned above will be created by the chart.
|
||||||
## Set to false if you want to create the namespaces manually.
|
## Set to false if you want to create the namespaces manually.
|
||||||
@@ -85,7 +89,7 @@ fetcher:
|
|||||||
## image represents the image of the fetcher component.
|
## image represents the image of the fetcher component.
|
||||||
image: fission/fetcher
|
image: fission/fetcher
|
||||||
## imageTag represents the tag of the image of the fetcher component.
|
## imageTag represents the tag of the image of the fetcher component.
|
||||||
imageTag: v1.15.1
|
imageTag: v1.16.0-rc1
|
||||||
|
|
||||||
## Fetcher is only for to downloading or uploading archive.
|
## Fetcher is only for to downloading or uploading archive.
|
||||||
## Normally, you don't need to change the value here, unless necessary.
|
## Normally, you don't need to change the value here, unless necessary.
|
||||||
@@ -157,7 +161,6 @@ router:
|
|||||||
## router resource utilization when under heavy workloads.
|
## router resource utilization when under heavy workloads.
|
||||||
##
|
##
|
||||||
displayAccessLog: false
|
displayAccessLog: false
|
||||||
|
|
||||||
## svcAnnotations is the annotations to be added to the service resource created for router.
|
## svcAnnotations is the annotations to be added to the service resource created for router.
|
||||||
##
|
##
|
||||||
# svcAnnotations:
|
# svcAnnotations:
|
||||||
@@ -451,7 +454,7 @@ preUpgradeChecks:
|
|||||||
image: fission/pre-upgrade-checks
|
image: fission/pre-upgrade-checks
|
||||||
## pre-install/pre-upgrade checks image version
|
## pre-install/pre-upgrade checks image version
|
||||||
##
|
##
|
||||||
imageTag: v1.15.1
|
imageTag: v1.16.0-rc1
|
||||||
|
|
||||||
## Fission post-install/post-upgrade reporting live in this image
|
## Fission post-install/post-upgrade reporting live in this image
|
||||||
##
|
##
|
||||||
@@ -479,6 +482,37 @@ prometheus:
|
|||||||
canaryDeployment:
|
canaryDeployment:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
|
## Enable authentication for fission function invocation via Fission router
|
||||||
|
##
|
||||||
|
authentication:
|
||||||
|
## set this flag to true if you need authentication
|
||||||
|
## for all function invocations
|
||||||
|
## default 'false'
|
||||||
|
##
|
||||||
|
enabled: false
|
||||||
|
## authUriPath defines authentication endpoint path
|
||||||
|
## via router
|
||||||
|
## default '/auth/login'
|
||||||
|
##
|
||||||
|
authUriPath:
|
||||||
|
## authUsername is used as a username for authentication
|
||||||
|
## default 'admin'
|
||||||
|
##
|
||||||
|
authUsername: admin
|
||||||
|
## jwtSigningKey is the signing key used for
|
||||||
|
## signing the JWT token
|
||||||
|
##
|
||||||
|
jwtSigningKey: serverless
|
||||||
|
## jwtExpiryTime is the JWT expiry time
|
||||||
|
## in seconds
|
||||||
|
## default '120'
|
||||||
|
##
|
||||||
|
jwtExpiryTime:
|
||||||
|
## jwtIssuer is the issuer of JWT
|
||||||
|
## default 'fission'
|
||||||
|
##
|
||||||
|
jwtIssuer: fission
|
||||||
|
|
||||||
## Use the following flags to enable OpenTracing.
|
## Use the following flags to enable OpenTracing.
|
||||||
## Note: OpenTracing support will be removed in an upcoming release.
|
## Note: OpenTracing support will be removed in an upcoming release.
|
||||||
## Please prefer using OpenTelemetry instead.
|
## Please prefer using OpenTelemetry instead.
|
||||||
|
|||||||
@@ -1,3 +1,16 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2022 The Fission Authors.
|
||||||
|
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://www.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.
|
||||||
|
*/
|
||||||
|
|
||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -10,6 +23,7 @@ import (
|
|||||||
"github.com/fission/fission/pkg/fission-cli/cliwrapper/driver/cobra/helptemplate"
|
"github.com/fission/fission/pkg/fission-cli/cliwrapper/driver/cobra/helptemplate"
|
||||||
"github.com/fission/fission/pkg/fission-cli/cmd"
|
"github.com/fission/fission/pkg/fission-cli/cmd"
|
||||||
"github.com/fission/fission/pkg/fission-cli/cmd/canaryconfig"
|
"github.com/fission/fission/pkg/fission-cli/cmd/canaryconfig"
|
||||||
|
"github.com/fission/fission/pkg/fission-cli/cmd/check"
|
||||||
"github.com/fission/fission/pkg/fission-cli/cmd/environment"
|
"github.com/fission/fission/pkg/fission-cli/cmd/environment"
|
||||||
"github.com/fission/fission/pkg/fission-cli/cmd/function"
|
"github.com/fission/fission/pkg/fission-cli/cmd/function"
|
||||||
"github.com/fission/fission/pkg/fission-cli/cmd/httptrigger"
|
"github.com/fission/fission/pkg/fission-cli/cmd/httptrigger"
|
||||||
@@ -19,6 +33,7 @@ import (
|
|||||||
"github.com/fission/fission/pkg/fission-cli/cmd/spec"
|
"github.com/fission/fission/pkg/fission-cli/cmd/spec"
|
||||||
"github.com/fission/fission/pkg/fission-cli/cmd/support"
|
"github.com/fission/fission/pkg/fission-cli/cmd/support"
|
||||||
"github.com/fission/fission/pkg/fission-cli/cmd/timetrigger"
|
"github.com/fission/fission/pkg/fission-cli/cmd/timetrigger"
|
||||||
|
"github.com/fission/fission/pkg/fission-cli/cmd/token"
|
||||||
"github.com/fission/fission/pkg/fission-cli/cmd/version"
|
"github.com/fission/fission/pkg/fission-cli/cmd/version"
|
||||||
"github.com/fission/fission/pkg/fission-cli/console"
|
"github.com/fission/fission/pkg/fission-cli/console"
|
||||||
"github.com/fission/fission/pkg/fission-cli/flag"
|
"github.com/fission/fission/pkg/fission-cli/flag"
|
||||||
@@ -77,11 +92,12 @@ func App() *cobra.Command {
|
|||||||
})
|
})
|
||||||
|
|
||||||
groups := helptemplate.CommandGroups{}
|
groups := helptemplate.CommandGroups{}
|
||||||
|
groups = append(groups, helptemplate.CreateCmdGroup("Auth Commands(Note: Authentication should be enabled to use a command in this group.)", token.Commands()))
|
||||||
groups = append(groups, helptemplate.CreateCmdGroup("Basic Commands", environment.Commands(), _package.Commands(), function.Commands()))
|
groups = append(groups, helptemplate.CreateCmdGroup("Basic Commands", environment.Commands(), _package.Commands(), function.Commands()))
|
||||||
groups = append(groups, helptemplate.CreateCmdGroup("Trigger Commands", httptrigger.Commands(), mqtrigger.Commands(), timetrigger.Commands(), kubewatch.Commands()))
|
groups = append(groups, helptemplate.CreateCmdGroup("Trigger Commands", httptrigger.Commands(), mqtrigger.Commands(), timetrigger.Commands(), kubewatch.Commands()))
|
||||||
groups = append(groups, helptemplate.CreateCmdGroup("Deploy Strategies Commands", canaryconfig.Commands()))
|
groups = append(groups, helptemplate.CreateCmdGroup("Deploy Strategies Commands", canaryconfig.Commands()))
|
||||||
groups = append(groups, helptemplate.CreateCmdGroup("Declarative Application Commands", spec.Commands()))
|
groups = append(groups, helptemplate.CreateCmdGroup("Declarative Application Commands", spec.Commands()))
|
||||||
groups = append(groups, helptemplate.CreateCmdGroup("Other Commands", support.Commands(), version.Commands()))
|
groups = append(groups, helptemplate.CreateCmdGroup("Other Commands", support.Commands(), version.Commands(), check.Commands()))
|
||||||
groups.Add(rootCmd)
|
groups.Add(rootCmd)
|
||||||
|
|
||||||
flagExposer := helptemplate.ActsAsRootCommand(rootCmd, nil, groups...)
|
flagExposer := helptemplate.ActsAsRootCommand(rootCmd, nil, groups...)
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ require (
|
|||||||
github.com/go-git/go-git/v5 v5.4.2
|
github.com/go-git/go-git/v5 v5.4.2
|
||||||
github.com/go-ini/ini v1.63.2 // indirect
|
github.com/go-ini/ini v1.63.2 // indirect
|
||||||
github.com/go-openapi/spec v0.20.4
|
github.com/go-openapi/spec v0.20.4
|
||||||
|
github.com/golang-jwt/jwt/v4 v4.2.0
|
||||||
github.com/gorilla/mux v1.8.0
|
github.com/gorilla/mux v1.8.0
|
||||||
github.com/gotestyourself/gotestyourself v2.2.0+incompatible // indirect
|
github.com/gotestyourself/gotestyourself v2.2.0+incompatible // indirect
|
||||||
github.com/graymeta/stow v0.2.7
|
github.com/graymeta/stow v0.2.7
|
||||||
|
|||||||
@@ -492,7 +492,10 @@ github.com/gogo/protobuf v1.2.2-0.20190730201129-28a6bbf47e48/go.mod h1:SlYgWuQ5
|
|||||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
|
github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c=
|
||||||
github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||||
|
github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU=
|
||||||
|
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||||
|
|||||||
@@ -16,6 +16,10 @@ limitations under the License.
|
|||||||
|
|
||||||
package v1
|
package v1
|
||||||
|
|
||||||
|
var (
|
||||||
|
MinimumKubernetesVersion = [3]int{1, 19, 0}
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
EXECUTOR_INSTANCEID_LABEL string = "executorInstanceId"
|
EXECUTOR_INSTANCEID_LABEL string = "executorInstanceId"
|
||||||
DEFAULT_FUNCTION_TIMEOUT int = 60
|
DEFAULT_FUNCTION_TIMEOUT int = 60
|
||||||
@@ -140,10 +144,8 @@ const (
|
|||||||
FissionBuilderSA = "fission-builder"
|
FissionBuilderSA = "fission-builder"
|
||||||
FissionFetcherSA = "fission-fetcher"
|
FissionFetcherSA = "fission-fetcher"
|
||||||
|
|
||||||
SecretConfigMapGetterCR = "secret-configmap-getter"
|
|
||||||
SecretConfigMapGetterRB = "secret-configmap-getter-binding"
|
SecretConfigMapGetterRB = "secret-configmap-getter-binding"
|
||||||
|
|
||||||
PackageGetterCR = "package-getter"
|
|
||||||
PackageGetterRB = "package-getter-binding"
|
PackageGetterRB = "package-getter-binding"
|
||||||
|
|
||||||
ClusterRole = "ClusterRole"
|
ClusterRole = "ClusterRole"
|
||||||
|
|||||||
@@ -854,6 +854,18 @@ type (
|
|||||||
GetObjectKind() schema.ObjectKind
|
GetObjectKind() schema.ObjectKind
|
||||||
GetObjectMeta() metav1.Object
|
GetObjectMeta() metav1.Object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AuthLogin defines the body for router login
|
||||||
|
AuthLogin struct {
|
||||||
|
Username string `json:"username"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RouterAuthToken defines the authorization token for accessing router
|
||||||
|
RouterAuthToken struct {
|
||||||
|
AccessToken string `json:"accesstoken"`
|
||||||
|
TokenType string `json:"tokentype"`
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
//IsEmpty checks if the archive byte and litreal are of length 0
|
//IsEmpty checks if the archive byte and litreal are of length 0
|
||||||
|
|||||||
@@ -47,6 +47,22 @@ func (in *Archive) DeepCopy() *Archive {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *AuthLogin) DeepCopyInto(out *AuthLogin) {
|
||||||
|
*out = *in
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthLogin.
|
||||||
|
func (in *AuthLogin) DeepCopy() *AuthLogin {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(AuthLogin)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *Builder) DeepCopyInto(out *Builder) {
|
func (in *Builder) DeepCopyInto(out *Builder) {
|
||||||
*out = *in
|
*out = *in
|
||||||
@@ -883,6 +899,22 @@ func (in *PackageStatus) DeepCopy() *PackageStatus {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *RouterAuthToken) DeepCopyInto(out *RouterAuthToken) {
|
||||||
|
*out = *in
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouterAuthToken.
|
||||||
|
func (in *RouterAuthToken) DeepCopy() *RouterAuthToken {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(RouterAuthToken)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *Runtime) DeepCopyInto(out *Runtime) {
|
func (in *Runtime) DeepCopyInto(out *Runtime) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
|||||||
@@ -22,6 +22,14 @@ func (Archive) SwaggerDoc() map[string]string {
|
|||||||
return map_Archive
|
return map_Archive
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var map_AuthLogin = map[string]string{
|
||||||
|
"": "AuthLogin defines the body for router login",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (AuthLogin) SwaggerDoc() map[string]string {
|
||||||
|
return map_AuthLogin
|
||||||
|
}
|
||||||
|
|
||||||
var map_Builder = map[string]string{
|
var map_Builder = map[string]string{
|
||||||
"": "Builder is the setting for environment builder.",
|
"": "Builder is the setting for environment builder.",
|
||||||
"image": "Image for containing the language compilation environment.",
|
"image": "Image for containing the language compilation environment.",
|
||||||
@@ -370,6 +378,14 @@ func (PackageStatus) SwaggerDoc() map[string]string {
|
|||||||
return map_PackageStatus
|
return map_PackageStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var map_RouterAuthToken = map[string]string{
|
||||||
|
"": "RouterAuthToken defines the authorization token for accessing router",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (RouterAuthToken) SwaggerDoc() map[string]string {
|
||||||
|
return map_RouterAuthToken
|
||||||
|
}
|
||||||
|
|
||||||
var map_Runtime = map[string]string{
|
var map_Runtime = map[string]string{
|
||||||
"": "Runtime is the setting for environment runtime.",
|
"": "Runtime is the setting for environment runtime.",
|
||||||
"image": "Image for containing the language runtime.",
|
"image": "Image for containing the language runtime.",
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ func (pkgw *packageWatcher) build(ctx context.Context, srcpkg *fv1.Package) {
|
|||||||
// Add the package getter rolebinding to builder sa
|
// Add the package getter rolebinding to builder sa
|
||||||
// we continue here if role binding was not setup successfully. this is because without this, the fetcher won't be able to fetch the source pkg into the container and
|
// we continue here if role binding was not setup successfully. this is because without this, the fetcher won't be able to fetch the source pkg into the container and
|
||||||
// the build will fail eventually
|
// the build will fail eventually
|
||||||
err := utils.SetupRoleBinding(ctx, pkgw.logger, pkgw.k8sClient, fv1.PackageGetterRB, pkg.ObjectMeta.Namespace, fv1.PackageGetterCR, fv1.ClusterRole, fv1.FissionBuilderSA, builderNs)
|
err := utils.SetupRoleBinding(ctx, pkgw.logger, pkgw.k8sClient, fv1.PackageGetterRB, pkg.ObjectMeta.Namespace, utils.GetPackageGetterCR(), fv1.ClusterRole, fv1.FissionBuilderSA, builderNs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pkgw.logger.Error("error setting up role binding for package",
|
pkgw.logger.Error("error setting up role binding for package",
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
|
|||||||
@@ -23,7 +23,9 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
|
||||||
"github.com/fission/fission/pkg/controller/client/rest"
|
"github.com/fission/fission/pkg/controller/client/rest"
|
||||||
"github.com/fission/fission/pkg/fission-cli/console"
|
"github.com/fission/fission/pkg/fission-cli/console"
|
||||||
@@ -62,6 +64,9 @@ func (c *Misc) SecretExists(m *metav1.ObjectMeta) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
if resp.StatusCode >= 400 {
|
||||||
|
return k8serrors.NewNotFound(schema.GroupResource{Group: "", Resource: "secret"}, m.Name)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,6 +79,9 @@ func (c *Misc) ConfigMapExists(m *metav1.ObjectMeta) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
if resp.StatusCode >= 400 {
|
||||||
|
return k8serrors.NewNotFound(schema.GroupResource{Group: "", Resource: "configmap"}, m.Name)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,8 @@ func MakeErrorFromHTTP(resp *http.Response) error {
|
|||||||
errCode = ErrorRequestTimeout
|
errCode = ErrorRequestTimeout
|
||||||
case http.StatusTooManyRequests:
|
case http.StatusTooManyRequests:
|
||||||
errCode = ErrorTooManyRequests
|
errCode = ErrorTooManyRequests
|
||||||
|
case http.StatusUnauthorized:
|
||||||
|
errCode = ErrorNotAuthorized
|
||||||
default:
|
default:
|
||||||
errCode = ErrorInternal
|
errCode = ErrorInternal
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -172,6 +172,9 @@ func (cn *Container) getDeploymentSpec(ctx context.Context, fn *fv1.Function, ta
|
|||||||
}
|
}
|
||||||
|
|
||||||
gracePeriodSeconds := int64(6 * 60)
|
gracePeriodSeconds := int64(6 * 60)
|
||||||
|
if *fn.Spec.PodSpec.TerminationGracePeriodSeconds >= 0 {
|
||||||
|
gracePeriodSeconds = *fn.Spec.PodSpec.TerminationGracePeriodSeconds
|
||||||
|
}
|
||||||
|
|
||||||
podAnnotations := make(map[string]string)
|
podAnnotations := make(map[string]string)
|
||||||
|
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ func (deploy *NewDeploy) setupRBACObjs(ctx context.Context, deployNamespace stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create a cluster role binding for the fetcher SA, if not already created, granting access to do a get on packages in any ns
|
// create a cluster role binding for the fetcher SA, if not already created, granting access to do a get on packages in any ns
|
||||||
err = utils.SetupRoleBinding(ctx, deploy.logger, deploy.kubernetesClient, fv1.PackageGetterRB, fn.Spec.Package.PackageRef.Namespace, fv1.PackageGetterCR, fv1.ClusterRole, fv1.FissionFetcherSA, deployNamespace)
|
err = utils.SetupRoleBinding(ctx, deploy.logger, deploy.kubernetesClient, fv1.PackageGetterRB, fn.Spec.Package.PackageRef.Namespace, utils.GetPackageGetterCR(), fv1.ClusterRole, fv1.FissionFetcherSA, deployNamespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
deploy.logger.Error("error creating role binding for function",
|
deploy.logger.Error("error creating role binding for function",
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
@@ -151,7 +151,7 @@ func (deploy *NewDeploy) setupRBACObjs(ctx context.Context, deployNamespace stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create rolebinding in function namespace for fetcherSA.envNamespace to be able to get secrets and configmaps
|
// create rolebinding in function namespace for fetcherSA.envNamespace to be able to get secrets and configmaps
|
||||||
err = utils.SetupRoleBinding(ctx, deploy.logger, deploy.kubernetesClient, fv1.SecretConfigMapGetterRB, fn.ObjectMeta.Namespace, fv1.SecretConfigMapGetterCR, fv1.ClusterRole, fv1.FissionFetcherSA, deployNamespace)
|
err = utils.SetupRoleBinding(ctx, deploy.logger, deploy.kubernetesClient, fv1.SecretConfigMapGetterRB, fn.ObjectMeta.Namespace, utils.GetSecretConfigMapGetterCR(), fv1.ClusterRole, fv1.FissionFetcherSA, deployNamespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
deploy.logger.Error("error creating role binding for function",
|
deploy.logger.Error("error creating role binding for function",
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ func FunctionEventHandlers(logger *zap.Logger, kubernetesClient *kubernetes.Clie
|
|||||||
// setup rolebinding is tried, if it fails, we don't return. we just log an error and move on, because :
|
// setup rolebinding is tried, if it fails, we don't return. we just log an error and move on, because :
|
||||||
// 1. not all functions have secrets and/or configmaps, so things will work without this rolebinding in that case.
|
// 1. not all functions have secrets and/or configmaps, so things will work without this rolebinding in that case.
|
||||||
// 2. on the contrary, when the route is tried, the env fetcher logs will show a 403 forbidden message and same will be relayed to executor.
|
// 2. on the contrary, when the route is tried, the env fetcher logs will show a 403 forbidden message and same will be relayed to executor.
|
||||||
err := utils.SetupRoleBinding(ctx, logger, kubernetesClient, fv1.SecretConfigMapGetterRB, fn.ObjectMeta.Namespace, fv1.SecretConfigMapGetterCR, fv1.ClusterRole, fv1.FissionFetcherSA, envNs)
|
err := utils.SetupRoleBinding(ctx, logger, kubernetesClient, fv1.SecretConfigMapGetterRB, fn.ObjectMeta.Namespace, utils.GetSecretConfigMapGetterCR(), fv1.ClusterRole, fv1.FissionFetcherSA, envNs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("error creating rolebinding", zap.Error(err), zap.String("role_binding", fv1.SecretConfigMapGetterRB))
|
logger.Error("error creating rolebinding", zap.Error(err), zap.String("role_binding", fv1.SecretConfigMapGetterRB))
|
||||||
} else {
|
} else {
|
||||||
@@ -185,7 +185,7 @@ func FunctionEventHandlers(logger *zap.Logger, kubernetesClient *kubernetes.Clie
|
|||||||
}
|
}
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
err := utils.SetupRoleBinding(ctx, logger, kubernetesClient, fv1.SecretConfigMapGetterRB,
|
err := utils.SetupRoleBinding(ctx, logger, kubernetesClient, fv1.SecretConfigMapGetterRB,
|
||||||
newFunc.ObjectMeta.Namespace, fv1.SecretConfigMapGetterCR, fv1.ClusterRole,
|
newFunc.ObjectMeta.Namespace, utils.GetSecretConfigMapGetterCR(), fv1.ClusterRole,
|
||||||
fv1.FissionFetcherSA, envNs)
|
fv1.FissionFetcherSA, envNs)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ func PackageEventHandlers(logger *zap.Logger, kubernetesClient *kubernetes.Clien
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
// here, we return if we hit an error during rolebinding setup. this is because this rolebinding is mandatory for
|
// here, we return if we hit an error during rolebinding setup. this is because this rolebinding is mandatory for
|
||||||
// every function's package to be loaded into its env. without that, there's no point to move forward.
|
// every function's package to be loaded into its env. without that, there's no point to move forward.
|
||||||
err := utils.SetupRoleBinding(ctx, logger, kubernetesClient, fv1.PackageGetterRB, pkg.ObjectMeta.Namespace, fv1.PackageGetterCR, fv1.ClusterRole, fv1.FissionFetcherSA, envNs)
|
err := utils.SetupRoleBinding(ctx, logger, kubernetesClient, fv1.PackageGetterRB, pkg.ObjectMeta.Namespace, utils.GetPackageGetterCR(), fv1.ClusterRole, fv1.FissionFetcherSA, envNs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("error creating rolebinding for package",
|
logger.Error("error creating rolebinding for package",
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
@@ -83,7 +83,7 @@ func PackageEventHandlers(logger *zap.Logger, kubernetesClient *kubernetes.Clien
|
|||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
err := utils.SetupRoleBinding(ctx, logger, kubernetesClient, fv1.PackageGetterRB,
|
err := utils.SetupRoleBinding(ctx, logger, kubernetesClient, fv1.PackageGetterRB,
|
||||||
newPkg.ObjectMeta.Namespace, fv1.PackageGetterCR, fv1.ClusterRole,
|
newPkg.ObjectMeta.Namespace, utils.GetPackageGetterCR(), fv1.ClusterRole,
|
||||||
fv1.FissionFetcherSA, envNs)
|
fv1.FissionFetcherSA, envNs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("error updating rolebinding for package",
|
logger.Error("error updating rolebinding for package",
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ limitations under the License.
|
|||||||
|
|
||||||
package featureconfig
|
package featureconfig
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
FeatureConfigFile = "/etc/config/config.yaml"
|
FeatureConfigFile = "/etc/config/config.yaml"
|
||||||
CanaryFeature = "canary"
|
CanaryFeature = "canary"
|
||||||
@@ -31,6 +33,7 @@ type (
|
|||||||
FeatureConfig struct {
|
FeatureConfig struct {
|
||||||
// In the future more such feature configs can be added here for each optional feature
|
// In the future more such feature configs can be added here for each optional feature
|
||||||
CanaryConfig CanaryFeatureConfig `json:"canary"`
|
CanaryConfig CanaryFeatureConfig `json:"canary"`
|
||||||
|
AuthConfig AuthFeatureConfig `json:"auth"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// specific feature config
|
// specific feature config
|
||||||
@@ -38,4 +41,11 @@ type (
|
|||||||
IsEnabled bool `json:"enabled"`
|
IsEnabled bool `json:"enabled"`
|
||||||
PrometheusSvc string `json:"prometheusSvc"`
|
PrometheusSvc string `json:"prometheusSvc"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AuthFeatureConfig struct {
|
||||||
|
IsEnabled bool `json:"enabled"`
|
||||||
|
AuthUriPath string `json:"authUriPath"`
|
||||||
|
JWTExpiryTime time.Duration `json:"jwtExpiryTime"`
|
||||||
|
JWTIssuer string `json:"jwtIssuer"`
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ func Commands() *cobra.Command {
|
|||||||
}
|
}
|
||||||
wrapper.SetFlags(deleteCmd, flag.FlagSet{
|
wrapper.SetFlags(deleteCmd, flag.FlagSet{
|
||||||
Required: []flag.Flag{flag.CanaryName},
|
Required: []flag.Flag{flag.CanaryName},
|
||||||
Optional: []flag.Flag{flag.NamespaceCanary},
|
Optional: []flag.Flag{flag.NamespaceCanary, flag.IgnoreNotFound},
|
||||||
})
|
})
|
||||||
|
|
||||||
listCmd := &cobra.Command{
|
listCmd := &cobra.Command{
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import (
|
|||||||
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
|
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
|
||||||
"github.com/fission/fission/pkg/fission-cli/cmd"
|
"github.com/fission/fission/pkg/fission-cli/cmd"
|
||||||
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
|
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
|
||||||
|
"github.com/fission/fission/pkg/fission-cli/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DeleteSubCommand struct {
|
type DeleteSubCommand struct {
|
||||||
@@ -43,6 +44,9 @@ func (opts *DeleteSubCommand) run(input cli.Input) error {
|
|||||||
|
|
||||||
err := opts.Client().V1().CanaryConfig().Delete(m)
|
err := opts.Client().V1().CanaryConfig().Delete(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return errors.Wrap(err, "error deleting canary config")
|
return errors.Wrap(err, "error deleting canary config")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2022 The Fission Authors.
|
||||||
|
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://www.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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package check
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
|
||||||
|
"github.com/fission/fission/pkg/fission-cli/cmd"
|
||||||
|
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
|
||||||
|
"github.com/fission/fission/pkg/healthcheck"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CheckSubCommand struct {
|
||||||
|
cmd.CommandActioner
|
||||||
|
}
|
||||||
|
|
||||||
|
func Check(input cli.Input) error {
|
||||||
|
return (&CheckSubCommand{}).do(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (opts *CheckSubCommand) do(input cli.Input) error {
|
||||||
|
|
||||||
|
kubeContext := input.String(flagkey.KubeContext)
|
||||||
|
|
||||||
|
checks := []healthcheck.CategoryID{}
|
||||||
|
|
||||||
|
if input.IsSet(flagkey.PreCheckOnly) {
|
||||||
|
checks = append(checks, healthcheck.Kubernetes)
|
||||||
|
} else {
|
||||||
|
checks = append(checks, healthcheck.FissionServices, healthcheck.FissionVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
hc := healthcheck.NewHealthChecker(checks, &healthcheck.Options{
|
||||||
|
KubeContext: kubeContext,
|
||||||
|
FissionClient: opts.Client(),
|
||||||
|
})
|
||||||
|
|
||||||
|
healthcheck.RunChecks(hc)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2022 The Fission Authors.
|
||||||
|
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://www.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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package check
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
wrapper "github.com/fission/fission/pkg/fission-cli/cliwrapper/driver/cobra"
|
||||||
|
"github.com/fission/fission/pkg/fission-cli/flag"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Commands() *cobra.Command {
|
||||||
|
command := &cobra.Command{
|
||||||
|
Use: "check",
|
||||||
|
Short: "Check the fission installation for potential problems",
|
||||||
|
Long: `Check the fission installation for potential problems.`,
|
||||||
|
RunE: wrapper.Wrapper(Check),
|
||||||
|
}
|
||||||
|
wrapper.SetFlags(command, flag.FlagSet{
|
||||||
|
Optional: []flag.Flag{flag.PreCheckOnly},
|
||||||
|
})
|
||||||
|
|
||||||
|
return command
|
||||||
|
}
|
||||||
@@ -72,7 +72,7 @@ func Commands() *cobra.Command {
|
|||||||
}
|
}
|
||||||
wrapper.SetFlags(deleteCmd, flag.FlagSet{
|
wrapper.SetFlags(deleteCmd, flag.FlagSet{
|
||||||
Required: []flag.Flag{flag.EnvName},
|
Required: []flag.Flag{flag.EnvName},
|
||||||
Optional: []flag.Flag{flag.NamespaceEnvironment},
|
Optional: []flag.Flag{flag.NamespaceEnvironment, flag.IgnoreNotFound, flag.EnvForce},
|
||||||
})
|
})
|
||||||
|
|
||||||
listCmd := &cobra.Command{
|
listCmd := &cobra.Command{
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import (
|
|||||||
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
|
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
|
||||||
"github.com/fission/fission/pkg/fission-cli/cmd"
|
"github.com/fission/fission/pkg/fission-cli/cmd"
|
||||||
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
|
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
|
||||||
|
"github.com/fission/fission/pkg/fission-cli/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DeleteSubCommand struct {
|
type DeleteSubCommand struct {
|
||||||
@@ -41,11 +42,29 @@ func (opts *DeleteSubCommand) do(input cli.Input) error {
|
|||||||
Namespace: input.String(flagkey.NamespaceEnvironment),
|
Namespace: input.String(flagkey.NamespaceEnvironment),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !input.Bool(flagkey.EnvForce) {
|
||||||
|
fns, err := opts.Client().V1().Function().List(metav1.NamespaceAll)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "Error getting functions wrt environment.")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, fn := range fns {
|
||||||
|
if fn.Spec.Environment.Name == m.Name &&
|
||||||
|
fn.Spec.Environment.Namespace == m.Namespace {
|
||||||
|
return errors.New("Environment is used by atleast one function.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err := opts.Client().V1().Environment().Delete(m)
|
err := opts.Client().V1().Environment().Delete(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return errors.Wrap(err, "error deleting environment")
|
return errors.Wrap(err, "error deleting environment")
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("environment '%v' deleted\n", m.Name)
|
fmt.Printf("environment '%v' deleted\n", m.Name)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ func Commands() *cobra.Command {
|
|||||||
}
|
}
|
||||||
wrapper.SetFlags(deleteCmd, flag.FlagSet{
|
wrapper.SetFlags(deleteCmd, flag.FlagSet{
|
||||||
Required: []flag.Flag{flag.FnName},
|
Required: []flag.Flag{flag.FnName},
|
||||||
Optional: []flag.Flag{flag.NamespaceFunction},
|
Optional: []flag.Flag{flag.NamespaceFunction, flag.IgnoreNotFound},
|
||||||
})
|
})
|
||||||
|
|
||||||
listCmd := &cobra.Command{
|
listCmd := &cobra.Command{
|
||||||
@@ -167,6 +167,7 @@ func Commands() *cobra.Command {
|
|||||||
flag.FnCfgMap, flag.FnSecret,
|
flag.FnCfgMap, flag.FnSecret,
|
||||||
flag.FnExecutionTimeout,
|
flag.FnExecutionTimeout,
|
||||||
flag.FnIdleTimeout,
|
flag.FnIdleTimeout,
|
||||||
|
flag.FnTerminationGracePeriod,
|
||||||
flag.Labels, flag.Annotation,
|
flag.Labels, flag.Annotation,
|
||||||
|
|
||||||
// flag for newdeploy to use.
|
// flag for newdeploy to use.
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
|
|||||||
|
|
||||||
if toSpec {
|
if toSpec {
|
||||||
|
|
||||||
fr, err := spec.ReadSpecs(specDir, specIgnore)
|
fr, err := spec.ReadSpecs(specDir, specIgnore, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
||||||
}
|
}
|
||||||
@@ -169,7 +169,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
|
|||||||
|
|
||||||
if toSpec {
|
if toSpec {
|
||||||
|
|
||||||
fr, err := spec.ReadSpecs(specDir, specIgnore)
|
fr, err := spec.ReadSpecs(specDir, specIgnore, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import (
|
|||||||
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
|
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
|
||||||
"github.com/fission/fission/pkg/fission-cli/cmd"
|
"github.com/fission/fission/pkg/fission-cli/cmd"
|
||||||
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
|
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
|
||||||
|
"github.com/fission/fission/pkg/fission-cli/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DeleteSubCommand struct {
|
type DeleteSubCommand struct {
|
||||||
@@ -43,6 +44,9 @@ func (opts *DeleteSubCommand) do(input cli.Input) error {
|
|||||||
|
|
||||||
err := opts.Client().V1().Function().Delete(m)
|
err := opts.Client().V1().Function().Delete(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return errors.Wrap(err, fmt.Sprintf("delete function '%v'", m.Name))
|
return errors.Wrap(err, fmt.Sprintf("delete function '%v'", m.Name))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -100,6 +100,11 @@ func (opts *RunContainerSubCommand) complete(input cli.Input) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fnGracePeriod := input.Int64(flagkey.FnGracePeriod)
|
||||||
|
if fnGracePeriod < 0 {
|
||||||
|
console.Warn("grace period must be a non-negative integer, using default value (6 mins)")
|
||||||
|
}
|
||||||
|
|
||||||
var imageName string
|
var imageName string
|
||||||
var port int
|
var port int
|
||||||
var command, args string
|
var command, args string
|
||||||
@@ -205,7 +210,8 @@ func (opts *RunContainerSubCommand) complete(input cli.Input) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
opts.function.Spec.PodSpec = &apiv1.PodSpec{
|
opts.function.Spec.PodSpec = &apiv1.PodSpec{
|
||||||
Containers: []apiv1.Container{*container},
|
Containers: []apiv1.Container{*container},
|
||||||
|
TerminationGracePeriodSeconds: &fnGracePeriod,
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -18,8 +18,10 @@ package function
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/http/httputil"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -178,6 +180,11 @@ func doHTTPRequest(ctx context.Context, url string, headers []string, method, bo
|
|||||||
return nil, errors.Wrap(err, "error creating HTTP request")
|
return nil, errors.Wrap(err, "error creating HTTP request")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
accesstoken, ok := os.LookupEnv(util.FISSION_AUTH_TOKEN)
|
||||||
|
if ok && len(accesstoken) != 0 {
|
||||||
|
req.Header.Set("Authorization", fmt.Sprintf("Bearer %v", accesstoken))
|
||||||
|
}
|
||||||
|
|
||||||
for _, header := range headers {
|
for _, header := range headers {
|
||||||
headerKeyValue := strings.SplitN(header, ":", 2)
|
headerKeyValue := strings.SplitN(header, ":", 2)
|
||||||
if len(headerKeyValue) != 2 {
|
if len(headerKeyValue) != 2 {
|
||||||
@@ -185,12 +192,29 @@ func doHTTPRequest(ctx context.Context, url string, headers []string, method, bo
|
|||||||
}
|
}
|
||||||
req.Header.Set(headerKeyValue[0], headerKeyValue[1])
|
req.Header.Set(headerKeyValue[0], headerKeyValue[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if console.Verbosity >= 2 {
|
||||||
|
dumpReq, err := httputil.DumpRequestOut(req, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
console.Verbose(2, string(dumpReq))
|
||||||
|
}
|
||||||
|
|
||||||
hc := &http.Client{Transport: otelhttp.NewTransport(http.DefaultTransport)}
|
hc := &http.Client{Transport: otelhttp.NewTransport(http.DefaultTransport)}
|
||||||
resp, err := hc.Do(req.WithContext(ctx))
|
resp, err := hc.Do(req.WithContext(ctx))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "error executing HTTP request")
|
return nil, errors.Wrap(err, "error executing HTTP request")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if console.Verbosity >= 2 {
|
||||||
|
dumpRes, err := httputil.DumpResponse(resp, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
console.Verbose(2, string(dumpRes))
|
||||||
|
}
|
||||||
|
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ func Commands() *cobra.Command {
|
|||||||
RunE: wrapper.Wrapper(Delete),
|
RunE: wrapper.Wrapper(Delete),
|
||||||
}
|
}
|
||||||
wrapper.SetFlags(deleteCmd, flag.FlagSet{
|
wrapper.SetFlags(deleteCmd, flag.FlagSet{
|
||||||
Optional: []flag.Flag{flag.HtName, flag.HtFnFilter, flag.NamespaceTrigger},
|
Optional: []flag.Flag{flag.HtName, flag.HtFnFilter, flag.NamespaceTrigger, flag.IgnoreNotFound},
|
||||||
})
|
})
|
||||||
|
|
||||||
listCmd := &cobra.Command{
|
listCmd := &cobra.Command{
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
|
|||||||
if input.Bool(flagkey.SpecSave) {
|
if input.Bool(flagkey.SpecSave) {
|
||||||
specDir := util.GetSpecDir(input)
|
specDir := util.GetSpecDir(input)
|
||||||
specIgnore := util.GetSpecIgnore(input)
|
specIgnore := util.GetSpecIgnore(input)
|
||||||
fr, err := spec.ReadSpecs(specDir, specIgnore)
|
fr, err := spec.ReadSpecs(specDir, specIgnore, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import (
|
|||||||
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
|
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
|
||||||
"github.com/fission/fission/pkg/fission-cli/cmd"
|
"github.com/fission/fission/pkg/fission-cli/cmd"
|
||||||
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
|
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
|
||||||
|
"github.com/fission/fission/pkg/fission-cli/util"
|
||||||
"github.com/fission/fission/pkg/utils"
|
"github.com/fission/fission/pkg/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -94,6 +95,9 @@ func (opts *DeleteSubCommand) run(input cli.Input) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if errs.ErrorOrNil() != nil {
|
if errs.ErrorOrNil() != nil {
|
||||||
|
if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return errors.Wrap(errs.ErrorOrNil(), "error deleting trigger(s)")
|
return errors.Wrap(errs.ErrorOrNil(), "error deleting trigger(s)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ func Commands() *cobra.Command {
|
|||||||
}
|
}
|
||||||
wrapper.SetFlags(deleteCmd, flag.FlagSet{
|
wrapper.SetFlags(deleteCmd, flag.FlagSet{
|
||||||
Required: []flag.Flag{flag.KwFnName},
|
Required: []flag.Flag{flag.KwFnName},
|
||||||
Optional: []flag.Flag{flag.NamespaceTrigger},
|
Optional: []flag.Flag{flag.NamespaceTrigger, flag.IgnoreNotFound},
|
||||||
})
|
})
|
||||||
|
|
||||||
listCmd := &cobra.Command{
|
listCmd := &cobra.Command{
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
|
|||||||
if input.Bool(flagkey.SpecSave) {
|
if input.Bool(flagkey.SpecSave) {
|
||||||
specDir := util.GetSpecDir(input)
|
specDir := util.GetSpecDir(input)
|
||||||
specIgnore := util.GetSpecIgnore(input)
|
specIgnore := util.GetSpecIgnore(input)
|
||||||
fr, err := spec.ReadSpecs(specDir, specIgnore)
|
fr, err := spec.ReadSpecs(specDir, specIgnore, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import (
|
|||||||
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
|
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
|
||||||
"github.com/fission/fission/pkg/fission-cli/cmd"
|
"github.com/fission/fission/pkg/fission-cli/cmd"
|
||||||
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
|
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
|
||||||
|
"github.com/fission/fission/pkg/fission-cli/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DeleteSubCommand struct {
|
type DeleteSubCommand struct {
|
||||||
@@ -57,6 +58,9 @@ func (opts *DeleteSubCommand) run(input cli.Input) error {
|
|||||||
Namespace: opts.namespace,
|
Namespace: opts.namespace,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return errors.Wrap(err, "error deleting kubewatch")
|
return errors.Wrap(err, "error deleting kubewatch")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ func Commands() *cobra.Command {
|
|||||||
}
|
}
|
||||||
wrapper.SetFlags(deleteCmd, flag.FlagSet{
|
wrapper.SetFlags(deleteCmd, flag.FlagSet{
|
||||||
Required: []flag.Flag{flag.MqtName},
|
Required: []flag.Flag{flag.MqtName},
|
||||||
Optional: []flag.Flag{flag.NamespaceTrigger},
|
Optional: []flag.Flag{flag.NamespaceTrigger, flag.IgnoreNotFound},
|
||||||
})
|
})
|
||||||
|
|
||||||
listCmd := &cobra.Command{
|
listCmd := &cobra.Command{
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
|
|||||||
if input.Bool(flagkey.SpecSave) {
|
if input.Bool(flagkey.SpecSave) {
|
||||||
specDir := util.GetSpecDir(input)
|
specDir := util.GetSpecDir(input)
|
||||||
specIgnore := util.GetSpecIgnore(input)
|
specIgnore := util.GetSpecIgnore(input)
|
||||||
fr, err := spec.ReadSpecs(specDir, specIgnore)
|
fr, err := spec.ReadSpecs(specDir, specIgnore, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
||||||
}
|
}
|
||||||
@@ -146,6 +146,11 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
|
|||||||
console.Warn(fmt.Sprintf("MessageQueueTrigger '%v' references unknown Function '%v', please create it before applying spec",
|
console.Warn(fmt.Sprintf("MessageQueueTrigger '%v' references unknown Function '%v', please create it before applying spec",
|
||||||
mqtName, fnName))
|
mqtName, fnName))
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
err = util.CheckFunctionExistence(opts.Client(), []string{fnName}, fnNamespace)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
opts.trigger = &fv1.MessageQueueTrigger{
|
opts.trigger = &fv1.MessageQueueTrigger{
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import (
|
|||||||
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
|
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
|
||||||
"github.com/fission/fission/pkg/fission-cli/cmd"
|
"github.com/fission/fission/pkg/fission-cli/cmd"
|
||||||
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
|
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
|
||||||
|
"github.com/fission/fission/pkg/fission-cli/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DeleteSubCommand struct {
|
type DeleteSubCommand struct {
|
||||||
@@ -55,6 +56,9 @@ func (opts *DeleteSubCommand) complete(input cli.Input) error {
|
|||||||
func (opts *DeleteSubCommand) run(input cli.Input) error {
|
func (opts *DeleteSubCommand) run(input cli.Input) error {
|
||||||
err := opts.Client().V1().MessageQueueTrigger().Delete(opts.metadata)
|
err := opts.Client().V1().MessageQueueTrigger().Delete(opts.metadata)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return errors.Wrap(err, "error deleting message queue trigger")
|
return errors.Wrap(err, "error deleting message queue trigger")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ func Commands() *cobra.Command {
|
|||||||
RunE: wrapper.Wrapper(Delete),
|
RunE: wrapper.Wrapper(Delete),
|
||||||
}
|
}
|
||||||
wrapper.SetFlags(deleteCmd, flag.FlagSet{
|
wrapper.SetFlags(deleteCmd, flag.FlagSet{
|
||||||
Optional: []flag.Flag{flag.PkgName, flag.PkgForce, flag.PkgOrphan, flag.NamespacePackage},
|
Optional: []flag.Flag{flag.PkgName, flag.PkgForce, flag.PkgOrphan, flag.NamespacePackage, flag.IgnoreNotFound},
|
||||||
})
|
})
|
||||||
|
|
||||||
listCmd := &cobra.Command{
|
listCmd := &cobra.Command{
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ func (opts *CreateSubCommand) run(input cli.Input) error {
|
|||||||
if input.Bool(flagkey.SpecSave) {
|
if input.Bool(flagkey.SpecSave) {
|
||||||
specDir = util.GetSpecDir(input)
|
specDir = util.GetSpecDir(input)
|
||||||
specIgnore := util.GetSpecIgnore(input)
|
specIgnore := util.GetSpecIgnore(input)
|
||||||
fr, err := spec.ReadSpecs(specDir, specIgnore)
|
fr, err := spec.ReadSpecs(specDir, specIgnore, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
||||||
}
|
}
|
||||||
@@ -186,7 +186,7 @@ func CreatePackage(input cli.Input, client client.Interface, pkgName string, pkg
|
|||||||
|
|
||||||
if input.Bool(flagkey.SpecSave) {
|
if input.Bool(flagkey.SpecSave) {
|
||||||
// if a package with the same spec exists, don't create a new spec file
|
// if a package with the same spec exists, don't create a new spec file
|
||||||
fr, err := spec.ReadSpecs(util.GetSpecDir(input), util.GetSpecIgnore(input))
|
fr, err := spec.ReadSpecs(util.GetSpecDir(input), util.GetSpecIgnore(input), false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "error reading specs")
|
return nil, errors.Wrap(err, "error reading specs")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import (
|
|||||||
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
|
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
|
||||||
"github.com/fission/fission/pkg/fission-cli/cmd"
|
"github.com/fission/fission/pkg/fission-cli/cmd"
|
||||||
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
|
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
|
||||||
|
"github.com/fission/fission/pkg/fission-cli/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DeleteSubCommand struct {
|
type DeleteSubCommand struct {
|
||||||
@@ -68,6 +69,9 @@ func (opts *DeleteSubCommand) run(input cli.Input) error {
|
|||||||
Name: opts.name,
|
Name: opts.name,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return errors.Wrap(err, "find package")
|
return errors.Wrap(err, "find package")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ func CreateArchive(client client.Interface, input cli.Input, includeFiles []stri
|
|||||||
} else if input.Bool(flagkey.SpecSave) {
|
} else if input.Bool(flagkey.SpecSave) {
|
||||||
// check if this AUS exists in the specs; if so, don't create a new one
|
// check if this AUS exists in the specs; if so, don't create a new one
|
||||||
specIgnore := util.GetSpecIgnore(input)
|
specIgnore := util.GetSpecIgnore(input)
|
||||||
fr, err := spec.ReadSpecs(specDir, specIgnore)
|
fr, err := spec.ReadSpecs(specDir, specIgnore, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "error reading specs")
|
return nil, errors.Wrap(err, "error reading specs")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ func (opts *ApplySubCommand) do(input cli.Input) error {
|
|||||||
func (opts *ApplySubCommand) run(input cli.Input) error {
|
func (opts *ApplySubCommand) run(input cli.Input) error {
|
||||||
specDir := util.GetSpecDir(input)
|
specDir := util.GetSpecDir(input)
|
||||||
specIgnore := util.GetSpecIgnore(input)
|
specIgnore := util.GetSpecIgnore(input)
|
||||||
|
applyCommitLabel := input.Bool(flagkey.SpecApplyCommitLabel)
|
||||||
deleteResources := input.Bool(flagkey.SpecDelete)
|
deleteResources := input.Bool(flagkey.SpecDelete)
|
||||||
watchResources := input.Bool(flagkey.SpecWatch)
|
watchResources := input.Bool(flagkey.SpecWatch)
|
||||||
waitForBuild := input.Bool(flagkey.SpecWait)
|
waitForBuild := input.Bool(flagkey.SpecWait)
|
||||||
@@ -112,7 +112,7 @@ func (opts *ApplySubCommand) run(input cli.Input) error {
|
|||||||
|
|
||||||
for {
|
for {
|
||||||
// read all specs
|
// read all specs
|
||||||
fr, err := ReadSpecs(specDir, specIgnore)
|
fr, err := ReadSpecs(specDir, specIgnore, applyCommitLabel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "error reading specs")
|
return errors.Wrap(err, "error reading specs")
|
||||||
}
|
}
|
||||||
@@ -130,7 +130,7 @@ func (opts *ApplySubCommand) run(input cli.Input) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// make changes to the cluster based on the specs
|
// make changes to the cluster based on the specs
|
||||||
pkgMetas, as, err := applyResources(opts.Client(), specDir, fr, deleteResources)
|
pkgMetas, as, err := applyResources(opts.Client(), specDir, fr, deleteResources, input.Bool(flagkey.SpecAllowConflicts))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "error applying specs")
|
return errors.Wrap(err, "error applying specs")
|
||||||
}
|
}
|
||||||
@@ -357,7 +357,7 @@ func applyArchives(fclient client.Interface, specDir string, fr *FissionResource
|
|||||||
}
|
}
|
||||||
|
|
||||||
// applyResources applies the given set of fission resources.
|
// applyResources applies the given set of fission resources.
|
||||||
func applyResources(fclient client.Interface, specDir string, fr *FissionResources, delete bool) (map[string]metav1.ObjectMeta, map[string]ResourceApplyStatus, error) {
|
func applyResources(fclient client.Interface, specDir string, fr *FissionResources, delete bool, specAllowConflicts bool) (map[string]metav1.ObjectMeta, map[string]ResourceApplyStatus, error) {
|
||||||
|
|
||||||
applyStatus := make(map[string]ResourceApplyStatus)
|
applyStatus := make(map[string]ResourceApplyStatus)
|
||||||
|
|
||||||
@@ -367,13 +367,13 @@ func applyResources(fclient client.Interface, specDir string, fr *FissionResourc
|
|||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, ras, err := applyEnvironments(fclient, fr, delete)
|
_, ras, err := applyEnvironments(fclient, fr, delete, specAllowConflicts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrap(err, "environment apply failed")
|
return nil, nil, errors.Wrap(err, "environment apply failed")
|
||||||
}
|
}
|
||||||
applyStatus["environment"] = *ras
|
applyStatus["environment"] = *ras
|
||||||
|
|
||||||
pkgMeta, ras, err := applyPackages(fclient, fr, delete)
|
pkgMeta, ras, err := applyPackages(fclient, fr, delete, specAllowConflicts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrap(err, "package apply failed")
|
return nil, nil, errors.Wrap(err, "package apply failed")
|
||||||
}
|
}
|
||||||
@@ -402,31 +402,31 @@ func applyResources(fclient client.Interface, specDir string, fr *FissionResourc
|
|||||||
fr.Functions[i].Spec.Package.PackageRef.ResourceVersion = m.ResourceVersion
|
fr.Functions[i].Spec.Package.PackageRef.ResourceVersion = m.ResourceVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
_, ras, err = applyFunctions(fclient, fr, delete)
|
_, ras, err = applyFunctions(fclient, fr, delete, specAllowConflicts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrap(err, "function apply failed")
|
return nil, nil, errors.Wrap(err, "function apply failed")
|
||||||
}
|
}
|
||||||
applyStatus["function"] = *ras
|
applyStatus["function"] = *ras
|
||||||
|
|
||||||
_, ras, err = applyHTTPTriggers(fclient, fr, delete)
|
_, ras, err = applyHTTPTriggers(fclient, fr, delete, specAllowConflicts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrap(err, "HTTPTrigger apply failed")
|
return nil, nil, errors.Wrap(err, "HTTPTrigger apply failed")
|
||||||
}
|
}
|
||||||
applyStatus["HTTPTrigger"] = *ras
|
applyStatus["HTTPTrigger"] = *ras
|
||||||
|
|
||||||
_, ras, err = applyKubernetesWatchTriggers(fclient, fr, delete)
|
_, ras, err = applyKubernetesWatchTriggers(fclient, fr, delete, specAllowConflicts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrap(err, "KubernetesWatchTrigger apply failed")
|
return nil, nil, errors.Wrap(err, "KubernetesWatchTrigger apply failed")
|
||||||
}
|
}
|
||||||
applyStatus["KubernetesWatchTrigger"] = *ras
|
applyStatus["KubernetesWatchTrigger"] = *ras
|
||||||
|
|
||||||
_, ras, err = applyTimeTriggers(fclient, fr, delete)
|
_, ras, err = applyTimeTriggers(fclient, fr, delete, specAllowConflicts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrap(err, "TimeTrigger apply failed")
|
return nil, nil, errors.Wrap(err, "TimeTrigger apply failed")
|
||||||
}
|
}
|
||||||
applyStatus["TimeTrigger"] = *ras
|
applyStatus["TimeTrigger"] = *ras
|
||||||
|
|
||||||
_, ras, err = applyMessageQueueTriggers(fclient, fr, delete)
|
_, ras, err = applyMessageQueueTriggers(fclient, fr, delete, specAllowConflicts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrap(err, "MessageQueueTrigger apply failed")
|
return nil, nil, errors.Wrap(err, "MessageQueueTrigger apply failed")
|
||||||
}
|
}
|
||||||
@@ -576,7 +576,7 @@ func waitForPackageBuild(fclient client.Interface, pkg *fv1.Package) (*fv1.Packa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyPackages(fclient client.Interface, fr *FissionResources, delete bool) (map[string]metav1.ObjectMeta, *ResourceApplyStatus, error) {
|
func applyPackages(fclient client.Interface, fr *FissionResources, delete bool, specAllowConflicts bool) (map[string]metav1.ObjectMeta, *ResourceApplyStatus, error) {
|
||||||
// get list
|
// get list
|
||||||
allObjs, err := fclient.V1().Package().List(metav1.NamespaceAll)
|
allObjs, err := fclient.V1().Package().List(metav1.NamespaceAll)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -585,9 +585,13 @@ func applyPackages(fclient client.Interface, fr *FissionResources, delete bool)
|
|||||||
|
|
||||||
// filter
|
// filter
|
||||||
objs := make([]fv1.Package, 0)
|
objs := make([]fv1.Package, 0)
|
||||||
for _, o := range allObjs {
|
if specAllowConflicts {
|
||||||
if hasDeploymentConfig(&o.ObjectMeta, fr) {
|
objs = allObjs
|
||||||
objs = append(objs, o)
|
} else {
|
||||||
|
for _, o := range allObjs {
|
||||||
|
if hasDeploymentConfig(&o.ObjectMeta, fr) {
|
||||||
|
objs = append(objs, o)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -626,13 +630,12 @@ func applyPackages(fclient client.Interface, fr *FissionResources, delete bool)
|
|||||||
keep = true
|
keep = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if keep && existingObj.Status.BuildStatus == fv1.BuildStatusSucceeded {
|
if keep && isObjectMetaEqual(existingObj.ObjectMeta, o.ObjectMeta) && existingObj.Status.BuildStatus == fv1.BuildStatusSucceeded {
|
||||||
// nothing to do on the server
|
// nothing to do on the server
|
||||||
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
||||||
} else {
|
} else {
|
||||||
// update
|
// update
|
||||||
o.ObjectMeta.ResourceVersion = existingObj.ObjectMeta.ResourceVersion
|
o.ObjectMeta.ResourceVersion = existingObj.ObjectMeta.ResourceVersion
|
||||||
|
|
||||||
// We may be racing against the package builder to update the
|
// We may be racing against the package builder to update the
|
||||||
// package (a previous version might have been getting built). So,
|
// package (a previous version might have been getting built). So,
|
||||||
// wait for the package to have a non-running build status.
|
// wait for the package to have a non-running build status.
|
||||||
@@ -687,7 +690,7 @@ func applyPackages(fclient client.Interface, fr *FissionResources, delete bool)
|
|||||||
return metadataMap, &ras, nil
|
return metadataMap, &ras, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyFunctions(fclient client.Interface, fr *FissionResources, delete bool) (map[string]metav1.ObjectMeta, *ResourceApplyStatus, error) {
|
func applyFunctions(fclient client.Interface, fr *FissionResources, delete bool, specAllowConflicts bool) (map[string]metav1.ObjectMeta, *ResourceApplyStatus, error) {
|
||||||
// get list
|
// get list
|
||||||
allObjs, err := fclient.V1().Function().List(metav1.NamespaceAll)
|
allObjs, err := fclient.V1().Function().List(metav1.NamespaceAll)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -696,9 +699,13 @@ func applyFunctions(fclient client.Interface, fr *FissionResources, delete bool)
|
|||||||
|
|
||||||
// filter
|
// filter
|
||||||
objs := make([]fv1.Function, 0)
|
objs := make([]fv1.Function, 0)
|
||||||
for _, o := range allObjs {
|
if specAllowConflicts {
|
||||||
if hasDeploymentConfig(&o.ObjectMeta, fr) {
|
objs = allObjs
|
||||||
objs = append(objs, o)
|
} else {
|
||||||
|
for _, o := range allObjs {
|
||||||
|
if hasDeploymentConfig(&o.ObjectMeta, fr) {
|
||||||
|
objs = append(objs, o)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -726,7 +733,7 @@ func applyFunctions(fclient client.Interface, fr *FissionResources, delete bool)
|
|||||||
existingObj, ok := existent[mapKey(&o.ObjectMeta)]
|
existingObj, ok := existent[mapKey(&o.ObjectMeta)]
|
||||||
if ok {
|
if ok {
|
||||||
// ok, a resource with the same name exists, is it the same?
|
// ok, a resource with the same name exists, is it the same?
|
||||||
if reflect.DeepEqual(existingObj.Spec, o.Spec) {
|
if isObjectMetaEqual(existingObj.ObjectMeta, o.ObjectMeta) && reflect.DeepEqual(existingObj.Spec, o.Spec) {
|
||||||
// nothing to do on the server
|
// nothing to do on the server
|
||||||
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
||||||
} else {
|
} else {
|
||||||
@@ -770,7 +777,7 @@ func applyFunctions(fclient client.Interface, fr *FissionResources, delete bool)
|
|||||||
return metadataMap, &ras, nil
|
return metadataMap, &ras, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyEnvironments(fclient client.Interface, fr *FissionResources, delete bool) (map[string]metav1.ObjectMeta, *ResourceApplyStatus, error) {
|
func applyEnvironments(fclient client.Interface, fr *FissionResources, delete bool, specAllowConflicts bool) (map[string]metav1.ObjectMeta, *ResourceApplyStatus, error) {
|
||||||
// get list
|
// get list
|
||||||
allObjs, err := fclient.V1().Environment().List(metav1.NamespaceAll)
|
allObjs, err := fclient.V1().Environment().List(metav1.NamespaceAll)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -779,9 +786,13 @@ func applyEnvironments(fclient client.Interface, fr *FissionResources, delete bo
|
|||||||
|
|
||||||
// filter
|
// filter
|
||||||
objs := make([]fv1.Environment, 0)
|
objs := make([]fv1.Environment, 0)
|
||||||
for _, o := range allObjs {
|
if specAllowConflicts {
|
||||||
if hasDeploymentConfig(&o.ObjectMeta, fr) {
|
objs = allObjs
|
||||||
objs = append(objs, o)
|
} else {
|
||||||
|
for _, o := range allObjs {
|
||||||
|
if hasDeploymentConfig(&o.ObjectMeta, fr) {
|
||||||
|
objs = append(objs, o)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -809,7 +820,7 @@ func applyEnvironments(fclient client.Interface, fr *FissionResources, delete bo
|
|||||||
existingObj, ok := existent[mapKey(&o.ObjectMeta)]
|
existingObj, ok := existent[mapKey(&o.ObjectMeta)]
|
||||||
if ok {
|
if ok {
|
||||||
// ok, a resource with the same name exists, is it the same?
|
// ok, a resource with the same name exists, is it the same?
|
||||||
if reflect.DeepEqual(existingObj.Spec, o.Spec) {
|
if isObjectMetaEqual(existingObj.ObjectMeta, o.ObjectMeta) && reflect.DeepEqual(existingObj.Spec, o.Spec) {
|
||||||
// nothing to do on the server
|
// nothing to do on the server
|
||||||
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
||||||
} else {
|
} else {
|
||||||
@@ -853,7 +864,7 @@ func applyEnvironments(fclient client.Interface, fr *FissionResources, delete bo
|
|||||||
return metadataMap, &ras, nil
|
return metadataMap, &ras, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyHTTPTriggers(fclient client.Interface, fr *FissionResources, delete bool) (map[string]metav1.ObjectMeta, *ResourceApplyStatus, error) {
|
func applyHTTPTriggers(fclient client.Interface, fr *FissionResources, delete bool, specAllowConflicts bool) (map[string]metav1.ObjectMeta, *ResourceApplyStatus, error) {
|
||||||
// get list
|
// get list
|
||||||
allObjs, err := fclient.V1().HTTPTrigger().List(metav1.NamespaceAll)
|
allObjs, err := fclient.V1().HTTPTrigger().List(metav1.NamespaceAll)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -862,9 +873,13 @@ func applyHTTPTriggers(fclient client.Interface, fr *FissionResources, delete bo
|
|||||||
|
|
||||||
// filter
|
// filter
|
||||||
objs := make([]fv1.HTTPTrigger, 0)
|
objs := make([]fv1.HTTPTrigger, 0)
|
||||||
for _, o := range allObjs {
|
if specAllowConflicts {
|
||||||
if hasDeploymentConfig(&o.ObjectMeta, fr) {
|
objs = allObjs
|
||||||
objs = append(objs, o)
|
} else {
|
||||||
|
for _, o := range allObjs {
|
||||||
|
if hasDeploymentConfig(&o.ObjectMeta, fr) {
|
||||||
|
objs = append(objs, o)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -892,7 +907,7 @@ func applyHTTPTriggers(fclient client.Interface, fr *FissionResources, delete bo
|
|||||||
existingObj, ok := existent[mapKey(&o.ObjectMeta)]
|
existingObj, ok := existent[mapKey(&o.ObjectMeta)]
|
||||||
if ok {
|
if ok {
|
||||||
// ok, a resource with the same name exists, is it the same?
|
// ok, a resource with the same name exists, is it the same?
|
||||||
if reflect.DeepEqual(existingObj.Spec, o.Spec) {
|
if isObjectMetaEqual(existingObj.ObjectMeta, o.ObjectMeta) && reflect.DeepEqual(existingObj.Spec, o.Spec) {
|
||||||
// nothing to do on the server
|
// nothing to do on the server
|
||||||
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
||||||
} else {
|
} else {
|
||||||
@@ -936,7 +951,7 @@ func applyHTTPTriggers(fclient client.Interface, fr *FissionResources, delete bo
|
|||||||
return metadataMap, &ras, nil
|
return metadataMap, &ras, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyKubernetesWatchTriggers(fclient client.Interface, fr *FissionResources, delete bool) (map[string]metav1.ObjectMeta, *ResourceApplyStatus, error) {
|
func applyKubernetesWatchTriggers(fclient client.Interface, fr *FissionResources, delete bool, specAllowConflicts bool) (map[string]metav1.ObjectMeta, *ResourceApplyStatus, error) {
|
||||||
// get list
|
// get list
|
||||||
allObjs, err := fclient.V1().KubeWatcher().List(metav1.NamespaceAll)
|
allObjs, err := fclient.V1().KubeWatcher().List(metav1.NamespaceAll)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -945,9 +960,13 @@ func applyKubernetesWatchTriggers(fclient client.Interface, fr *FissionResources
|
|||||||
|
|
||||||
// filter
|
// filter
|
||||||
objs := make([]fv1.KubernetesWatchTrigger, 0)
|
objs := make([]fv1.KubernetesWatchTrigger, 0)
|
||||||
for _, o := range allObjs {
|
if specAllowConflicts {
|
||||||
if hasDeploymentConfig(&o.ObjectMeta, fr) {
|
objs = allObjs
|
||||||
objs = append(objs, o)
|
} else {
|
||||||
|
for _, o := range allObjs {
|
||||||
|
if hasDeploymentConfig(&o.ObjectMeta, fr) {
|
||||||
|
objs = append(objs, o)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -975,7 +994,7 @@ func applyKubernetesWatchTriggers(fclient client.Interface, fr *FissionResources
|
|||||||
existingObj, ok := existent[mapKey(&o.ObjectMeta)]
|
existingObj, ok := existent[mapKey(&o.ObjectMeta)]
|
||||||
if ok {
|
if ok {
|
||||||
// ok, a resource with the same name exists, is it the same?
|
// ok, a resource with the same name exists, is it the same?
|
||||||
if reflect.DeepEqual(existingObj.Spec, o.Spec) {
|
if isObjectMetaEqual(existingObj.ObjectMeta, o.ObjectMeta) && reflect.DeepEqual(existingObj.Spec, o.Spec) {
|
||||||
// nothing to do on the server
|
// nothing to do on the server
|
||||||
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
||||||
} else {
|
} else {
|
||||||
@@ -1019,7 +1038,7 @@ func applyKubernetesWatchTriggers(fclient client.Interface, fr *FissionResources
|
|||||||
return metadataMap, &ras, nil
|
return metadataMap, &ras, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyTimeTriggers(fclient client.Interface, fr *FissionResources, delete bool) (map[string]metav1.ObjectMeta, *ResourceApplyStatus, error) {
|
func applyTimeTriggers(fclient client.Interface, fr *FissionResources, delete bool, specAllowConflicts bool) (map[string]metav1.ObjectMeta, *ResourceApplyStatus, error) {
|
||||||
// get list
|
// get list
|
||||||
allObjs, err := fclient.V1().TimeTrigger().List(metav1.NamespaceAll)
|
allObjs, err := fclient.V1().TimeTrigger().List(metav1.NamespaceAll)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1028,9 +1047,13 @@ func applyTimeTriggers(fclient client.Interface, fr *FissionResources, delete bo
|
|||||||
|
|
||||||
// filter
|
// filter
|
||||||
objs := make([]fv1.TimeTrigger, 0)
|
objs := make([]fv1.TimeTrigger, 0)
|
||||||
for _, o := range allObjs {
|
if specAllowConflicts {
|
||||||
if hasDeploymentConfig(&o.ObjectMeta, fr) {
|
objs = allObjs
|
||||||
objs = append(objs, o)
|
} else {
|
||||||
|
for _, o := range allObjs {
|
||||||
|
if hasDeploymentConfig(&o.ObjectMeta, fr) {
|
||||||
|
objs = append(objs, o)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1058,7 +1081,7 @@ func applyTimeTriggers(fclient client.Interface, fr *FissionResources, delete bo
|
|||||||
existingObj, ok := existent[mapKey(&o.ObjectMeta)]
|
existingObj, ok := existent[mapKey(&o.ObjectMeta)]
|
||||||
if ok {
|
if ok {
|
||||||
// ok, a resource with the same name exists, is it the same?
|
// ok, a resource with the same name exists, is it the same?
|
||||||
if reflect.DeepEqual(existingObj.Spec, o.Spec) {
|
if isObjectMetaEqual(existingObj.ObjectMeta, o.ObjectMeta) && reflect.DeepEqual(existingObj.Spec, o.Spec) {
|
||||||
// nothing to do on the server
|
// nothing to do on the server
|
||||||
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
||||||
} else {
|
} else {
|
||||||
@@ -1102,7 +1125,7 @@ func applyTimeTriggers(fclient client.Interface, fr *FissionResources, delete bo
|
|||||||
return metadataMap, &ras, nil
|
return metadataMap, &ras, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyMessageQueueTriggers(fclient client.Interface, fr *FissionResources, delete bool) (map[string]metav1.ObjectMeta, *ResourceApplyStatus, error) {
|
func applyMessageQueueTriggers(fclient client.Interface, fr *FissionResources, delete bool, specAllowConflicts bool) (map[string]metav1.ObjectMeta, *ResourceApplyStatus, error) {
|
||||||
// get list
|
// get list
|
||||||
allObjs, err := fclient.V1().MessageQueueTrigger().List("", metav1.NamespaceAll)
|
allObjs, err := fclient.V1().MessageQueueTrigger().List("", metav1.NamespaceAll)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1111,9 +1134,13 @@ func applyMessageQueueTriggers(fclient client.Interface, fr *FissionResources, d
|
|||||||
|
|
||||||
// filter
|
// filter
|
||||||
objs := make([]fv1.MessageQueueTrigger, 0)
|
objs := make([]fv1.MessageQueueTrigger, 0)
|
||||||
for _, o := range allObjs {
|
if specAllowConflicts {
|
||||||
if hasDeploymentConfig(&o.ObjectMeta, fr) {
|
objs = allObjs
|
||||||
objs = append(objs, o)
|
} else {
|
||||||
|
for _, o := range allObjs {
|
||||||
|
if hasDeploymentConfig(&o.ObjectMeta, fr) {
|
||||||
|
objs = append(objs, o)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1141,7 +1168,7 @@ func applyMessageQueueTriggers(fclient client.Interface, fr *FissionResources, d
|
|||||||
existingObj, ok := existent[mapKey(&o.ObjectMeta)]
|
existingObj, ok := existent[mapKey(&o.ObjectMeta)]
|
||||||
if ok {
|
if ok {
|
||||||
// ok, a resource with the same name exists, is it the same?
|
// ok, a resource with the same name exists, is it the same?
|
||||||
if reflect.DeepEqual(existingObj.Spec, o.Spec) {
|
if isObjectMetaEqual(existingObj.ObjectMeta, o.ObjectMeta) && reflect.DeepEqual(existingObj.Spec, o.Spec) {
|
||||||
// nothing to do on the server
|
// nothing to do on the server
|
||||||
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
||||||
} else {
|
} else {
|
||||||
@@ -1184,3 +1211,7 @@ func applyMessageQueueTriggers(fclient client.Interface, fr *FissionResources, d
|
|||||||
|
|
||||||
return metadataMap, &ras, nil
|
return metadataMap, &ras, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isObjectMetaEqual(existingObj, newObj metav1.ObjectMeta) bool {
|
||||||
|
return reflect.DeepEqual(existingObj.Labels, newObj.Labels) && reflect.DeepEqual(existingObj.Annotations, newObj.Annotations)
|
||||||
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ func Commands() *cobra.Command {
|
|||||||
RunE: wrapper.Wrapper(Validate),
|
RunE: wrapper.Wrapper(Validate),
|
||||||
}
|
}
|
||||||
wrapper.SetFlags(validateCmd, flag.FlagSet{
|
wrapper.SetFlags(validateCmd, flag.FlagSet{
|
||||||
Optional: []flag.Flag{flag.SpecDir, flag.SpecIgnore},
|
Optional: []flag.Flag{flag.SpecDir, flag.SpecIgnore, flag.SpecAllowConflicts},
|
||||||
})
|
})
|
||||||
|
|
||||||
applyCmd := &cobra.Command{
|
applyCmd := &cobra.Command{
|
||||||
@@ -48,7 +48,7 @@ func Commands() *cobra.Command {
|
|||||||
RunE: wrapper.Wrapper(Apply),
|
RunE: wrapper.Wrapper(Apply),
|
||||||
}
|
}
|
||||||
wrapper.SetFlags(applyCmd, flag.FlagSet{
|
wrapper.SetFlags(applyCmd, flag.FlagSet{
|
||||||
Optional: []flag.Flag{flag.SpecDir, flag.SpecIgnore, flag.SpecDelete, flag.SpecWait, flag.SpecWatch, flag.SpecValidation},
|
Optional: []flag.Flag{flag.SpecDir, flag.SpecIgnore, flag.SpecDelete, flag.SpecWait, flag.SpecWatch, flag.SpecValidation, flag.SpecApplyCommitLabel, flag.SpecAllowConflicts},
|
||||||
})
|
})
|
||||||
|
|
||||||
destroyCmd := &cobra.Command{
|
destroyCmd := &cobra.Command{
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package spec
|
|||||||
import (
|
import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"github.com/fission/fission/pkg/controller/client"
|
||||||
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
|
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
|
||||||
"github.com/fission/fission/pkg/fission-cli/cmd"
|
"github.com/fission/fission/pkg/fission-cli/cmd"
|
||||||
"github.com/fission/fission/pkg/fission-cli/util"
|
"github.com/fission/fission/pkg/fission-cli/util"
|
||||||
@@ -43,7 +44,7 @@ func (opts *DestroySubCommand) run(input cli.Input) error {
|
|||||||
specIgnore := util.GetSpecIgnore(input)
|
specIgnore := util.GetSpecIgnore(input)
|
||||||
|
|
||||||
// read everything
|
// read everything
|
||||||
fr, err := ReadSpecs(specDir, specIgnore)
|
fr, err := ReadSpecs(specDir, specIgnore, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "error reading specs")
|
return errors.Wrap(err, "error reading specs")
|
||||||
}
|
}
|
||||||
@@ -53,10 +54,52 @@ func (opts *DestroySubCommand) run(input cli.Input) error {
|
|||||||
emptyFr.DeploymentConfig = fr.DeploymentConfig
|
emptyFr.DeploymentConfig = fr.DeploymentConfig
|
||||||
|
|
||||||
// "apply" the empty state
|
// "apply" the empty state
|
||||||
_, _, err = applyResources(opts.Client(), specDir, &emptyFr, true)
|
err = deleteResources(opts.Client(), &emptyFr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "error deleting resources")
|
return errors.Wrap(err, "error deleting resources")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func deleteResources(fclient client.Interface, fr *FissionResources) error {
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
|
_, _, err = applyHTTPTriggers(fclient, fr, true, false)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "HTTPTrigger delete failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err = applyKubernetesWatchTriggers(fclient, fr, true, false)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "KubernetesWatchTrigger delete failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err = applyTimeTriggers(fclient, fr, true, false)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "TimeTrigger delete failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err = applyMessageQueueTriggers(fclient, fr, true, false)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "MessageQueueTrigger delete failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err = applyFunctions(fclient, fr, true, false)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "function delete failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err = applyPackages(fclient, fr, true, false)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "package delete failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err = applyEnvironments(fclient, fr, true, false)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "environment delete failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ func (opts *ListSubCommand) run(input cli.Input) error {
|
|||||||
// get specdir, specignore and read the deployID
|
// get specdir, specignore and read the deployID
|
||||||
specDir := util.GetSpecDir(input)
|
specDir := util.GetSpecDir(input)
|
||||||
specIgnore := util.GetSpecIgnore(input)
|
specIgnore := util.GetSpecIgnore(input)
|
||||||
fr, err := ReadSpecs(specDir, specIgnore)
|
fr, err := ReadSpecs(specDir, specIgnore, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "error reading specs")
|
return errors.Wrap(err, "error reading specs")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ func SpecSave(resource interface{}, specFile string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fr, err := ReadSpecs(specDir, util.SPEC_IGNORE_FILE)
|
fr, err := ReadSpecs(specDir, util.SPEC_IGNORE_FILE, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
||||||
}
|
}
|
||||||
@@ -526,9 +526,19 @@ func (fr *FissionResources) trackSourceMap(kind string, newobj *metav1.ObjectMet
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply commit label to the object metadata
|
||||||
|
func applyCommitLabel(commitLabelVal string, m *metav1.ObjectMeta) {
|
||||||
|
if len(commitLabelVal) != 0 {
|
||||||
|
if m.Labels == nil {
|
||||||
|
m.Labels = make(map[string]string)
|
||||||
|
}
|
||||||
|
m.Labels[util.COMMIT_LABEL] = commitLabelVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ParseYaml takes one yaml document, figures out its type, parses it, and puts it in
|
// ParseYaml takes one yaml document, figures out its type, parses it, and puts it in
|
||||||
// the right list in the given fission resources set.
|
// the right list in the given fission resources set.
|
||||||
func (fr *FissionResources) ParseYaml(b []byte, loc *Location) error {
|
func (fr *FissionResources) ParseYaml(b []byte, loc *Location, commitLabelVal string) error {
|
||||||
var m *metav1.ObjectMeta
|
var m *metav1.ObjectMeta
|
||||||
|
|
||||||
// Figure out the object type by unmarshaling into the TypeMeta struct; then
|
// Figure out the object type by unmarshaling into the TypeMeta struct; then
|
||||||
@@ -547,6 +557,7 @@ func (fr *FissionResources) ParseYaml(b []byte, loc *Location) error {
|
|||||||
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
||||||
}
|
}
|
||||||
m = &v.ObjectMeta
|
m = &v.ObjectMeta
|
||||||
|
applyCommitLabel(commitLabelVal, m)
|
||||||
fr.Packages = append(fr.Packages, v)
|
fr.Packages = append(fr.Packages, v)
|
||||||
case "Function":
|
case "Function":
|
||||||
var v fv1.Function
|
var v fv1.Function
|
||||||
@@ -555,6 +566,7 @@ func (fr *FissionResources) ParseYaml(b []byte, loc *Location) error {
|
|||||||
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
||||||
}
|
}
|
||||||
m = &v.ObjectMeta
|
m = &v.ObjectMeta
|
||||||
|
applyCommitLabel(commitLabelVal, m)
|
||||||
fr.Functions = append(fr.Functions, v)
|
fr.Functions = append(fr.Functions, v)
|
||||||
case "Environment":
|
case "Environment":
|
||||||
var v fv1.Environment
|
var v fv1.Environment
|
||||||
@@ -563,6 +575,7 @@ func (fr *FissionResources) ParseYaml(b []byte, loc *Location) error {
|
|||||||
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
||||||
}
|
}
|
||||||
m = &v.ObjectMeta
|
m = &v.ObjectMeta
|
||||||
|
applyCommitLabel(commitLabelVal, m)
|
||||||
fr.Environments = append(fr.Environments, v)
|
fr.Environments = append(fr.Environments, v)
|
||||||
case "HTTPTrigger":
|
case "HTTPTrigger":
|
||||||
var v fv1.HTTPTrigger
|
var v fv1.HTTPTrigger
|
||||||
@@ -570,8 +583,8 @@ func (fr *FissionResources) ParseYaml(b []byte, loc *Location) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
||||||
}
|
}
|
||||||
|
|
||||||
m = &v.ObjectMeta
|
m = &v.ObjectMeta
|
||||||
|
applyCommitLabel(commitLabelVal, m)
|
||||||
fr.HttpTriggers = append(fr.HttpTriggers, v)
|
fr.HttpTriggers = append(fr.HttpTriggers, v)
|
||||||
case "KubernetesWatchTrigger":
|
case "KubernetesWatchTrigger":
|
||||||
var v fv1.KubernetesWatchTrigger
|
var v fv1.KubernetesWatchTrigger
|
||||||
@@ -580,6 +593,7 @@ func (fr *FissionResources) ParseYaml(b []byte, loc *Location) error {
|
|||||||
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
||||||
}
|
}
|
||||||
m = &v.ObjectMeta
|
m = &v.ObjectMeta
|
||||||
|
applyCommitLabel(commitLabelVal, m)
|
||||||
fr.KubernetesWatchTriggers = append(fr.KubernetesWatchTriggers, v)
|
fr.KubernetesWatchTriggers = append(fr.KubernetesWatchTriggers, v)
|
||||||
case "TimeTrigger":
|
case "TimeTrigger":
|
||||||
var v fv1.TimeTrigger
|
var v fv1.TimeTrigger
|
||||||
@@ -588,6 +602,7 @@ func (fr *FissionResources) ParseYaml(b []byte, loc *Location) error {
|
|||||||
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
||||||
}
|
}
|
||||||
m = &v.ObjectMeta
|
m = &v.ObjectMeta
|
||||||
|
applyCommitLabel(commitLabelVal, m)
|
||||||
fr.TimeTriggers = append(fr.TimeTriggers, v)
|
fr.TimeTriggers = append(fr.TimeTriggers, v)
|
||||||
case "MessageQueueTrigger":
|
case "MessageQueueTrigger":
|
||||||
var v fv1.MessageQueueTrigger
|
var v fv1.MessageQueueTrigger
|
||||||
@@ -596,6 +611,7 @@ func (fr *FissionResources) ParseYaml(b []byte, loc *Location) error {
|
|||||||
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
||||||
}
|
}
|
||||||
m = &v.ObjectMeta
|
m = &v.ObjectMeta
|
||||||
|
applyCommitLabel(commitLabelVal, m)
|
||||||
fr.MessageQueueTriggers = append(fr.MessageQueueTriggers, v)
|
fr.MessageQueueTriggers = append(fr.MessageQueueTriggers, v)
|
||||||
|
|
||||||
// The following are not CRDs
|
// The following are not CRDs
|
||||||
@@ -606,6 +622,7 @@ func (fr *FissionResources) ParseYaml(b []byte, loc *Location) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
||||||
}
|
}
|
||||||
|
|
||||||
fr.DeploymentConfig = v
|
fr.DeploymentConfig = v
|
||||||
case "ArchiveUploadSpec":
|
case "ArchiveUploadSpec":
|
||||||
var v types.ArchiveUploadSpec
|
var v types.ArchiveUploadSpec
|
||||||
@@ -613,10 +630,12 @@ func (fr *FissionResources) ParseYaml(b []byte, loc *Location) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
||||||
}
|
}
|
||||||
|
|
||||||
m = &metav1.ObjectMeta{
|
m = &metav1.ObjectMeta{
|
||||||
Name: v.Name,
|
Name: v.Name,
|
||||||
Namespace: "",
|
Namespace: "",
|
||||||
}
|
}
|
||||||
|
applyCommitLabel(commitLabelVal, m)
|
||||||
fr.ArchiveUploadSpecs = append(fr.ArchiveUploadSpecs, v)
|
fr.ArchiveUploadSpecs = append(fr.ArchiveUploadSpecs, v)
|
||||||
default:
|
default:
|
||||||
// no need to error out just because there's some extra files around;
|
// no need to error out just because there's some extra files around;
|
||||||
|
|||||||
@@ -31,8 +31,10 @@ import (
|
|||||||
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
|
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
|
||||||
"github.com/fission/fission/pkg/fission-cli/cmd"
|
"github.com/fission/fission/pkg/fission-cli/cmd"
|
||||||
"github.com/fission/fission/pkg/fission-cli/console"
|
"github.com/fission/fission/pkg/fission-cli/console"
|
||||||
|
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
|
||||||
"github.com/fission/fission/pkg/fission-cli/util"
|
"github.com/fission/fission/pkg/fission-cli/util"
|
||||||
"github.com/fission/fission/pkg/utils"
|
"github.com/fission/fission/pkg/utils"
|
||||||
|
"github.com/fission/fission/pkg/utils/gitrepo"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ValidateSubCommand struct {
|
type ValidateSubCommand struct {
|
||||||
@@ -54,7 +56,7 @@ func (opts *ValidateSubCommand) run(input cli.Input) error {
|
|||||||
// this will error on parse errors and on duplicates
|
// this will error on parse errors and on duplicates
|
||||||
specDir := util.GetSpecDir(input)
|
specDir := util.GetSpecDir(input)
|
||||||
specIgnore := util.GetSpecIgnore(input)
|
specIgnore := util.GetSpecIgnore(input)
|
||||||
fr, err := ReadSpecs(specDir, specIgnore)
|
fr, err := ReadSpecs(specDir, specIgnore, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "error reading specs")
|
return errors.Wrap(err, "error reading specs")
|
||||||
}
|
}
|
||||||
@@ -70,7 +72,7 @@ func (opts *ValidateSubCommand) run(input cli.Input) error {
|
|||||||
return errors.Wrap(err, "error validating specs")
|
return errors.Wrap(err, "error validating specs")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = resourceConflictCheck(opts.Client(), fr)
|
err = resourceConflictCheck(opts.Client(), fr, input.Bool(flagkey.SpecAllowConflicts))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "name conflict error")
|
return errors.Wrap(err, "name conflict error")
|
||||||
}
|
}
|
||||||
@@ -88,7 +90,7 @@ func (opts *ValidateSubCommand) run(input cli.Input) error {
|
|||||||
// the same name is already present in the same cluster namespace.
|
// the same name is already present in the same cluster namespace.
|
||||||
// If a same name resource exists in the same namespace, a name
|
// If a same name resource exists in the same namespace, a name
|
||||||
// conflict error will be returned.
|
// conflict error will be returned.
|
||||||
func resourceConflictCheck(c client.Interface, fr *FissionResources) error {
|
func resourceConflictCheck(c client.Interface, fr *FissionResources, specAllowConflicts bool) error {
|
||||||
deployUID := fr.DeploymentConfig.UID
|
deployUID := fr.DeploymentConfig.UID
|
||||||
result := utils.MultiErrorWithFormat()
|
result := utils.MultiErrorWithFormat()
|
||||||
|
|
||||||
@@ -98,7 +100,7 @@ func resourceConflictCheck(c client.Interface, fr *FissionResources) error {
|
|||||||
}
|
}
|
||||||
for _, sObj := range fr.Functions {
|
for _, sObj := range fr.Functions {
|
||||||
for _, cObj := range fnList {
|
for _, cObj := range fnList {
|
||||||
if err := isResourceConflicts(deployUID, &sObj, &cObj); err != nil {
|
if err := isResourceConflicts(deployUID, &sObj, &cObj, specAllowConflicts); err != nil {
|
||||||
result = multierror.Append(result, err)
|
result = multierror.Append(result, err)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -111,7 +113,7 @@ func resourceConflictCheck(c client.Interface, fr *FissionResources) error {
|
|||||||
}
|
}
|
||||||
for _, sObj := range fr.Environments {
|
for _, sObj := range fr.Environments {
|
||||||
for _, cObj := range envList {
|
for _, cObj := range envList {
|
||||||
if err := isResourceConflicts(deployUID, &sObj, &cObj); err != nil {
|
if err := isResourceConflicts(deployUID, &sObj, &cObj, specAllowConflicts); err != nil {
|
||||||
result = multierror.Append(result, err)
|
result = multierror.Append(result, err)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -124,7 +126,7 @@ func resourceConflictCheck(c client.Interface, fr *FissionResources) error {
|
|||||||
}
|
}
|
||||||
for _, sObj := range fr.Packages {
|
for _, sObj := range fr.Packages {
|
||||||
for _, cObj := range pkgList {
|
for _, cObj := range pkgList {
|
||||||
if err := isResourceConflicts(deployUID, &sObj, &cObj); err != nil {
|
if err := isResourceConflicts(deployUID, &sObj, &cObj, specAllowConflicts); err != nil {
|
||||||
result = multierror.Append(result, err)
|
result = multierror.Append(result, err)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -137,7 +139,7 @@ func resourceConflictCheck(c client.Interface, fr *FissionResources) error {
|
|||||||
}
|
}
|
||||||
for _, sObj := range fr.HttpTriggers {
|
for _, sObj := range fr.HttpTriggers {
|
||||||
for _, cObj := range httptriggerList {
|
for _, cObj := range httptriggerList {
|
||||||
if err := isResourceConflicts(deployUID, &sObj, &cObj); err != nil {
|
if err := isResourceConflicts(deployUID, &sObj, &cObj, specAllowConflicts); err != nil {
|
||||||
result = multierror.Append(result, err)
|
result = multierror.Append(result, err)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -150,7 +152,7 @@ func resourceConflictCheck(c client.Interface, fr *FissionResources) error {
|
|||||||
}
|
}
|
||||||
for _, sObj := range fr.MessageQueueTriggers {
|
for _, sObj := range fr.MessageQueueTriggers {
|
||||||
for _, cObj := range mqtriggerList {
|
for _, cObj := range mqtriggerList {
|
||||||
if err := isResourceConflicts(deployUID, &sObj, &cObj); err != nil {
|
if err := isResourceConflicts(deployUID, &sObj, &cObj, specAllowConflicts); err != nil {
|
||||||
result = multierror.Append(result, err)
|
result = multierror.Append(result, err)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -163,7 +165,7 @@ func resourceConflictCheck(c client.Interface, fr *FissionResources) error {
|
|||||||
}
|
}
|
||||||
for _, sObj := range fr.TimeTriggers {
|
for _, sObj := range fr.TimeTriggers {
|
||||||
for _, cObj := range timetriggerList {
|
for _, cObj := range timetriggerList {
|
||||||
if err := isResourceConflicts(deployUID, &sObj, &cObj); err != nil {
|
if err := isResourceConflicts(deployUID, &sObj, &cObj, specAllowConflicts); err != nil {
|
||||||
result = multierror.Append(result, err)
|
result = multierror.Append(result, err)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -176,7 +178,7 @@ func resourceConflictCheck(c client.Interface, fr *FissionResources) error {
|
|||||||
}
|
}
|
||||||
for _, sObj := range fr.KubernetesWatchTriggers {
|
for _, sObj := range fr.KubernetesWatchTriggers {
|
||||||
for _, cObj := range kubewatchtriggerList {
|
for _, cObj := range kubewatchtriggerList {
|
||||||
if err := isResourceConflicts(deployUID, &sObj, &cObj); err != nil {
|
if err := isResourceConflicts(deployUID, &sObj, &cObj, specAllowConflicts); err != nil {
|
||||||
result = multierror.Append(result, err)
|
result = multierror.Append(result, err)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -186,10 +188,13 @@ func resourceConflictCheck(c client.Interface, fr *FissionResources) error {
|
|||||||
return result.ErrorOrNil()
|
return result.ErrorOrNil()
|
||||||
}
|
}
|
||||||
|
|
||||||
func isResourceConflicts(deployUID string, specObj fv1.MetadataAccessor, clusterObj fv1.MetadataAccessor) error {
|
func isResourceConflicts(deployUID string, specObj fv1.MetadataAccessor, clusterObj fv1.MetadataAccessor, specAllowConflicts bool) error {
|
||||||
if specObj.GetObjectMeta().GetName() == clusterObj.GetObjectMeta().GetName() &&
|
if specObj.GetObjectMeta().GetName() == clusterObj.GetObjectMeta().GetName() &&
|
||||||
specObj.GetObjectMeta().GetNamespace() == clusterObj.GetObjectMeta().GetNamespace() &&
|
specObj.GetObjectMeta().GetNamespace() == clusterObj.GetObjectMeta().GetNamespace() &&
|
||||||
deployUID != clusterObj.GetObjectMeta().GetAnnotations()[FISSION_DEPLOYMENT_UID_KEY] {
|
deployUID != clusterObj.GetObjectMeta().GetAnnotations()[FISSION_DEPLOYMENT_UID_KEY] {
|
||||||
|
if specAllowConflicts {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return fmt.Errorf("%v: '%v/%v' with different deploy uid already exists",
|
return fmt.Errorf("%v: '%v/%v' with different deploy uid already exists",
|
||||||
clusterObj.GetObjectKind().GroupVersionKind().Kind, clusterObj.GetObjectMeta().GetName(), clusterObj.GetObjectMeta().GetNamespace())
|
clusterObj.GetObjectKind().GroupVersionKind().Kind, clusterObj.GetObjectMeta().GetName(), clusterObj.GetObjectMeta().GetNamespace())
|
||||||
}
|
}
|
||||||
@@ -198,7 +203,7 @@ func isResourceConflicts(deployUID string, specObj fv1.MetadataAccessor, cluster
|
|||||||
|
|
||||||
// ReadSpecs reads all specs in the specified directory and returns a parsed set of
|
// ReadSpecs reads all specs in the specified directory and returns a parsed set of
|
||||||
// fission resources.
|
// fission resources.
|
||||||
func ReadSpecs(specDir, specIgnore string) (*FissionResources, error) {
|
func ReadSpecs(specDir, specIgnore string, applyCommitLabel bool) (*FissionResources, error) {
|
||||||
|
|
||||||
// make sure spec directory exists before continue
|
// make sure spec directory exists before continue
|
||||||
if _, err := os.Stat(specDir); os.IsNotExist(err) {
|
if _, err := os.Stat(specDir); os.IsNotExist(err) {
|
||||||
@@ -225,6 +230,21 @@ func ReadSpecs(specDir, specIgnore string) (*FissionResources, error) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get absolute path of specdir
|
||||||
|
if !filepath.IsAbs(specDir) {
|
||||||
|
cwd, err := filepath.Abs("./")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
specDir = filepath.Join(cwd, specDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
var gr *gitrepo.GitRepo
|
||||||
|
// check if applyCommitLabel flag is true
|
||||||
|
if applyCommitLabel {
|
||||||
|
gr = gitrepo.NewGitRepo(specDir)
|
||||||
|
}
|
||||||
|
|
||||||
var result *multierror.Error
|
var result *multierror.Error
|
||||||
|
|
||||||
// Users can organize the specdir into subdirs if they want to.
|
// Users can organize the specdir into subdirs if they want to.
|
||||||
@@ -239,16 +259,24 @@ func ReadSpecs(specDir, specIgnore string) (*FissionResources, error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if file matches any path in .specignore file
|
||||||
if ignoreParser.MatchesPath(path) {
|
if ignoreParser.MatchesPath(path) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var fileCommitLabelVal string
|
||||||
|
// check if applyCommitLabel is true and specdir is tracked by git repo
|
||||||
|
if applyCommitLabel {
|
||||||
|
fileCommitLabelVal, _ = gr.GetFileCommitLabel(path)
|
||||||
|
}
|
||||||
|
|
||||||
// read
|
// read
|
||||||
b, err := os.ReadFile(path)
|
b, err := os.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
result = multierror.Append(result, err)
|
result = multierror.Append(result, err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle the case where there are multiple YAML docs per file. go-yaml
|
// handle the case where there are multiple YAML docs per file. go-yaml
|
||||||
// doesn't support this directly, yet.
|
// doesn't support this directly, yet.
|
||||||
docs := bytes.Split(b, []byte("\n---"))
|
docs := bytes.Split(b, []byte("\n---"))
|
||||||
@@ -260,7 +288,7 @@ func ReadSpecs(specDir, specIgnore string) (*FissionResources, error) {
|
|||||||
err = fr.ParseYaml(d, &Location{
|
err = fr.ParseYaml(d, &Location{
|
||||||
Path: path,
|
Path: path,
|
||||||
Line: lines,
|
Line: lines,
|
||||||
})
|
}, fileCommitLabelVal)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// collect all errors so user can fix them all
|
// collect all errors so user can fix them all
|
||||||
result = multierror.Append(result, err)
|
result = multierror.Append(result, err)
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ func Commands() *cobra.Command {
|
|||||||
}
|
}
|
||||||
wrapper.SetFlags(deleteCmd, flag.FlagSet{
|
wrapper.SetFlags(deleteCmd, flag.FlagSet{
|
||||||
Required: []flag.Flag{flag.TtName},
|
Required: []flag.Flag{flag.TtName},
|
||||||
Optional: []flag.Flag{flag.NamespaceTrigger},
|
Optional: []flag.Flag{flag.NamespaceTrigger, flag.IgnoreNotFound},
|
||||||
})
|
})
|
||||||
|
|
||||||
listCmd := &cobra.Command{
|
listCmd := &cobra.Command{
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
|
|||||||
if input.Bool(flagkey.SpecSave) {
|
if input.Bool(flagkey.SpecSave) {
|
||||||
specDir := util.GetSpecDir(input)
|
specDir := util.GetSpecDir(input)
|
||||||
specIgnore := util.GetSpecIgnore(input)
|
specIgnore := util.GetSpecIgnore(input)
|
||||||
fr, err := spec.ReadSpecs(specDir, specIgnore)
|
fr, err := spec.ReadSpecs(specDir, specIgnore, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import (
|
|||||||
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
|
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
|
||||||
"github.com/fission/fission/pkg/fission-cli/cmd"
|
"github.com/fission/fission/pkg/fission-cli/cmd"
|
||||||
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
|
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
|
||||||
|
"github.com/fission/fission/pkg/fission-cli/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DeleteSubCommand struct {
|
type DeleteSubCommand struct {
|
||||||
@@ -43,6 +44,9 @@ func (opts *DeleteSubCommand) do(input cli.Input) error {
|
|||||||
|
|
||||||
err := opts.Client().V1().TimeTrigger().Delete(m)
|
err := opts.Client().V1().TimeTrigger().Delete(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return errors.Wrap(err, "error deleting trigger")
|
return errors.Wrap(err, "error deleting trigger")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2022 The Fission Authors.
|
||||||
|
|
||||||
|
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://www.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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package token
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
wrapper "github.com/fission/fission/pkg/fission-cli/cliwrapper/driver/cobra"
|
||||||
|
"github.com/fission/fission/pkg/fission-cli/flag"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Commands() *cobra.Command {
|
||||||
|
createCmd := &cobra.Command{
|
||||||
|
Use: "create",
|
||||||
|
Short: "Create a JWT token for function invocation",
|
||||||
|
RunE: wrapper.Wrapper(Create),
|
||||||
|
}
|
||||||
|
wrapper.SetFlags(createCmd, flag.FlagSet{
|
||||||
|
Required: []flag.Flag{flag.TokUsername, flag.TokPassword},
|
||||||
|
Optional: []flag.Flag{flag.TokAuthURI},
|
||||||
|
})
|
||||||
|
|
||||||
|
command := &cobra.Command{
|
||||||
|
Use: "token",
|
||||||
|
Short: "Create a JWT token for function invocation",
|
||||||
|
}
|
||||||
|
|
||||||
|
command.AddCommand(createCmd)
|
||||||
|
|
||||||
|
return command
|
||||||
|
}
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2022 The Fission Authors.
|
||||||
|
|
||||||
|
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://www.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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package token
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
fv1 "github.com/fission/fission/pkg/apis/core/v1"
|
||||||
|
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
|
||||||
|
"github.com/fission/fission/pkg/fission-cli/cmd"
|
||||||
|
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
|
||||||
|
"github.com/fission/fission/pkg/fission-cli/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CreateSubCommand struct {
|
||||||
|
cmd.CommandActioner
|
||||||
|
}
|
||||||
|
|
||||||
|
func Create(input cli.Input) error {
|
||||||
|
return (&CreateSubCommand{}).do(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (opts *CreateSubCommand) do(input cli.Input) error {
|
||||||
|
return opts.run(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (opts *CreateSubCommand) run(input cli.Input) error {
|
||||||
|
|
||||||
|
lb := &fv1.AuthLogin{}
|
||||||
|
|
||||||
|
username := input.String(flagkey.TokUsername)
|
||||||
|
if len(username) != 0 {
|
||||||
|
lb.Username = username
|
||||||
|
}
|
||||||
|
|
||||||
|
password := input.String(flagkey.TokPassword)
|
||||||
|
if len(password) != 0 {
|
||||||
|
lb.Password = password
|
||||||
|
}
|
||||||
|
|
||||||
|
values := map[string]string{"username": username, "password": password}
|
||||||
|
|
||||||
|
jsonValue, _ := json.Marshal(values)
|
||||||
|
|
||||||
|
kubeContext := input.String(flagkey.KubeContext)
|
||||||
|
// Portforward to the fission router
|
||||||
|
localRouterPort, err := util.SetupPortForward(util.GetFissionNamespace(), "application=fission-router", kubeContext)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
authURI, _ := os.LookupEnv("FISSION_AUTH_URI")
|
||||||
|
|
||||||
|
if input.IsSet(flagkey.TokAuthURI) {
|
||||||
|
authURI = input.String(flagkey.TokAuthURI)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(authURI) == 0 {
|
||||||
|
authURI = util.FISSION_AUTH_URI
|
||||||
|
}
|
||||||
|
|
||||||
|
relativeURL, _ := url.Parse(authURI)
|
||||||
|
serverURL, _ := url.Parse("http://127.0.0.1:" + localRouterPort)
|
||||||
|
authAuthenticatorUrl := serverURL.ResolveReference(relativeURL)
|
||||||
|
|
||||||
|
resp, err := http.Post(authAuthenticatorUrl.String(), "application/json", bytes.NewBuffer(jsonValue))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "error creating token")
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.StatusCode == http.StatusCreated {
|
||||||
|
var rat fv1.RouterAuthToken
|
||||||
|
err = json.Unmarshal(body, &rat)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println(rat.AccessToken)
|
||||||
|
} else if resp.StatusCode == http.StatusNotFound {
|
||||||
|
fmt.Printf("%s. Please check if authentication is enabled and correct auth URI is mentioned via --authuri or FISSION_AUTH_URI.\n", resp.Status)
|
||||||
|
} else {
|
||||||
|
fmt.Println(resp.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -74,8 +74,12 @@ var (
|
|||||||
|
|
||||||
ClientOnly = Flag{Type: Bool, Name: flagkey.ClientOnly, Usage: "If set, the CLI won't connect to remote server"}
|
ClientOnly = Flag{Type: Bool, Name: flagkey.ClientOnly, Usage: "If set, the CLI won't connect to remote server"}
|
||||||
|
|
||||||
|
PreCheckOnly = Flag{Type: Bool, Name: flagkey.PreCheckOnly, Usage: "Only run pre-installation checks, to determine if fission can be installed"}
|
||||||
|
|
||||||
KubeContext = Flag{Type: String, Name: flagkey.KubeContext, Usage: "Kubernetes context to be used for the execution of Fission commands", DefaultValue: ""}
|
KubeContext = Flag{Type: String, Name: flagkey.KubeContext, Usage: "Kubernetes context to be used for the execution of Fission commands", DefaultValue: ""}
|
||||||
|
|
||||||
|
IgnoreNotFound = Flag{Type: Bool, Name: flagkey.IgnoreNotFound, Usage: "Treat \"resource not found\" as a successful delete.", DefaultValue: false}
|
||||||
|
|
||||||
Labels = Flag{Type: String, Name: flagkey.Labels, Usage: "Comma separated labels to apply to the function. E.g. --labels=\"environment=dev,application=analytics\""}
|
Labels = Flag{Type: String, Name: flagkey.Labels, Usage: "Comma separated labels to apply to the function. E.g. --labels=\"environment=dev,application=analytics\""}
|
||||||
Annotation = Flag{Type: StringSlice, Name: flagkey.Annotation, Usage: "Annotation to apply to the function. To mention multiple annotations --annotation=\"abc.com/team=dev\" --annotation=\"foo=bar\""}
|
Annotation = Flag{Type: StringSlice, Name: flagkey.Annotation, Usage: "Annotation to apply to the function. To mention multiple annotations --annotation=\"abc.com/team=dev\" --annotation=\"foo=bar\""}
|
||||||
|
|
||||||
@@ -123,6 +127,8 @@ var (
|
|||||||
FnRequestsPerPod = Flag{Type: Int, Name: flagkey.FnRequestsPerPod, Aliases: []string{"rpp"}, Usage: "Maximum number of concurrent requests that can be served by a specialized pod", DefaultValue: 1}
|
FnRequestsPerPod = Flag{Type: Int, Name: flagkey.FnRequestsPerPod, Aliases: []string{"rpp"}, Usage: "Maximum number of concurrent requests that can be served by a specialized pod", DefaultValue: 1}
|
||||||
FnOnceOnly = Flag{Type: Bool, Name: flagkey.FnOnceOnly, Aliases: []string{"yolo"}, Usage: "Specifies if specialized pod will serve exactly one request in its lifetime"}
|
FnOnceOnly = Flag{Type: Bool, Name: flagkey.FnOnceOnly, Aliases: []string{"yolo"}, Usage: "Specifies if specialized pod will serve exactly one request in its lifetime"}
|
||||||
FnSubPath = Flag{Type: String, Name: flagkey.FnSubPath, Usage: "Sub Path to check if function internally supports routing"}
|
FnSubPath = Flag{Type: String, Name: flagkey.FnSubPath, Usage: "Sub Path to check if function internally supports routing"}
|
||||||
|
// Termination Grace Period configurable at function creation/update only for container functions
|
||||||
|
FnTerminationGracePeriod = Flag{Type: Int64, Name: flagkey.FnGracePeriod, Usage: "Grace time (in seconds) for pod to perform connection draining before termination (default value will be used if negative value is given)", DefaultValue: 360}
|
||||||
|
|
||||||
HtName = Flag{Type: String, Name: flagkey.HtName, Usage: "HTTP trigger name"}
|
HtName = Flag{Type: String, Name: flagkey.HtName, Usage: "HTTP trigger name"}
|
||||||
HtMethod = Flag{Type: StringSlice, Name: flagkey.HtMethod, Usage: "HTTP Methods: GET,POST,PUT,DELETE,HEAD. To mention single method: --method GET and for multiple methods --method GET --method POST. [DEPRECATED for 'fn create', use 'route create' instead]", DefaultValue: []string{http.MethodGet}}
|
HtMethod = Flag{Type: StringSlice, Name: flagkey.HtMethod, Usage: "HTTP Methods: GET,POST,PUT,DELETE,HEAD. To mention single method: --method GET and for multiple methods --method GET --method POST. [DEPRECATED for 'fn create', use 'route create' instead]", DefaultValue: []string{http.MethodGet}}
|
||||||
@@ -138,6 +144,10 @@ var (
|
|||||||
HtPrefix = Flag{Type: String, Name: flagkey.HtPrefix, Usage: "Prefix with which functions are exposed. NOTE: Prefix takes precedence over URL/RelativeURL [DEPRECATED for 'fn create', use 'route create' instead]"}
|
HtPrefix = Flag{Type: String, Name: flagkey.HtPrefix, Usage: "Prefix with which functions are exposed. NOTE: Prefix takes precedence over URL/RelativeURL [DEPRECATED for 'fn create', use 'route create' instead]"}
|
||||||
HtKeepPrefix = Flag{Type: Bool, Name: flagkey.HtKeepPrefix, Usage: "Keep the prefix in the URL while forwarding request to the function"}
|
HtKeepPrefix = Flag{Type: Bool, Name: flagkey.HtKeepPrefix, Usage: "Keep the prefix in the URL while forwarding request to the function"}
|
||||||
|
|
||||||
|
TokUsername = Flag{Type: String, Name: flagkey.TokUsername, Usage: "Username to generate token for function invocation"}
|
||||||
|
TokPassword = Flag{Type: String, Name: flagkey.TokPassword, Usage: "Password to generate token for function invocation"}
|
||||||
|
TokAuthURI = Flag{Type: String, Name: flagkey.TokAuthURI, Usage: "Relative URI path to generate token"}
|
||||||
|
|
||||||
TtName = Flag{Type: String, Name: flagkey.TtName, Usage: "Time Trigger name"}
|
TtName = Flag{Type: String, Name: flagkey.TtName, Usage: "Time Trigger name"}
|
||||||
TtCron = Flag{Type: String, Name: flagkey.TtCron, Usage: "Time trigger cron spec with each asterisk representing respectively second, minute, hour, the day of the month, month and day of the week. Also supports readable formats like '@every 5m', '@hourly'"}
|
TtCron = Flag{Type: String, Name: flagkey.TtCron, Usage: "Time trigger cron spec with each asterisk representing respectively second, minute, hour, the day of the month, month and day of the week. Also supports readable formats like '@every 5m', '@hourly'"}
|
||||||
TtFnName = Flag{Type: String, Name: flagkey.TtFnName, Usage: "Function name"}
|
TtFnName = Flag{Type: String, Name: flagkey.TtFnName, Usage: "Function name"}
|
||||||
@@ -145,7 +155,7 @@ var (
|
|||||||
|
|
||||||
MqtName = Flag{Type: String, Name: flagkey.MqtName, Usage: "Message queue trigger name"}
|
MqtName = Flag{Type: String, Name: flagkey.MqtName, Usage: "Message queue trigger name"}
|
||||||
MqtFnName = Flag{Type: String, Name: flagkey.MqtFnName, Usage: "Function name"}
|
MqtFnName = Flag{Type: String, Name: flagkey.MqtFnName, Usage: "Function name"}
|
||||||
MqtMQType = Flag{Type: String, Name: flagkey.MqtMQType, Usage: "Message queue type, e.g. nats-streaming, azure-storage-queue, kafka", DefaultValue: "nats-streaming"}
|
MqtMQType = Flag{Type: String, Name: flagkey.MqtMQType, Usage: "For mqtype \"fission\" => nats-streaming, azure-storage-queue, kafka\n\t\t\t\t\t For mqtype \"keda\" => kafka, aws-sqs-queue, aws-kinesis-stream, gcp-pubsub, stan, rabbitmq, redis", DefaultValue: "kafka"}
|
||||||
MqtTopic = Flag{Type: String, Name: flagkey.MqtTopic, Usage: "Message queue Topic the trigger listens on"}
|
MqtTopic = Flag{Type: String, Name: flagkey.MqtTopic, Usage: "Message queue Topic the trigger listens on"}
|
||||||
MqtRespTopic = Flag{Type: String, Name: flagkey.MqtRespTopic, Usage: "Topic that the function response is sent on (response discarded if unspecified)"}
|
MqtRespTopic = Flag{Type: String, Name: flagkey.MqtRespTopic, Usage: "Topic that the function response is sent on (response discarded if unspecified)"}
|
||||||
MqtErrorTopic = Flag{Type: String, Name: flagkey.MqtErrorTopic, Usage: "Topic that the function error messages are sent to (errors discarded if unspecified"}
|
MqtErrorTopic = Flag{Type: String, Name: flagkey.MqtErrorTopic, Usage: "Topic that the function error messages are sent to (errors discarded if unspecified"}
|
||||||
@@ -157,7 +167,7 @@ var (
|
|||||||
MqtMaxReplicaCount = Flag{Type: Int, Name: flagkey.MqtMaxReplicaCount, Usage: "Maximum number of replicas of consumers to scale up to", DefaultValue: 100}
|
MqtMaxReplicaCount = Flag{Type: Int, Name: flagkey.MqtMaxReplicaCount, Usage: "Maximum number of replicas of consumers to scale up to", DefaultValue: 100}
|
||||||
MqtMetadata = Flag{Type: StringSlice, Name: flagkey.MqtMetadata, Usage: "Metadata needed for connecting to source system in format: --metadata key1=value1 --metadata key2=value2"}
|
MqtMetadata = Flag{Type: StringSlice, Name: flagkey.MqtMetadata, Usage: "Metadata needed for connecting to source system in format: --metadata key1=value1 --metadata key2=value2"}
|
||||||
MqtSecret = Flag{Type: String, Name: flagkey.MqtSecret, Usage: "Name of secret object", DefaultValue: ""}
|
MqtSecret = Flag{Type: String, Name: flagkey.MqtSecret, Usage: "Name of secret object", DefaultValue: ""}
|
||||||
MqtKind = Flag{Type: String, Name: flagkey.MqtKind, Usage: "Kind of Message Queue Trigger, e.g. fission, keda", DefaultValue: "fission"}
|
MqtKind = Flag{Type: String, Name: flagkey.MqtKind, Usage: "Kind of Message Queue Trigger, e.g. fission, keda", DefaultValue: "keda"}
|
||||||
|
|
||||||
EnvName = Flag{Type: String, Name: flagkey.EnvName, Usage: "Environment name"}
|
EnvName = Flag{Type: String, Name: flagkey.EnvName, Usage: "Environment name"}
|
||||||
EnvPoolsize = Flag{Type: Int, Name: flagkey.EnvPoolsize, Usage: "Size of the pool", DefaultValue: 3}
|
EnvPoolsize = Flag{Type: Int, Name: flagkey.EnvPoolsize, Usage: "Size of the pool", DefaultValue: 3}
|
||||||
@@ -170,6 +180,7 @@ var (
|
|||||||
EnvVersion = Flag{Type: Int, Name: flagkey.EnvVersion, Usage: "Environment API version (1 means v1 interface)", DefaultValue: 1}
|
EnvVersion = Flag{Type: Int, Name: flagkey.EnvVersion, Usage: "Environment API version (1 means v1 interface)", DefaultValue: 1}
|
||||||
EnvImagePullSecret = Flag{Type: String, Name: flagkey.EnvImagePullSecret, Usage: "Secret for Kubernetes to pull an image from a private registry"}
|
EnvImagePullSecret = Flag{Type: String, Name: flagkey.EnvImagePullSecret, Usage: "Secret for Kubernetes to pull an image from a private registry"}
|
||||||
EnvExecutorType = Flag{Type: String, Name: flagkey.EnvExecutorType, Usage: "Executor type of pod in environment; one of 'poolmgr', 'newdeploy', 'container'"}
|
EnvExecutorType = Flag{Type: String, Name: flagkey.EnvExecutorType, Usage: "Executor type of pod in environment; one of 'poolmgr', 'newdeploy', 'container'"}
|
||||||
|
EnvForce = Flag{Type: Bool, Name: flagkey.EnvForce, Short: "f", Usage: "Force delete env even if one or more functions exist", DefaultValue: false}
|
||||||
|
|
||||||
KwName = Flag{Type: String, Name: flagkey.KwName, Usage: "Watch name"}
|
KwName = Flag{Type: String, Name: flagkey.KwName, Usage: "Watch name"}
|
||||||
KwFnName = Flag{Type: String, Name: flagkey.KwFnName, Usage: "Function name"}
|
KwFnName = Flag{Type: String, Name: flagkey.KwFnName, Usage: "Function name"}
|
||||||
@@ -191,16 +202,18 @@ var (
|
|||||||
PkgSrcChecksum = Flag{Type: String, Name: flagkey.PkgSrcChecksum, Usage: "SHA256 checksum of source archive when providing URL"}
|
PkgSrcChecksum = Flag{Type: String, Name: flagkey.PkgSrcChecksum, Usage: "SHA256 checksum of source archive when providing URL"}
|
||||||
PkgInsecure = Flag{Type: Bool, Name: flagkey.PkgInsecure, Usage: "Skip generating SHA256 checksum for file integrity validation"}
|
PkgInsecure = Flag{Type: Bool, Name: flagkey.PkgInsecure, Usage: "Skip generating SHA256 checksum for file integrity validation"}
|
||||||
|
|
||||||
SpecSave = Flag{Type: Bool, Name: flagkey.SpecSave, Usage: "Save to the spec directory instead of creating on cluster"}
|
SpecSave = Flag{Type: Bool, Name: flagkey.SpecSave, Usage: "Save to the spec directory instead of creating on cluster"}
|
||||||
SpecDir = Flag{Type: String, Name: flagkey.SpecDir, Usage: "Directory to store specs, defaults to ./specs"}
|
SpecDir = Flag{Type: String, Name: flagkey.SpecDir, Usage: "Directory to store specs, defaults to ./specs"}
|
||||||
SpecName = Flag{Type: String, Name: flagkey.SpecName, Usage: "Name for the app, applied to resources as a Kubernetes annotation"}
|
SpecName = Flag{Type: String, Name: flagkey.SpecName, Usage: "Name for the app, applied to resources as a Kubernetes annotation"}
|
||||||
SpecDeployID = Flag{Type: String, Name: flagkey.SpecDeployID, Aliases: []string{"id"}, Usage: "Deployment ID for the spec deployment config"}
|
SpecDeployID = Flag{Type: String, Name: flagkey.SpecDeployID, Aliases: []string{"id"}, Usage: "Deployment ID for the spec deployment config"}
|
||||||
SpecWait = Flag{Type: Bool, Name: flagkey.SpecWait, Usage: "Wait for package builds"}
|
SpecWait = Flag{Type: Bool, Name: flagkey.SpecWait, Usage: "Wait for package builds"}
|
||||||
SpecWatch = Flag{Type: Bool, Name: flagkey.SpecWatch, Usage: "Watch local files for change, and re-apply specs as necessary"}
|
SpecWatch = Flag{Type: Bool, Name: flagkey.SpecWatch, Usage: "Watch local files for change, and re-apply specs as necessary"}
|
||||||
SpecDelete = Flag{Type: Bool, Name: flagkey.SpecDelete, Usage: "Allow apply to delete resources that no longer exist in the specification"}
|
SpecDelete = Flag{Type: Bool, Name: flagkey.SpecDelete, Usage: "Allow apply to delete resources that no longer exist in the specification"}
|
||||||
SpecDry = Flag{Type: Bool, Name: flagkey.SpecDry, Usage: "View the generated specs"}
|
SpecDry = Flag{Type: Bool, Name: flagkey.SpecDry, Usage: "View the generated specs"}
|
||||||
SpecValidation = Flag{Type: String, Name: flagkey.SpecValidate, Usage: "Turns server side validations of Fission objects on/off"}
|
SpecValidation = Flag{Type: String, Name: flagkey.SpecValidate, Usage: "Turns server side validations of Fission objects on/off"}
|
||||||
SpecIgnore = Flag{Type: String, Name: flagkey.SpecIgnore, Usage: fmt.Sprintf("File containing specs to be ignored inside --specdir, defaults to %v", util.SPEC_IGNORE_FILE)}
|
SpecIgnore = Flag{Type: String, Name: flagkey.SpecIgnore, Usage: fmt.Sprintf("File containing specs to be ingored inside --specdir, defaults to %v", util.SPEC_IGNORE_FILE)}
|
||||||
|
SpecApplyCommitLabel = Flag{Type: Bool, Name: flagkey.SpecApplyCommitLabel, Usage: "Apply commit label to the resources"}
|
||||||
|
SpecAllowConflicts = Flag{Type: Bool, Name: flagkey.SpecAllowConflicts, Usage: "If true, spec apply will be forced even if conflicting resources exist", DefaultValue: false}
|
||||||
|
|
||||||
SupportOutput = Flag{Type: String, Name: flagkey.SupportOutput, Short: "o", Usage: "Output directory to save dump archive/files", DefaultValue: flagkey.DefaultSpecOutputDir}
|
SupportOutput = Flag{Type: String, Name: flagkey.SupportOutput, Short: "o", Usage: "Output directory to save dump archive/files", DefaultValue: flagkey.DefaultSpecOutputDir}
|
||||||
SupportNoZip = Flag{Type: Bool, Name: flagkey.SupportNoZip, Usage: "Save dump information into multiple files instead of single zip file"}
|
SupportNoZip = Flag{Type: Bool, Name: flagkey.SupportNoZip, Usage: "Save dump information into multiple files instead of single zip file"}
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ const (
|
|||||||
ClientOnly = "client-only"
|
ClientOnly = "client-only"
|
||||||
KubeContext = "kube-context"
|
KubeContext = "kube-context"
|
||||||
|
|
||||||
|
PreCheckOnly = "pre"
|
||||||
|
|
||||||
resourceName = "name"
|
resourceName = "name"
|
||||||
force = "force"
|
force = "force"
|
||||||
Output = "output"
|
Output = "output"
|
||||||
@@ -29,6 +31,8 @@ const (
|
|||||||
Labels = "labels"
|
Labels = "labels"
|
||||||
Annotation = "annotation"
|
Annotation = "annotation"
|
||||||
|
|
||||||
|
IgnoreNotFound = "ignorenotfound"
|
||||||
|
|
||||||
NamespaceFunction = "fnNamespace"
|
NamespaceFunction = "fnNamespace"
|
||||||
NamespaceEnvironment = "envNamespace"
|
NamespaceEnvironment = "envNamespace"
|
||||||
NamespacePackage = "pkgNamespace"
|
NamespacePackage = "pkgNamespace"
|
||||||
@@ -74,6 +78,7 @@ const (
|
|||||||
FnRequestsPerPod = "requestsperpod"
|
FnRequestsPerPod = "requestsperpod"
|
||||||
FnOnceOnly = "onceonly"
|
FnOnceOnly = "onceonly"
|
||||||
FnSubPath = "subpath"
|
FnSubPath = "subpath"
|
||||||
|
FnGracePeriod = "graceperiod"
|
||||||
|
|
||||||
HtName = resourceName
|
HtName = resourceName
|
||||||
HtMethod = "method"
|
HtMethod = "method"
|
||||||
@@ -89,6 +94,10 @@ const (
|
|||||||
HtPrefix = "prefix"
|
HtPrefix = "prefix"
|
||||||
HtKeepPrefix = "keepprefix"
|
HtKeepPrefix = "keepprefix"
|
||||||
|
|
||||||
|
TokUsername = "username"
|
||||||
|
TokPassword = "password"
|
||||||
|
TokAuthURI = "authuri"
|
||||||
|
|
||||||
TtName = resourceName
|
TtName = resourceName
|
||||||
TtCron = "cron"
|
TtCron = "cron"
|
||||||
TtFnName = "function"
|
TtFnName = "function"
|
||||||
@@ -121,6 +130,7 @@ const (
|
|||||||
EnvVersion = "version"
|
EnvVersion = "version"
|
||||||
EnvImagePullSecret = "imagepullsecret"
|
EnvImagePullSecret = "imagepullsecret"
|
||||||
EnvExecutorType = "executortype"
|
EnvExecutorType = "executortype"
|
||||||
|
EnvForce = force
|
||||||
|
|
||||||
KwName = resourceName
|
KwName = resourceName
|
||||||
KwFnName = "function"
|
KwFnName = "function"
|
||||||
@@ -142,16 +152,18 @@ const (
|
|||||||
PkgStatus = "status"
|
PkgStatus = "status"
|
||||||
PkgOrphan = "orphan"
|
PkgOrphan = "orphan"
|
||||||
|
|
||||||
SpecSave = "spec"
|
SpecSave = "spec"
|
||||||
SpecDir = "specdir"
|
SpecDir = "specdir"
|
||||||
SpecName = resourceName
|
SpecName = resourceName
|
||||||
SpecDeployID = "deployid"
|
SpecDeployID = "deployid"
|
||||||
SpecWait = "wait"
|
SpecWait = "wait"
|
||||||
SpecWatch = "watch"
|
SpecWatch = "watch"
|
||||||
SpecDelete = "delete"
|
SpecDelete = "delete"
|
||||||
SpecDry = "dry"
|
SpecDry = "dry"
|
||||||
SpecValidate = "validation"
|
SpecValidate = "validation"
|
||||||
SpecIgnore = "specignore"
|
SpecIgnore = "specignore"
|
||||||
|
SpecApplyCommitLabel = "commitlabel"
|
||||||
|
SpecAllowConflicts = "allowconflicts"
|
||||||
|
|
||||||
SupportOutput = Output
|
SupportOutput = Output
|
||||||
SupportNoZip = "nozip"
|
SupportNoZip = "nozip"
|
||||||
|
|||||||
@@ -18,5 +18,8 @@ package util
|
|||||||
|
|
||||||
// fission-cli options
|
// fission-cli options
|
||||||
const (
|
const (
|
||||||
SPEC_IGNORE_FILE = ".specignore"
|
SPEC_IGNORE_FILE = ".specignore"
|
||||||
|
COMMIT_LABEL = "commit"
|
||||||
|
FISSION_AUTH_URI = "/auth/login"
|
||||||
|
FISSION_AUTH_TOKEN = "FISSION_AUTH_TOKEN"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2021 The Fission Authors.
|
||||||
|
|
||||||
|
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://www.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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func IsNotFound(err error) bool {
|
||||||
|
return strings.HasSuffix(strings.TrimSpace(err.Error()), "not found")
|
||||||
|
}
|
||||||
@@ -74,10 +74,7 @@ func (c *Clientset) Tracker() testing.ObjectTracker {
|
|||||||
return c.tracker
|
return c.tracker
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var _ clientset.Interface = &Clientset{}
|
||||||
_ clientset.Interface = &Clientset{}
|
|
||||||
_ testing.FakeClient = &Clientset{}
|
|
||||||
)
|
|
||||||
|
|
||||||
// CoreV1 retrieves the CoreV1Client
|
// CoreV1 retrieves the CoreV1Client
|
||||||
func (c *Clientset) CoreV1() corev1.CoreV1Interface {
|
func (c *Clientset) CoreV1() corev1.CoreV1Interface {
|
||||||
|
|||||||
@@ -0,0 +1,243 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2022 The Fission Authors.
|
||||||
|
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://www.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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package healthcheck
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/fatih/color"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/client-go/kubernetes"
|
||||||
|
|
||||||
|
fv1 "github.com/fission/fission/pkg/apis/core/v1"
|
||||||
|
"github.com/fission/fission/pkg/controller/client"
|
||||||
|
"github.com/fission/fission/pkg/fission-cli/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CategoryID string
|
||||||
|
|
||||||
|
const (
|
||||||
|
Kubernetes CategoryID = "kubernetes"
|
||||||
|
FissionServices CategoryID = "fission-services"
|
||||||
|
FissionVersion CategoryID = "fission-version"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
okStatus = color.New(color.FgGreen, color.Bold).SprintFunc()("\u221A") // √
|
||||||
|
failStatus = color.New(color.FgRed, color.Bold).SprintFunc()("\u00D7") // ×
|
||||||
|
)
|
||||||
|
|
||||||
|
// Category is a group of checkers
|
||||||
|
type Category struct {
|
||||||
|
ID CategoryID
|
||||||
|
checkers []Checker
|
||||||
|
enabled bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type Checker struct {
|
||||||
|
successMsg string
|
||||||
|
check func() error
|
||||||
|
}
|
||||||
|
|
||||||
|
type Options struct {
|
||||||
|
KubeContext string
|
||||||
|
FissionClient client.Interface
|
||||||
|
}
|
||||||
|
|
||||||
|
type HealthChecker struct {
|
||||||
|
categories []*Category
|
||||||
|
*Options
|
||||||
|
|
||||||
|
kubeAPI *kubernetes.Clientset
|
||||||
|
fissionNamespace string
|
||||||
|
}
|
||||||
|
|
||||||
|
func isCompatibleVersion(minimalRequirementVersion [3]int, actualVersion [3]int) bool {
|
||||||
|
if minimalRequirementVersion[0] < actualVersion[0] {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (minimalRequirementVersion[0] == actualVersion[0]) && minimalRequirementVersion[1] < actualVersion[1] {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (minimalRequirementVersion[0] == actualVersion[0]) && (minimalRequirementVersion[1] == actualVersion[1]) && (minimalRequirementVersion[2] <= actualVersion[2]) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hc *HealthChecker) CheckKubeVersion() (err error) {
|
||||||
|
|
||||||
|
version, err := hc.kubeAPI.ServerVersion()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
major, _ := strconv.Atoi(version.Major)
|
||||||
|
minor, _ := strconv.Atoi(version.Minor)
|
||||||
|
apiVersion := [3]int{major, minor, 0}
|
||||||
|
|
||||||
|
if !isCompatibleVersion(fv1.MinimumKubernetesVersion, apiVersion) {
|
||||||
|
return fmt.Errorf("kubernetes is on version %d.%d.%d, but version %d.%d.%d or more recent is required",
|
||||||
|
apiVersion[0], apiVersion[1], apiVersion[2],
|
||||||
|
fv1.MinimumKubernetesVersion[0], fv1.MinimumKubernetesVersion[1], fv1.MinimumKubernetesVersion[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hc *HealthChecker) CheckServiceStatus(namespace string, name string) (err error) {
|
||||||
|
depl, err := hc.kubeAPI.AppsV1().Deployments(namespace).Get(context.TODO(), name, metav1.GetOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get %s deployment status", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if depl.Status.UnavailableReplicas > 0 || depl.Status.Replicas == 0 {
|
||||||
|
return fmt.Errorf("%s deployment is not running", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = hc.kubeAPI.CoreV1().Services(namespace).Get(context.TODO(), name, metav1.GetOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get %s service status", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hc *HealthChecker) CheckFissionVersion() error {
|
||||||
|
ver := util.GetVersion(hc.FissionClient)
|
||||||
|
|
||||||
|
clientVersion := ver.Client["fission/core"].Version
|
||||||
|
serverVersion := ver.Server["fission/core"].Version
|
||||||
|
|
||||||
|
if clientVersion != serverVersion {
|
||||||
|
return fmt.Errorf("client version %s does not match with server version %s", clientVersion, serverVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCategory(id CategoryID, checkers []Checker, enabled bool) *Category {
|
||||||
|
return &Category{
|
||||||
|
ID: id,
|
||||||
|
checkers: checkers,
|
||||||
|
enabled: enabled,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hc *HealthChecker) allCategories() []*Category {
|
||||||
|
return []*Category{
|
||||||
|
NewCategory(
|
||||||
|
Kubernetes,
|
||||||
|
[]Checker{
|
||||||
|
{
|
||||||
|
successMsg: "kubernetes version is compatible",
|
||||||
|
check: func() (err error) {
|
||||||
|
return hc.CheckKubeVersion()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
NewCategory(
|
||||||
|
FissionServices,
|
||||||
|
[]Checker{
|
||||||
|
{
|
||||||
|
successMsg: "controller is running fine",
|
||||||
|
check: func() error {
|
||||||
|
return hc.CheckServiceStatus(hc.fissionNamespace, "controller")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
successMsg: "executor is running fine",
|
||||||
|
check: func() error {
|
||||||
|
return hc.CheckServiceStatus(hc.fissionNamespace, "executor")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
successMsg: "router is running fine",
|
||||||
|
check: func() error {
|
||||||
|
return hc.CheckServiceStatus(hc.fissionNamespace, "router")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
successMsg: "storagesvc is running fine",
|
||||||
|
check: func() error {
|
||||||
|
return hc.CheckServiceStatus(hc.fissionNamespace, "storagesvc")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
NewCategory(
|
||||||
|
FissionVersion,
|
||||||
|
[]Checker{
|
||||||
|
{
|
||||||
|
successMsg: "fission is up-to-date",
|
||||||
|
check: func() error {
|
||||||
|
return hc.CheckFissionVersion()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHealthChecker(categoryIDs []CategoryID, options *Options) *HealthChecker {
|
||||||
|
hc := &HealthChecker{
|
||||||
|
Options: options,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, clientset, _ := util.GetKubernetesClient(hc.KubeContext)
|
||||||
|
hc.kubeAPI = clientset
|
||||||
|
hc.fissionNamespace = "fission"
|
||||||
|
|
||||||
|
hc.categories = hc.allCategories()
|
||||||
|
|
||||||
|
checkMap := map[CategoryID]struct{}{}
|
||||||
|
for _, category := range categoryIDs {
|
||||||
|
checkMap[category] = struct{}{}
|
||||||
|
}
|
||||||
|
for i := range hc.categories {
|
||||||
|
if _, ok := checkMap[hc.categories[i].ID]; ok {
|
||||||
|
hc.categories[i].enabled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hc
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunChecks(hc *HealthChecker) {
|
||||||
|
for _, c := range hc.categories {
|
||||||
|
if c.enabled {
|
||||||
|
fmt.Println(c.ID)
|
||||||
|
fmt.Println(strings.Repeat("-", 20))
|
||||||
|
for _, checker := range c.checkers {
|
||||||
|
err := checker.check()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("%s %s\n", failStatus, err)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("%s %s\n", okStatus, checker.successMsg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Printf("\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -104,7 +104,7 @@ func mqTriggerEventHandlers(logger *zap.Logger, kubeClient *kubernetes.Clientset
|
|||||||
logger.Error("Failed to delete Authentication Trigger", zap.Error(err))
|
logger.Error("Failed to delete Authentication Trigger", zap.Error(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err = deleteDeployment(mqt.ObjectMeta.Name, kubeClient); err != nil {
|
if err = deleteDeployment(mqt.ObjectMeta.Name, mqt.ObjectMeta.Namespace, kubeClient); err != nil {
|
||||||
logger.Error("Failed to delete Deployment", zap.Error(err))
|
logger.Error("Failed to delete Deployment", zap.Error(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -453,7 +453,7 @@ func createDeployment(mqt *fv1.MessageQueueTrigger, routerURL string, kubeClient
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = kubeClient.AppsV1().Deployments(apiv1.NamespaceDefault).Create(context.TODO(), deployment, metav1.CreateOptions{})
|
_, err = kubeClient.AppsV1().Deployments(mqt.ObjectMeta.Namespace).Create(context.TODO(), deployment, metav1.CreateOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -465,16 +465,16 @@ func updateDeployment(mqt *fv1.MessageQueueTrigger, routerURL string, kubeClient
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = kubeClient.AppsV1().Deployments(apiv1.NamespaceDefault).Update(context.TODO(), deployment, metav1.UpdateOptions{})
|
_, err = kubeClient.AppsV1().Deployments(mqt.ObjectMeta.Namespace).Update(context.TODO(), deployment, metav1.UpdateOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteDeployment(name string, kubeClient *kubernetes.Clientset) error {
|
func deleteDeployment(name string, namespace string, kubeClient *kubernetes.Clientset) error {
|
||||||
deletePolicy := metav1.DeletePropagationForeground
|
deletePolicy := metav1.DeletePropagationForeground
|
||||||
if err := kubeClient.AppsV1().Deployments(apiv1.NamespaceDefault).Delete(context.TODO(), name, metav1.DeleteOptions{
|
if err := kubeClient.AppsV1().Deployments(namespace).Delete(context.TODO(), name, metav1.DeleteOptions{
|
||||||
PropagationPolicy: &deletePolicy,
|
PropagationPolicy: &deletePolicy,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -21,8 +21,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
topicValidators = make(map[string]TopicValidator)
|
topicValidators = make(map[string]TopicValidator)
|
||||||
lock = sync.Mutex{}
|
lock = sync.Mutex{}
|
||||||
|
kedaMqTypeValidators = map[string]bool{
|
||||||
|
"kafka": true,
|
||||||
|
"aws-sqs-queue": true,
|
||||||
|
"aws-kinesis-stream": true,
|
||||||
|
"gcp-pubsub": true,
|
||||||
|
"stan": true,
|
||||||
|
"rabbitmq": true,
|
||||||
|
"redis": true,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@@ -58,7 +67,7 @@ func IsValidTopic(mqType, topic, mqtKind string) bool {
|
|||||||
|
|
||||||
func IsValidMessageQueue(mqType, mqtKind string) bool {
|
func IsValidMessageQueue(mqType, mqtKind string) bool {
|
||||||
if mqtKind == "keda" {
|
if mqtKind == "keda" {
|
||||||
return true
|
return kedaMqTypeValidators[mqType]
|
||||||
}
|
}
|
||||||
_, registered := topicValidators[mqType]
|
_, registered := topicValidators[mqType]
|
||||||
return registered
|
return registered
|
||||||
|
|||||||
+172
-3
@@ -18,10 +18,16 @@ package router
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/golang-jwt/jwt/v4"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
@@ -31,6 +37,7 @@ import (
|
|||||||
fv1 "github.com/fission/fission/pkg/apis/core/v1"
|
fv1 "github.com/fission/fission/pkg/apis/core/v1"
|
||||||
"github.com/fission/fission/pkg/crd"
|
"github.com/fission/fission/pkg/crd"
|
||||||
executorClient "github.com/fission/fission/pkg/executor/client"
|
executorClient "github.com/fission/fission/pkg/executor/client"
|
||||||
|
config "github.com/fission/fission/pkg/featureconfig"
|
||||||
genInformer "github.com/fission/fission/pkg/generated/informers/externalversions"
|
genInformer "github.com/fission/fission/pkg/generated/informers/externalversions"
|
||||||
"github.com/fission/fission/pkg/throttler"
|
"github.com/fission/fission/pkg/throttler"
|
||||||
"github.com/fission/fission/pkg/utils"
|
"github.com/fission/fission/pkg/utils"
|
||||||
@@ -38,6 +45,8 @@ import (
|
|||||||
"github.com/fission/fission/pkg/utils/tracing"
|
"github.com/fission/fission/pkg/utils/tracing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var featureConfig *config.FeatureConfig
|
||||||
|
|
||||||
// HTTPTriggerSet represents an HTTP trigger set
|
// HTTPTriggerSet represents an HTTP trigger set
|
||||||
type HTTPTriggerSet struct {
|
type HTTPTriggerSet struct {
|
||||||
*functionServiceMap
|
*functionServiceMap
|
||||||
@@ -59,6 +68,20 @@ type HTTPTriggerSet struct {
|
|||||||
unTapServiceTimeout time.Duration
|
unTapServiceTimeout time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
_ = loadFeatureConfigmap()
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadFeatureConfigmap() error {
|
||||||
|
var err error
|
||||||
|
featureConfig, err = config.GetFeatureConfig()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return errors.New("error while loading feature configmap")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func makeHTTPTriggerSet(logger *zap.Logger, fmap *functionServiceMap, fissionClient *crd.FissionClient,
|
func makeHTTPTriggerSet(logger *zap.Logger, fmap *functionServiceMap, fissionClient *crd.FissionClient,
|
||||||
kubeClient *kubernetes.Clientset, executor *executorClient.Client, params *tsRoundTripperParams, isDebugEnv bool, unTapServiceTimeout time.Duration, actionThrottler *throttler.Throttler) *HTTPTriggerSet {
|
kubeClient *kubernetes.Clientset, executor *executorClient.Client, params *tsRoundTripperParams, isDebugEnv bool, unTapServiceTimeout time.Duration, actionThrottler *throttler.Throttler) *HTTPTriggerSet {
|
||||||
|
|
||||||
@@ -106,10 +129,92 @@ func defaultHomeHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createErrorResponse(errMsg string, statusCode int) []byte {
|
||||||
|
resp, _ := json.Marshal(map[string]interface{}{"statusCode": statusCode, "message": errMsg})
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
|
||||||
func routerHealthHandler(w http.ResponseWriter, r *http.Request) {
|
func routerHealthHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func authLoginHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
body, err := io.ReadAll(r.Body)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
_, _ = w.Write(createErrorResponse("Error while reading request body", http.StatusBadRequest))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var t fv1.AuthLogin
|
||||||
|
|
||||||
|
err = json.Unmarshal(body, &t)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
_, _ = w.Write(createErrorResponse("Error while reading request body", http.StatusBadRequest))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
username, ok := os.LookupEnv("AUTH_USERNAME")
|
||||||
|
if !ok || len(username) == 0 {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
_, _ = w.Write(createErrorResponse("Username not found or invalid", http.StatusBadRequest))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
password, ok := os.LookupEnv("AUTH_PASSWORD")
|
||||||
|
if !ok || len(password) == 0 {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
_, _ = w.Write(createErrorResponse("Password not found or invalid", http.StatusBadRequest))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
signingKey, ok := os.LookupEnv("JWT_SIGNING_KEY")
|
||||||
|
if !ok || len(signingKey) == 0 {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
_, _ = w.Write(createErrorResponse("Internal server error occurred", http.StatusInternalServerError))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rat := &fv1.RouterAuthToken{}
|
||||||
|
|
||||||
|
if t.Username == username && t.Password == password {
|
||||||
|
|
||||||
|
claims := &jwt.RegisteredClaims{
|
||||||
|
ExpiresAt: jwt.NewNumericDate(jwt.TimeFunc().Add(featureConfig.AuthConfig.JWTExpiryTime * time.Second)),
|
||||||
|
Issuer: featureConfig.AuthConfig.JWTIssuer,
|
||||||
|
NotBefore: jwt.NewNumericDate(jwt.TimeFunc()),
|
||||||
|
}
|
||||||
|
|
||||||
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||||
|
ss, err := token.SignedString([]byte(signingKey))
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
_, _ = w.Write(createErrorResponse("Internal server error occurred", http.StatusInternalServerError))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rat.AccessToken = ss
|
||||||
|
rat.TokenType = "Bearer"
|
||||||
|
|
||||||
|
} else {
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
_, _ = w.Write(createErrorResponse("Unauthorized: invalid username and/or password", http.StatusUnauthorized))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := json.Marshal(rat)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
_, _ = w.Write(createErrorResponse("Internal server error occurred", http.StatusInternalServerError))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusCreated)
|
||||||
|
_, _ = w.Write(resp)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func (ts *HTTPTriggerSet) getRouter(fnTimeoutMap map[types.UID]int) *mux.Router {
|
func (ts *HTTPTriggerSet) getRouter(fnTimeoutMap map[types.UID]int) *mux.Router {
|
||||||
muxRouter := mux.NewRouter()
|
muxRouter := mux.NewRouter()
|
||||||
|
|
||||||
@@ -199,7 +304,12 @@ func (ts *HTTPTriggerSet) getRouter(fnTimeoutMap map[types.UID]int) *mux.Router
|
|||||||
}
|
}
|
||||||
ts.logger.Debug("add prefix route for function", zap.String("route", prefix), zap.Any("function", fh.function), zap.Strings("methods", methods))
|
ts.logger.Debug("add prefix route for function", zap.String("route", prefix), zap.Any("function", fh.function), zap.Strings("methods", methods))
|
||||||
} else {
|
} else {
|
||||||
ht1 := muxRouter.Handle(prefix, handler)
|
var ht1 *mux.Route
|
||||||
|
if featureConfig.AuthConfig.IsEnabled {
|
||||||
|
ht1 = muxRouter.Handle(prefix, authMiddleware(handler))
|
||||||
|
} else {
|
||||||
|
ht1 = muxRouter.Handle(prefix, handler)
|
||||||
|
}
|
||||||
ht1.Methods(methods...)
|
ht1.Methods(methods...)
|
||||||
if trigger.Spec.Host != "" {
|
if trigger.Spec.Host != "" {
|
||||||
ht1.Host(trigger.Spec.Host)
|
ht1.Host(trigger.Spec.Host)
|
||||||
@@ -212,7 +322,12 @@ func (ts *HTTPTriggerSet) getRouter(fnTimeoutMap map[types.UID]int) *mux.Router
|
|||||||
ts.logger.Debug("add prefix and handler route for function", zap.String("route", prefix), zap.Any("function", fh.function), zap.Strings("methods", methods))
|
ts.logger.Debug("add prefix and handler route for function", zap.String("route", prefix), zap.Any("function", fh.function), zap.Strings("methods", methods))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ht := muxRouter.Handle(trigger.Spec.RelativeURL, handler)
|
var ht *mux.Route
|
||||||
|
if featureConfig.AuthConfig.IsEnabled {
|
||||||
|
ht = muxRouter.Handle(trigger.Spec.RelativeURL, authMiddleware(handler))
|
||||||
|
} else {
|
||||||
|
ht = muxRouter.Handle(trigger.Spec.RelativeURL, handler)
|
||||||
|
}
|
||||||
ht.Methods(methods...)
|
ht.Methods(methods...)
|
||||||
if trigger.Spec.Host != "" {
|
if trigger.Spec.Host != "" {
|
||||||
ht.Host(trigger.Spec.Host)
|
ht.Host(trigger.Spec.Host)
|
||||||
@@ -259,17 +374,71 @@ func (ts *HTTPTriggerSet) getRouter(fnTimeoutMap map[types.UID]int) *mux.Router
|
|||||||
} else {
|
} else {
|
||||||
handler = otel.GetHandlerWithOTEL(http.HandlerFunc(fh.handler), internalRoute)
|
handler = otel.GetHandlerWithOTEL(http.HandlerFunc(fh.handler), internalRoute)
|
||||||
}
|
}
|
||||||
muxRouter.Handle(internalRoute, handler)
|
|
||||||
|
if featureConfig.AuthConfig.IsEnabled {
|
||||||
|
muxRouter.Handle(internalRoute, authMiddleware(handler))
|
||||||
|
} else {
|
||||||
|
muxRouter.Handle(internalRoute, handler)
|
||||||
|
}
|
||||||
muxRouter.PathPrefix(internalPrefixRoute).Handler(handler)
|
muxRouter.PathPrefix(internalPrefixRoute).Handler(handler)
|
||||||
ts.logger.Debug("add internal handler and prefix route for function", zap.String("router", internalRoute), zap.Any("function", fn))
|
ts.logger.Debug("add internal handler and prefix route for function", zap.String("router", internalRoute), zap.Any("function", fn))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if featureConfig.AuthConfig.IsEnabled {
|
||||||
|
|
||||||
|
path := featureConfig.AuthConfig.AuthUriPath
|
||||||
|
if len(path) == 0 {
|
||||||
|
path = "/auth/login"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auth endpoint for the router.
|
||||||
|
muxRouter.HandleFunc(path, authLoginHandler).Methods("POST")
|
||||||
|
}
|
||||||
|
|
||||||
// Healthz endpoint for the router.
|
// Healthz endpoint for the router.
|
||||||
muxRouter.HandleFunc("/router-healthz", routerHealthHandler).Methods("GET")
|
muxRouter.HandleFunc("/router-healthz", routerHealthHandler).Methods("GET")
|
||||||
|
|
||||||
return muxRouter
|
return muxRouter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func authMiddleware(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
authHeader := strings.Split(r.Header.Get("Authorization"), "Bearer ")
|
||||||
|
if len(authHeader) != 2 || len(authHeader[1]) == 0 {
|
||||||
|
// malformed token
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
_, _ = w.Write(createErrorResponse("Unauthorized: malformed Token", http.StatusUnauthorized))
|
||||||
|
} else {
|
||||||
|
jwtToken := authHeader[1]
|
||||||
|
token, err := jwt.Parse(jwtToken, func(token *jwt.Token) (interface{}, error) {
|
||||||
|
return []byte(os.Getenv("JWT_SIGNING_KEY")), nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if token != nil && token.Valid {
|
||||||
|
// valid token
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
} else if ve, ok := err.(*jwt.ValidationError); ok {
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
if ve.Errors&jwt.ValidationErrorMalformed != 0 {
|
||||||
|
// malformed token
|
||||||
|
_, _ = w.Write(createErrorResponse("Unauthorized: malformed Token", http.StatusUnauthorized))
|
||||||
|
} else if ve.Errors&(jwt.ValidationErrorExpired|jwt.ValidationErrorNotValidYet) != 0 {
|
||||||
|
// token is either expired or not active yet
|
||||||
|
_, _ = w.Write(createErrorResponse("Unauthorized: token is either expired or not active yet", http.StatusUnauthorized))
|
||||||
|
} else {
|
||||||
|
_, _ = w.Write(createErrorResponse(fmt.Sprintf("Unauthorized: %v", err.Error()), http.StatusUnauthorized))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
_, _ = w.Write(createErrorResponse("Unauthorized", http.StatusUnauthorized))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (ts *HTTPTriggerSet) updateTriggerStatusFailed(ht *fv1.HTTPTrigger, err error) {
|
func (ts *HTTPTriggerSet) updateTriggerStatusFailed(ht *fv1.HTTPTrigger, err error) {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,157 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2022 The Fission Authors.
|
||||||
|
|
||||||
|
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://www.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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package gitrepo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-git/go-git/v5"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GitRepo struct {
|
||||||
|
setupDone bool
|
||||||
|
isGitRepo bool
|
||||||
|
repo *git.Repository
|
||||||
|
status git.Status
|
||||||
|
dirPath string
|
||||||
|
gitRepoRootPath string // absolute path of the root of the git repository
|
||||||
|
commitID string // commit ID the HEAD of the repository is poitning to
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGitRepo creates new GitRepo struct
|
||||||
|
// checks if the given directory path is part of git repository
|
||||||
|
// accordingly updates the fields of GitRepo struct and returns it
|
||||||
|
func NewGitRepo(dirPath string) *GitRepo {
|
||||||
|
|
||||||
|
var g *GitRepo = &GitRepo{}
|
||||||
|
var err error
|
||||||
|
|
||||||
|
g.dirPath = dirPath
|
||||||
|
g.setupDone = true
|
||||||
|
|
||||||
|
// check if directory is tracked by git repo
|
||||||
|
g.repo, err = git.PlainOpenWithOptions(dirPath, &git.PlainOpenOptions{DetectDotGit: true})
|
||||||
|
if err != nil {
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
workTree, err := g.repo.Worktree()
|
||||||
|
if err != nil {
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
g.status, err = workTree.Status()
|
||||||
|
if err != nil {
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
if g.status == nil {
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
plumbRef, err := g.repo.Head()
|
||||||
|
if err != nil {
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract short commit ID
|
||||||
|
g.commitID = plumbRef.Hash().String()[:7]
|
||||||
|
|
||||||
|
// get the root path of git repository
|
||||||
|
g.gitRepoRootPath = workTree.Filesystem.Root()
|
||||||
|
|
||||||
|
g.isGitRepo = true
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsGitRepo returns if the initialized directory path is tracked by git repo
|
||||||
|
func (g *GitRepo) IsGitRepo() bool {
|
||||||
|
return g.setupDone && g.isGitRepo
|
||||||
|
}
|
||||||
|
|
||||||
|
// getFileCommitLabel returns the value of 'commit' label
|
||||||
|
// for the resources present in the file
|
||||||
|
/*
|
||||||
|
The value of the `commit` label for different status of the file is as follows:
|
||||||
|
| Git File Status | Label Value |
|
||||||
|
|---------------------------------------|----------------------|
|
||||||
|
| New untracked file | untracked |
|
||||||
|
| New staged file | staged |
|
||||||
|
| Tracked file with changes in worktree | <commitID>-unstaged |
|
||||||
|
| Tracked file with changes staged | <commitID>-staged |
|
||||||
|
| Tracked file with clean commit | <commitID> |
|
||||||
|
*/
|
||||||
|
func (g *GitRepo) GetFileCommitLabel(filePath string) (string, error) {
|
||||||
|
|
||||||
|
if !g.setupDone {
|
||||||
|
return "", errors.New(`GitRepo is not setup. It has to be created by calling 'NewGitRepo' function,
|
||||||
|
then this function has to be called.`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !g.isGitRepo {
|
||||||
|
return "", errors.Errorf(`directory: %s doesn't belong to git repository.`, g.dirPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// filepath in the git repository
|
||||||
|
splitPathList := strings.Split(filePath, g.gitRepoRootPath+string(os.PathSeparator))
|
||||||
|
if len(splitPathList) != 2 {
|
||||||
|
return "", errors.Errorf("error finding the git repository path of %s", filePath)
|
||||||
|
}
|
||||||
|
gitFilePath := splitPathList[1]
|
||||||
|
gitFileStatus := g.status.File(gitFilePath)
|
||||||
|
|
||||||
|
// check if file is tracked
|
||||||
|
if !g.status.IsUntracked(gitFilePath) {
|
||||||
|
|
||||||
|
// unstaged file
|
||||||
|
if gitFileStatus.Worktree == git.Modified {
|
||||||
|
return fmt.Sprintf("%s-unstaged", g.commitID), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// newly staged file
|
||||||
|
if gitFileStatus.Staging == git.Added {
|
||||||
|
return "staged", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// staged file
|
||||||
|
if gitFileStatus.Staging == git.Modified {
|
||||||
|
return fmt.Sprintf("%s-staged", g.commitID), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if file is committed already
|
||||||
|
oc, err := g.repo.Log(&git.LogOptions{FileName: &gitFilePath})
|
||||||
|
if err != nil {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = oc.Next()
|
||||||
|
defer oc.Close()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// File not tracked by git and/or not committed
|
||||||
|
return "untracked", nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// File tracked by git and has been committed
|
||||||
|
return g.commitID, nil
|
||||||
|
}
|
||||||
@@ -19,6 +19,7 @@ package utils
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
@@ -295,3 +296,19 @@ func DeleteRoleBinding(ctx context.Context, k8sClient *kubernetes.Clientset, rol
|
|||||||
func MakeSAMapKey(saName, saNamespace string) string {
|
func MakeSAMapKey(saName, saNamespace string) string {
|
||||||
return fmt.Sprintf("%s-%s", saName, saNamespace)
|
return fmt.Sprintf("%s-%s", saName, saNamespace)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetSecretConfigMapGetterCR() string {
|
||||||
|
releaseName := os.Getenv("HELM_RELEASE_NAME")
|
||||||
|
if len(releaseName) > 0 {
|
||||||
|
return fmt.Sprintf("%s-secret-configmap-getter", releaseName)
|
||||||
|
}
|
||||||
|
return "secret-configmap-getter"
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPackageGetterCR() string {
|
||||||
|
releaseName := os.Getenv("HELM_RELEASE_NAME")
|
||||||
|
if len(releaseName) > 0 {
|
||||||
|
return fmt.Sprintf("%s-package-getter", releaseName)
|
||||||
|
}
|
||||||
|
return "package-getter"
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ url: %s
|
|||||||
---
|
---
|
||||||
`
|
`
|
||||||
|
|
||||||
const baseURL = "/docs/fission-cli/"
|
const baseURL = "/docs/reference/fission-cli/"
|
||||||
|
|
||||||
var filePrepender = func(filename string) string {
|
var filePrepender = func(filename string) string {
|
||||||
name := filepath.Base(filename)
|
name := filepath.Base(filename)
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
---
|
---
|
||||||
title: "Fission CRD Reference"
|
title: "Fission CRD Reference"
|
||||||
weight: 99
|
weight: 8
|
||||||
description: >
|
description: >
|
||||||
Fission Custom Resources Definition(CRD) Reference
|
Fission Custom Resources Definition(CRD) Reference
|
||||||
url: /docs/crd-reference/
|
|
||||||
---
|
---
|
||||||
|
|||||||
Reference in New Issue
Block a user