Compare commits
29
Commits
v1.15.0
...
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 | ||
|
|
327275d1a4 | ||
|
|
37609ad7ec | ||
|
|
bf8c01cff0 | ||
|
|
f635f6d16a | ||
|
|
223892f121 | ||
|
|
76f51e977d | ||
|
|
73784f39ac | ||
|
|
35a5397a05 | ||
|
|
fe0c1e3683 | ||
|
|
24737e8958 |
+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,27 @@
|
|||||||
# 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)
|
||||||
|
|
||||||
|
[Full Changelog](https://github.com/fission/fission/compare/v1.15.0-rc2...v1.15.0)
|
||||||
|
|
||||||
|
**Merged pull requests:**
|
||||||
|
|
||||||
|
- Update alpine base image to 3.14.3 and security fixes [\#2266](https://github.com/fission/fission/pull/2266) ([sanketsudake](https://github.com/sanketsudake))
|
||||||
|
- Update chart logo with svg image [\#2264](https://github.com/fission/fission/pull/2264) ([sanketsudake](https://github.com/sanketsudake))
|
||||||
|
|
||||||
## [v1.15.0-rc2](https://github.com/fission/fission/tree/v1.15.0-rc2) (2021-11-11)
|
## [v1.15.0-rc2](https://github.com/fission/fission/tree/v1.15.0-rc2) (2021-11-11)
|
||||||
|
|
||||||
[Full Changelog](https://github.com/fission/fission/compare/v1.15.0-rc1...v1.15.0-rc2)
|
[Full Changelog](https://github.com/fission/fission/compare/v1.15.0-rc1...v1.15.0-rc2)
|
||||||
|
|||||||
@@ -80,7 +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:
|
||||||
|
# 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
|
||||||
|
cp tools/crd-ref-docs/header.md crd_docs.md
|
||||||
|
cat out.md >> crd_docs.md && rm out.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.0
|
version: v1.16.0-rc1
|
||||||
appVersion: v1.15.0
|
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.0
|
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.0
|
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.0
|
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.
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ var (
|
|||||||
func Run(ctx context.Context, logger *zap.Logger) {
|
func Run(ctx context.Context, logger *zap.Logger) {
|
||||||
flag.Usage = fetcherUsage
|
flag.Usage = fetcherUsage
|
||||||
collectorEndpoint := flag.String("jaeger-collector-endpoint", "", "")
|
collectorEndpoint := flag.String("jaeger-collector-endpoint", "", "")
|
||||||
specializeOnStart := flag.Bool("specialize-on-startup", false, "Flag to activate specialize process at pod starup")
|
specializeOnStart := flag.Bool("specialize-on-startup", false, "Flag to activate specialize process at pod startup")
|
||||||
specializePayload := flag.String("specialize-request", "", "JSON payload for specialize request")
|
specializePayload := flag.String("specialize-request", "", "JSON payload for specialize request")
|
||||||
secretDir := flag.String("secret-dir", "", "Path to shared secrets directory")
|
secretDir := flag.String("secret-dir", "", "Path to shared secrets directory")
|
||||||
configDir := flag.String("cfgmap-dir", "", "Path to shared configmap directory")
|
configDir := flag.String("cfgmap-dir", "", "Path to shared configmap directory")
|
||||||
|
|||||||
@@ -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...)
|
||||||
|
|||||||
@@ -96,21 +96,21 @@ func (client *PreUpgradeTaskClient) LatestSchemaApplied(ctx context.Context) err
|
|||||||
client.logger.Info("Checking if user has applied the latest CRDs")
|
client.logger.Info("Checking if user has applied the latest CRDs")
|
||||||
funcCRD := client.GetFunctionCRD(ctx)
|
funcCRD := client.GetFunctionCRD(ctx)
|
||||||
if funcCRD == nil {
|
if funcCRD == nil {
|
||||||
return errors.New("Could not get the Function CRD")
|
return fmt.Errorf("could not get the Function CRD")
|
||||||
}
|
}
|
||||||
// Any new field added in Function spec can be checked here provided the substring matches the description in CRD Validation of the field
|
// Any new field added in Function spec can be checked here provided the substring matches the description in CRD Validation of the field
|
||||||
if !strings.Contains(funcCRD.Spec.String(), "RequestsPerPod") || !strings.Contains(funcCRD.Spec.String(), "OnceOnly") || !strings.Contains(funcCRD.Spec.String(), "PodSpec") {
|
if !strings.Contains(funcCRD.Spec.String(), "RequestsPerPod") || !strings.Contains(funcCRD.Spec.String(), "OnceOnly") || !strings.Contains(funcCRD.Spec.String(), "PodSpec") {
|
||||||
return errors.New("Apply the newer CRDs before upgrading")
|
return fmt.Errorf("could not find RequestPerPod/OnceOnly/PodSpec in Function CRD")
|
||||||
}
|
}
|
||||||
|
|
||||||
mqtCRD := client.GetMqtCRD(ctx)
|
mqtCRD := client.GetMqtCRD(ctx)
|
||||||
if mqtCRD == nil {
|
if mqtCRD == nil {
|
||||||
return errors.New("Could not get the MQT CRD")
|
return fmt.Errorf("could not get the MQT CRD")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Any new field added in MQT spec can be checked here provided the substring matches the description in CRD Validation of the field
|
// Any new field added in MQT spec can be checked here provided the substring matches the description in CRD Validation of the field
|
||||||
if !strings.Contains(mqtCRD.Spec.String(), "PodSpec") {
|
if !strings.Contains(mqtCRD.Spec.String(), "PodSpec") {
|
||||||
return errors.New("Apply the newer CRDs before upgrading")
|
return fmt.Errorf("could not find PodSpec field in MQT CRD")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ Options:
|
|||||||
|
|
||||||
err = crdBackedClient.LatestSchemaApplied(ctx)
|
err = crdBackedClient.LatestSchemaApplied(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatal("New CRDs are not applied")
|
logger.Fatal("New CRDs are not applied", zap.Error(err))
|
||||||
}
|
}
|
||||||
crdBackedClient.VerifyFunctionSpecReferences(ctx)
|
crdBackedClient.VerifyFunctionSpecReferences(ctx)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9399,7 +9399,7 @@ spec:
|
|||||||
format: int64
|
format: int64
|
||||||
type: integer
|
type: integer
|
||||||
version:
|
version:
|
||||||
description: "Version is the Environment API version \n Version \"1\" allows user to run code snippet in a file and it's supported by most of environments except tensorflow-serving. \n Version \"2\" supports downloading and compiling user function if source archive is not empty. \n Version \"3\" is almost the same with v2, but you're able to control the size of pre-warm pool of the environment."
|
description: "Version is the Environment API version \n Version \"1\" allows user to run code snippet in a file, and it's supported by most of the environments except tensorflow-serving. \n Version \"2\" supports downloading and compiling user function if source archive is not empty. \n Version \"3\" is almost the same with v2, but you're able to control the size of pre-warm pool of the environment."
|
||||||
type: integer
|
type: integer
|
||||||
required:
|
required:
|
||||||
- runtime
|
- runtime
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ spec:
|
|||||||
description: ExecutionStrategy specifies low-level parameters for function execution, such as the number of instances.
|
description: ExecutionStrategy specifies low-level parameters for function execution, such as the number of instances.
|
||||||
properties:
|
properties:
|
||||||
ExecutorType:
|
ExecutorType:
|
||||||
description: "ExecutorType is the executor type of a function used. Defaults to \"poolmgr\". \n Available value: - poolmgr - newdeploy - container"
|
description: "ExecutorType is the executor type of function used. Defaults to \"poolmgr\". \n Available value: - poolmgr - newdeploy - container"
|
||||||
type: string
|
type: string
|
||||||
MaxScale:
|
MaxScale:
|
||||||
description: This is only for newdeploy to set up maximum replicas of deployment.
|
description: This is only for newdeploy to set up maximum replicas of deployment.
|
||||||
@@ -57,7 +57,7 @@ spec:
|
|||||||
type: integer
|
type: integer
|
||||||
type: object
|
type: object
|
||||||
StrategyType:
|
StrategyType:
|
||||||
description: StrategyType is the strategy type of a function. Now it only supports 'execution'.
|
description: StrategyType is the strategy type of function. Now it only supports 'execution'.
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
concurrency:
|
concurrency:
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ spec:
|
|||||||
description: HTTPTriggerSpec is for router to expose user functions at the given URL path.
|
description: HTTPTriggerSpec is for router to expose user functions at the given URL path.
|
||||||
properties:
|
properties:
|
||||||
createingress:
|
createingress:
|
||||||
description: If CreateIngress is true, router will create a ingress definition.
|
description: If CreateIngress is true, router will create an ingress definition.
|
||||||
type: boolean
|
type: boolean
|
||||||
functionref:
|
functionref:
|
||||||
description: FunctionReference is a reference to the target function.
|
description: FunctionReference is a reference to the target function.
|
||||||
@@ -58,12 +58,12 @@ spec:
|
|||||||
description: 'TODO: remove this field since we have IngressConfig already Deprecated: the original idea of this field is not for setting Ingress. Since we have IngressConfig now, remove Host after couple releases.'
|
description: 'TODO: remove this field since we have IngressConfig already Deprecated: the original idea of this field is not for setting Ingress. Since we have IngressConfig now, remove Host after couple releases.'
|
||||||
type: string
|
type: string
|
||||||
ingressconfig:
|
ingressconfig:
|
||||||
description: 'TODO: make IngressConfig a independent Fission resource IngressConfig for router to set up Ingress.'
|
description: 'TODO: make IngressConfig an independent Fission resource IngressConfig for router to set up Ingress.'
|
||||||
properties:
|
properties:
|
||||||
annotations:
|
annotations:
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
type: string
|
type: string
|
||||||
description: Annotations will be add to metadata when creating Ingress.
|
description: Annotations will be added to metadata when creating Ingress.
|
||||||
nullable: true
|
nullable: true
|
||||||
type: object
|
type: object
|
||||||
host:
|
host:
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ spec:
|
|||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
literal:
|
literal:
|
||||||
description: Literal contents of the package. Can be used for encoding packages below TODO (256KB?) size.
|
description: Literal contents of the package. Can be used for encoding packages below TODO (256 KB?) size.
|
||||||
format: byte
|
format: byte
|
||||||
type: string
|
type: string
|
||||||
type:
|
type:
|
||||||
@@ -84,7 +84,7 @@ spec:
|
|||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
literal:
|
literal:
|
||||||
description: Literal contents of the package. Can be used for encoding packages below TODO (256KB?) size.
|
description: Literal contents of the package. Can be used for encoding packages below TODO (256 KB?) size.
|
||||||
format: byte
|
format: byte
|
||||||
type: string
|
type: string
|
||||||
type:
|
type:
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ require (
|
|||||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
|
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
|
||||||
github.com/Shopify/sarama v1.30.0
|
github.com/Shopify/sarama v1.30.0
|
||||||
github.com/blend/go-sdk v1.20211025.3 // indirect
|
github.com/blend/go-sdk v1.20211025.3 // indirect
|
||||||
github.com/bsm/sarama-cluster v2.1.15+incompatible
|
|
||||||
github.com/containerd/continuity v0.2.1 // indirect
|
github.com/containerd/continuity v0.2.1 // indirect
|
||||||
github.com/dchest/uniuri v0.0.0-20200228104902-7aecb25e1fe5
|
github.com/dchest/uniuri v0.0.0-20200228104902-7aecb25e1fe5
|
||||||
github.com/docker/go-connections v0.4.0 // indirect
|
github.com/docker/go-connections v0.4.0 // indirect
|
||||||
@@ -23,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
|
||||||
@@ -36,7 +36,7 @@ require (
|
|||||||
github.com/nats-io/stan.go v0.10.0
|
github.com/nats-io/stan.go v0.10.0
|
||||||
github.com/nwaples/rardecode v1.1.2 // indirect
|
github.com/nwaples/rardecode v1.1.2 // indirect
|
||||||
github.com/opencontainers/image-spec v1.0.2 // indirect
|
github.com/opencontainers/image-spec v1.0.2 // indirect
|
||||||
github.com/opencontainers/runc v1.0.2 // indirect
|
github.com/opencontainers/runc v1.0.3 // indirect
|
||||||
github.com/ory/dockertest v3.3.5+incompatible
|
github.com/ory/dockertest v3.3.5+incompatible
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/prometheus/client_golang v1.11.0
|
github.com/prometheus/client_golang v1.11.0
|
||||||
|
|||||||
@@ -187,8 +187,6 @@ github.com/blend/sentry-go v1.0.1/go.mod h1:hgyX3WXen2YBiA0NitlfsXsvS+9ly2YlEBmm
|
|||||||
github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c=
|
github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c=
|
||||||
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
|
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
|
||||||
github.com/bonitoo-io/go-sql-bigquery v0.3.4-1.4.0/go.mod h1:J4Y6YJm0qTWB9aFziB7cPeSyc6dOZFyJdteSeybVpXQ=
|
github.com/bonitoo-io/go-sql-bigquery v0.3.4-1.4.0/go.mod h1:J4Y6YJm0qTWB9aFziB7cPeSyc6dOZFyJdteSeybVpXQ=
|
||||||
github.com/bsm/sarama-cluster v2.1.15+incompatible h1:RkV6WiNRnqEEbp81druK8zYhmnIgdOjqSVi0+9Cnl2A=
|
|
||||||
github.com/bsm/sarama-cluster v2.1.15+incompatible/go.mod h1:r7ao+4tTNXvWm+VRpRJchr2kQhqxgmAp2iEX5W96gMM=
|
|
||||||
github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34=
|
github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34=
|
||||||
github.com/cactus/go-statsd-client/statsd v0.0.0-20191106001114-12b4e2b38748/go.mod h1:l/bIBLeOl9eX+wxJAzxS4TveKRtAqlyDpHjhkfO0MEI=
|
github.com/cactus/go-statsd-client/statsd v0.0.0-20191106001114-12b4e2b38748/go.mod h1:l/bIBLeOl9eX+wxJAzxS4TveKRtAqlyDpHjhkfO0MEI=
|
||||||
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
||||||
@@ -494,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=
|
||||||
@@ -971,8 +972,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8
|
|||||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||||
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
|
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
|
||||||
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
github.com/opencontainers/runc v1.0.2 h1:opHZMaswlyxz1OuGpBE53Dwe4/xF7EZTY0A2L/FpCOg=
|
github.com/opencontainers/runc v1.0.3 h1:1hbqejyQWCJBvtKAfdO0b1FmaEf2z/bxnjqbARass5k=
|
||||||
github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
github.com/opencontainers/runc v1.0.3/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
|
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
|
||||||
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
|
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ kube::swagger::gen_types_swagger_doc() {
|
|||||||
|
|
||||||
echo "Generating swagger type docs for ${group_version} at ${gv_dir}"
|
echo "Generating swagger type docs for ${group_version} at ${gv_dir}"
|
||||||
|
|
||||||
sed 's/YEAR/2017/' hack/boilerplate.txt > "$TMPFILE"
|
# sed 's/YEAR/2017/' hack/boilerplate.txt > "$TMPFILE"
|
||||||
echo "package ${group_version##*/}" >> "$TMPFILE"
|
echo "package ${group_version##*/}" >> "$TMPFILE"
|
||||||
cat >> "$TMPFILE" <<EOF
|
cat >> "$TMPFILE" <<EOF
|
||||||
// This file contains a collection of methods that can be used from go-restful to
|
// This file contains a collection of methods that can be used from go-restful to
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -22,10 +22,6 @@ limitations under the License.
|
|||||||
// +groupName=fission.io
|
// +groupName=fission.io
|
||||||
// +groupGoName=core
|
// +groupGoName=core
|
||||||
//
|
//
|
||||||
// In order not to break the backward compatibility, keep coreV1 types stay
|
|
||||||
// at "fission.io" group instead of moving them to "core.fission.io".
|
|
||||||
// If the value of group is different from the one we register, the
|
|
||||||
// CRD client will not be able to get anything from the API server.
|
|
||||||
package v1
|
package v1
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
+22
-10
@@ -229,7 +229,7 @@ type (
|
|||||||
// externally.
|
// externally.
|
||||||
ArchiveType string
|
ArchiveType string
|
||||||
|
|
||||||
// Archive contains or references a collection of source or
|
// Archive contains or references a collection of sources or
|
||||||
// binary files.
|
// binary files.
|
||||||
Archive struct {
|
Archive struct {
|
||||||
// Type defines how the package is specified: literal or URL.
|
// Type defines how the package is specified: literal or URL.
|
||||||
@@ -240,7 +240,7 @@ type (
|
|||||||
Type ArchiveType `json:"type,omitempty"`
|
Type ArchiveType `json:"type,omitempty"`
|
||||||
|
|
||||||
// Literal contents of the package. Can be used for
|
// Literal contents of the package. Can be used for
|
||||||
// encoding packages below TODO (256KB?) size.
|
// encoding packages below TODO (256 KB?) size.
|
||||||
// +optional
|
// +optional
|
||||||
Literal []byte `json:"literal,omitempty"`
|
Literal []byte `json:"literal,omitempty"`
|
||||||
|
|
||||||
@@ -254,7 +254,7 @@ type (
|
|||||||
Checksum Checksum `json:"checksum,omitempty"`
|
Checksum Checksum `json:"checksum,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnvironmentReference is a reference to a environment.
|
// EnvironmentReference is a reference to an environment.
|
||||||
EnvironmentReference struct {
|
EnvironmentReference struct {
|
||||||
Namespace string `json:"namespace"`
|
Namespace string `json:"namespace"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
@@ -431,7 +431,7 @@ type (
|
|||||||
// +optional
|
// +optional
|
||||||
ExecutionStrategy ExecutionStrategy `json:"ExecutionStrategy"`
|
ExecutionStrategy ExecutionStrategy `json:"ExecutionStrategy"`
|
||||||
|
|
||||||
// StrategyType is the strategy type of a function.
|
// StrategyType is the strategy type of function.
|
||||||
// Now it only supports 'execution'.
|
// Now it only supports 'execution'.
|
||||||
// +optional
|
// +optional
|
||||||
StrategyType StrategyType `json:"StrategyType"`
|
StrategyType StrategyType `json:"StrategyType"`
|
||||||
@@ -450,7 +450,7 @@ type (
|
|||||||
// and resources allocated to the function pod.
|
// and resources allocated to the function pod.
|
||||||
ExecutionStrategy struct {
|
ExecutionStrategy struct {
|
||||||
|
|
||||||
// ExecutorType is the executor type of a function used. Defaults to "poolmgr".
|
// ExecutorType is the executor type of function used. Defaults to "poolmgr".
|
||||||
//
|
//
|
||||||
// Available value:
|
// Available value:
|
||||||
// - poolmgr
|
// - poolmgr
|
||||||
@@ -578,8 +578,8 @@ type (
|
|||||||
EnvironmentSpec struct {
|
EnvironmentSpec struct {
|
||||||
// Version is the Environment API version
|
// Version is the Environment API version
|
||||||
//
|
//
|
||||||
// Version "1" allows user to run code snippet in a file and
|
// Version "1" allows user to run code snippet in a file, and
|
||||||
// it's supported by most of environments except tensorflow-serving.
|
// it's supported by most of the environments except tensorflow-serving.
|
||||||
//
|
//
|
||||||
// Version "2" supports downloading and compiling user function if source archive is not empty.
|
// Version "2" supports downloading and compiling user function if source archive is not empty.
|
||||||
//
|
//
|
||||||
@@ -681,11 +681,11 @@ type (
|
|||||||
// FunctionReference is a reference to the target function.
|
// FunctionReference is a reference to the target function.
|
||||||
FunctionReference FunctionReference `json:"functionref"`
|
FunctionReference FunctionReference `json:"functionref"`
|
||||||
|
|
||||||
// If CreateIngress is true, router will create a ingress definition.
|
// If CreateIngress is true, router will create an ingress definition.
|
||||||
// +optional
|
// +optional
|
||||||
CreateIngress bool `json:"createingress"`
|
CreateIngress bool `json:"createingress"`
|
||||||
|
|
||||||
// TODO: make IngressConfig a independent Fission resource
|
// TODO: make IngressConfig an independent Fission resource
|
||||||
// IngressConfig for router to set up Ingress.
|
// IngressConfig for router to set up Ingress.
|
||||||
// +optional
|
// +optional
|
||||||
IngressConfig IngressConfig `json:"ingressconfig"`
|
IngressConfig IngressConfig `json:"ingressconfig"`
|
||||||
@@ -693,7 +693,7 @@ type (
|
|||||||
|
|
||||||
// IngressConfig is for router to set up Ingress.
|
// IngressConfig is for router to set up Ingress.
|
||||||
IngressConfig struct {
|
IngressConfig struct {
|
||||||
// Annotations will be add to metadata when creating Ingress.
|
// Annotations will be added to metadata when creating Ingress.
|
||||||
// +optional
|
// +optional
|
||||||
// +nullable
|
// +nullable
|
||||||
Annotations map[string]string `json:"annotations"`
|
Annotations map[string]string `json:"annotations"`
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -457,7 +457,7 @@ func (config IngressConfig) Validate() error {
|
|||||||
|
|
||||||
// In Ingress, to accept requests from all host, the host field will
|
// In Ingress, to accept requests from all host, the host field will
|
||||||
// be an empty string instead of "*" shown in kubectl. The router replaces
|
// be an empty string instead of "*" shown in kubectl. The router replaces
|
||||||
// the asterisk with "" when creating/updateing the Ingress, so here we
|
// the asterisk with "" when creating/updating the Ingress, so here we
|
||||||
// skip the check if the Host is equal to "*".
|
// skip the check if the Host is equal to "*".
|
||||||
if len(config.Host) > 0 && config.Host != "*" {
|
if len(config.Host) > 0 && config.Host != "*" {
|
||||||
if strings.Contains(config.Host, "*") {
|
if strings.Contains(config.Host, "*") {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -1,18 +1,3 @@
|
|||||||
/*
|
|
||||||
Copyright 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 v1
|
package v1
|
||||||
|
|
||||||
// This file contains a collection of methods that can be used from go-restful to
|
// This file contains a collection of methods that can be used from go-restful to
|
||||||
@@ -26,9 +11,9 @@ package v1
|
|||||||
// Those methods can be generated by using hack/update-swagger-docs.sh
|
// Those methods can be generated by using hack/update-swagger-docs.sh
|
||||||
// AUTO-GENERATED FUNCTIONS START HERE
|
// AUTO-GENERATED FUNCTIONS START HERE
|
||||||
var map_Archive = map[string]string{
|
var map_Archive = map[string]string{
|
||||||
"": "Archive contains or references a collection of source or binary files.",
|
"": "Archive contains or references a collection of sources or binary files.",
|
||||||
"type": "Type defines how the package is specified: literal or URL. Available value:\n - literal\n - url",
|
"type": "Type defines how the package is specified: literal or URL. Available value:\n - literal\n - url",
|
||||||
"literal": "Literal contents of the package. Can be used for encoding packages below TODO (256KB?) size.",
|
"literal": "Literal contents of the package. Can be used for encoding packages below TODO (256 KB?) size.",
|
||||||
"url": "URL references a package.",
|
"url": "URL references a package.",
|
||||||
"checksum": "Checksum ensures the integrity of packages referenced by URL. Ignored for literals.",
|
"checksum": "Checksum ensures the integrity of packages referenced by URL. Ignored for literals.",
|
||||||
}
|
}
|
||||||
@@ -37,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.",
|
||||||
@@ -120,7 +113,7 @@ func (EnvironmentList) SwaggerDoc() map[string]string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var map_EnvironmentReference = map[string]string{
|
var map_EnvironmentReference = map[string]string{
|
||||||
"": "EnvironmentReference is a reference to a environment.",
|
"": "EnvironmentReference is a reference to an environment.",
|
||||||
}
|
}
|
||||||
|
|
||||||
func (EnvironmentReference) SwaggerDoc() map[string]string {
|
func (EnvironmentReference) SwaggerDoc() map[string]string {
|
||||||
@@ -129,7 +122,7 @@ func (EnvironmentReference) SwaggerDoc() map[string]string {
|
|||||||
|
|
||||||
var map_EnvironmentSpec = map[string]string{
|
var map_EnvironmentSpec = map[string]string{
|
||||||
"": "EnvironmentSpec contains with builder, runtime and some other related environment settings.",
|
"": "EnvironmentSpec contains with builder, runtime and some other related environment settings.",
|
||||||
"version": "Version is the Environment API version\n\nVersion \"1\" allows user to run code snippet in a file and it's supported by most of environments except tensorflow-serving.\n\nVersion \"2\" supports downloading and compiling user function if source archive is not empty.\n\nVersion \"3\" is almost the same with v2, but you're able to control the size of pre-warm pool of the environment.",
|
"version": "Version is the Environment API version\n\nVersion \"1\" allows user to run code snippet in a file, and it's supported by most of the environments except tensorflow-serving.\n\nVersion \"2\" supports downloading and compiling user function if source archive is not empty.\n\nVersion \"3\" is almost the same with v2, but you're able to control the size of pre-warm pool of the environment.",
|
||||||
"runtime": "Runtime is configuration for running function, like container image etc.",
|
"runtime": "Runtime is configuration for running function, like container image etc.",
|
||||||
"builder": "(Optional) Builder is configuration for builder manager to launch environment builder to build source code into deployable binary.",
|
"builder": "(Optional) Builder is configuration for builder manager to launch environment builder to build source code into deployable binary.",
|
||||||
"allowedFunctionsPerContainer": "(Optional) defaults to 'single'. Fission workflow uses 'infinite' to load multiple functions in one function pod. Available value: - single - infinite",
|
"allowedFunctionsPerContainer": "(Optional) defaults to 'single'. Fission workflow uses 'infinite' to load multiple functions in one function pod. Available value: - single - infinite",
|
||||||
@@ -147,7 +140,7 @@ func (EnvironmentSpec) SwaggerDoc() map[string]string {
|
|||||||
|
|
||||||
var map_ExecutionStrategy = map[string]string{
|
var map_ExecutionStrategy = map[string]string{
|
||||||
"": "ExecutionStrategy specifies low-level parameters for function execution, such as the number of instances.\n\nMinScale affects the cold start behavior for a function. If MinScale is 0 then the deployment is created on first invocation of function and is good for requests of asynchronous nature. If MinScale is greater than 0 then MinScale number of pods are created at the time of creation of function. This ensures faster response during first invocation at the cost of consuming resources.\n\nMaxScale is the maximum number of pods that function will scale to based on TargetCPUPercent and resources allocated to the function pod.",
|
"": "ExecutionStrategy specifies low-level parameters for function execution, such as the number of instances.\n\nMinScale affects the cold start behavior for a function. If MinScale is 0 then the deployment is created on first invocation of function and is good for requests of asynchronous nature. If MinScale is greater than 0 then MinScale number of pods are created at the time of creation of function. This ensures faster response during first invocation at the cost of consuming resources.\n\nMaxScale is the maximum number of pods that function will scale to based on TargetCPUPercent and resources allocated to the function pod.",
|
||||||
"ExecutorType": "ExecutorType is the executor type of a function used. Defaults to \"poolmgr\".\n\nAvailable value:\n - poolmgr\n - newdeploy\n - container",
|
"ExecutorType": "ExecutorType is the executor type of function used. Defaults to \"poolmgr\".\n\nAvailable value:\n - poolmgr\n - newdeploy\n - container",
|
||||||
"MinScale": "This is only for newdeploy to set up minimum replicas of deployment.",
|
"MinScale": "This is only for newdeploy to set up minimum replicas of deployment.",
|
||||||
"MaxScale": "This is only for newdeploy to set up maximum replicas of deployment.",
|
"MaxScale": "This is only for newdeploy to set up maximum replicas of deployment.",
|
||||||
"TargetCPUPercent": "This is only for newdeploy to set up target CPU utilization of HPA.",
|
"TargetCPUPercent": "This is only for newdeploy to set up target CPU utilization of HPA.",
|
||||||
@@ -240,7 +233,7 @@ var map_HTTPTriggerSpec = map[string]string{
|
|||||||
"method": "Use Methods instead of Method. This field is going to be deprecated in a future release HTTP method to access a function.",
|
"method": "Use Methods instead of Method. This field is going to be deprecated in a future release HTTP method to access a function.",
|
||||||
"methods": "HTTP methods to access a function",
|
"methods": "HTTP methods to access a function",
|
||||||
"functionref": "FunctionReference is a reference to the target function.",
|
"functionref": "FunctionReference is a reference to the target function.",
|
||||||
"createingress": "If CreateIngress is true, router will create a ingress definition.",
|
"createingress": "If CreateIngress is true, router will create an ingress definition.",
|
||||||
"ingressconfig": "IngressConfig for router to set up Ingress.",
|
"ingressconfig": "IngressConfig for router to set up Ingress.",
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,7 +243,7 @@ func (HTTPTriggerSpec) SwaggerDoc() map[string]string {
|
|||||||
|
|
||||||
var map_IngressConfig = map[string]string{
|
var map_IngressConfig = map[string]string{
|
||||||
"": "IngressConfig is for router to set up Ingress.",
|
"": "IngressConfig is for router to set up Ingress.",
|
||||||
"annotations": "Annotations will be add to metadata when creating Ingress.",
|
"annotations": "Annotations will be added to metadata when creating Ingress.",
|
||||||
"path": "Path is for path matching. The format of path depends on what ingress controller you used.",
|
"path": "Path is for path matching. The format of path depends on what ingress controller you used.",
|
||||||
"host": "Host is for ingress controller to apply rules. If host is empty or \"*\", the rule applies to all inbound HTTP traffic.",
|
"host": "Host is for ingress controller to apply rules. If host is empty or \"*\", the rule applies to all inbound HTTP traffic.",
|
||||||
"tls": "TLS is for user to specify a Secret that contains TLS key and certificate. The domain name in the key and crt must match the value of Host field.",
|
"tls": "TLS is for user to specify a Secret that contains TLS key and certificate. The domain name in the key and crt must match the value of Host field.",
|
||||||
@@ -263,7 +256,7 @@ func (IngressConfig) SwaggerDoc() map[string]string {
|
|||||||
var map_InvokeStrategy = map[string]string{
|
var map_InvokeStrategy = map[string]string{
|
||||||
"": "InvokeStrategy is a set of controls over how the function executes. It affects the performance and resource usage of the function.\n\nAn InvokeStrategy is of one of two types: ExecutionStrategy, which controls low-level parameters such as which ExecutorType to use, when to autoscale, minimum and maximum number of running instances, etc. A higher-level AbstractInvokeStrategy will also be supported; this strategy would specify the target request rate of the function, the target latency statistics, and the target cost (in terms of compute resources).",
|
"": "InvokeStrategy is a set of controls over how the function executes. It affects the performance and resource usage of the function.\n\nAn InvokeStrategy is of one of two types: ExecutionStrategy, which controls low-level parameters such as which ExecutorType to use, when to autoscale, minimum and maximum number of running instances, etc. A higher-level AbstractInvokeStrategy will also be supported; this strategy would specify the target request rate of the function, the target latency statistics, and the target cost (in terms of compute resources).",
|
||||||
"ExecutionStrategy": "ExecutionStrategy specifies low-level parameters for function execution, such as the number of instances.",
|
"ExecutionStrategy": "ExecutionStrategy specifies low-level parameters for function execution, such as the number of instances.",
|
||||||
"StrategyType": "StrategyType is the strategy type of a function. Now it only supports 'execution'.",
|
"StrategyType": "StrategyType is the strategy type of function. Now it only supports 'execution'.",
|
||||||
}
|
}
|
||||||
|
|
||||||
func (InvokeStrategy) SwaggerDoc() map[string]string {
|
func (InvokeStrategy) SwaggerDoc() map[string]string {
|
||||||
@@ -385,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.",
|
||||||
|
|||||||
@@ -165,9 +165,9 @@ 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 wont 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),
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ func MakeCanaryConfigMgr(logger *zap.Logger, fissionClient *crd.FissionClient, k
|
|||||||
|
|
||||||
_, err := url.Parse(prometheusSvc)
|
_, err := url.Parse(prometheusSvc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Errorf("prometheus service url not found/invalid, cant create canary config manager: %v", prometheusSvc)
|
return nil, errors.Errorf("prometheus service url not found/invalid, can't create canary config manager: %v", prometheusSvc)
|
||||||
}
|
}
|
||||||
|
|
||||||
promClient, err := MakePrometheusClient(logger, prometheusSvc)
|
promClient, err := MakePrometheusClient(logger, prometheusSvc)
|
||||||
@@ -140,7 +140,7 @@ func (canaryCfgMgr *canaryConfigMgr) addCanaryConfig(canaryConfig *fv1.CanaryCon
|
|||||||
// for each canary config, create a ticker with increment interval
|
// for each canary config, create a ticker with increment interval
|
||||||
interval, err := time.ParseDuration(canaryConfig.Spec.WeightIncrementDuration)
|
interval, err := time.ParseDuration(canaryConfig.Spec.WeightIncrementDuration)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
canaryCfgMgr.logger.Error("error parsing duration - cant proceed with this canaryConfig",
|
canaryCfgMgr.logger.Error("error parsing duration - can't proceed with this canaryConfig",
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.String("duration", canaryConfig.Spec.WeightIncrementDuration),
|
zap.String("duration", canaryConfig.Spec.WeightIncrementDuration),
|
||||||
zap.String("name", canaryConfig.ObjectMeta.Name),
|
zap.String("name", canaryConfig.ObjectMeta.Name),
|
||||||
@@ -351,7 +351,7 @@ func (canaryCfgMgr *canaryConfigMgr) RollForwardOrBack(canaryConfig *fv1.CanaryC
|
|||||||
err = canaryCfgMgr.updateCanaryConfigStatusWithRetries(canaryConfig.ObjectMeta.Name, canaryConfig.ObjectMeta.Namespace,
|
err = canaryCfgMgr.updateCanaryConfigStatusWithRetries(canaryConfig.ObjectMeta.Name, canaryConfig.ObjectMeta.Namespace,
|
||||||
fv1.CanaryConfigStatusSucceeded)
|
fv1.CanaryConfigStatusSucceeded)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// cant do much after max retries other than logging it.
|
// can't do much after max retries other than logging it.
|
||||||
canaryCfgMgr.logger.Error("error updating canary config after max retries",
|
canaryCfgMgr.logger.Error("error updating canary config after max retries",
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.String("name", canaryConfig.ObjectMeta.Name),
|
zap.String("name", canaryConfig.ObjectMeta.Name),
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ func (a *API) WatchApiCreate(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO check for duplicate watches
|
// TODO check for duplicate watches
|
||||||
// TODO check for duplicate watches -> we probably wont need it?
|
// TODO check for duplicate watches -> we probably won't need it?
|
||||||
// check if namespace exists, if not create it.
|
// check if namespace exists, if not create it.
|
||||||
err = a.createNsIfNotExists(r.Context(), watch.ObjectMeta.Namespace)
|
err = a.createNsIfNotExists(r.Context(), watch.ObjectMeta.Namespace)
|
||||||
if err != nil {
|
if err != 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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -299,7 +299,7 @@ func StartExecutor(ctx context.Context, logger *zap.Logger, functionNamespace st
|
|||||||
funcInformer, pkgInformer, envInformer,
|
funcInformer, pkgInformer, envInformer,
|
||||||
gpmPodInformer, gpmRsInformer)
|
gpmPodInformer, gpmRsInformer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "pool manager creation faied")
|
return errors.Wrap(err, "pool manager creation failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
ndmInformerFactory, err := utils.GetInformerFactoryByExecutor(kubernetesClient, fv1.ExecutorTypeNewdeploy, time.Minute*30)
|
ndmInformerFactory, err := utils.GetInformerFactoryByExecutor(kubernetesClient, fv1.ExecutorTypeNewdeploy, time.Minute*30)
|
||||||
@@ -315,7 +315,7 @@ func StartExecutor(ctx context.Context, logger *zap.Logger, functionNamespace st
|
|||||||
funcInformer, envInformer,
|
funcInformer, envInformer,
|
||||||
ndmDeplInformer, ndmSvcInformer)
|
ndmDeplInformer, ndmSvcInformer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "new deploy manager creation faied")
|
return errors.Wrap(err, "new deploy manager creation failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
cnmInformerFactory, err := utils.GetInformerFactoryByExecutor(kubernetesClient, fv1.ExecutorTypeContainer, time.Minute*30)
|
cnmInformerFactory, err := utils.GetInformerFactoryByExecutor(kubernetesClient, fv1.ExecutorTypeContainer, time.Minute*30)
|
||||||
@@ -330,7 +330,7 @@ func StartExecutor(ctx context.Context, logger *zap.Logger, functionNamespace st
|
|||||||
functionNamespace, executorInstanceID, funcInformer,
|
functionNamespace, executorInstanceID, funcInformer,
|
||||||
cnmDeplInformer, cnmSvcInformer)
|
cnmDeplInformer, cnmSvcInformer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "container manager creation faied")
|
return errors.Wrap(err, "container manager creation failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
executorTypes := make(map[fv1.ExecutorType]executortype.ExecutorType)
|
executorTypes := make(map[fv1.ExecutorType]executortype.ExecutorType)
|
||||||
|
|||||||
@@ -664,7 +664,7 @@ func (caaf *Container) getObjName(fn *fv1.Function) string {
|
|||||||
functionMetadata = functionMetadata + "-" + fn.ObjectMeta.Namespace
|
functionMetadata = functionMetadata + "-" + fn.ObjectMeta.Namespace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// contructed name should be 63 characters long, as it is a valid k8s name
|
// constructed name should be 63 characters long, as it is a valid k8s name
|
||||||
// functionMetadata should be 35 characters long, as we take 17 characters from functionUid
|
// functionMetadata should be 35 characters long, as we take 17 characters from functionUid
|
||||||
// with newdeploy 10 character prefix
|
// with newdeploy 10 character prefix
|
||||||
return strings.ToLower(fmt.Sprintf("container-%s-%s", functionMetadata, uid))
|
return strings.ToLower(fmt.Sprintf("container-%s-%s", functionMetadata, uid))
|
||||||
|
|||||||
@@ -55,40 +55,12 @@ func (cn *Container) createOrGetDeployment(ctx context.Context, fn *fv1.Function
|
|||||||
}
|
}
|
||||||
|
|
||||||
existingDepl, err := cn.kubernetesClient.AppsV1().Deployments(deployNamespace).Get(ctx, deployName, metav1.GetOptions{})
|
existingDepl, err := cn.kubernetesClient.AppsV1().Deployments(deployNamespace).Get(ctx, deployName, metav1.GetOptions{})
|
||||||
if err == nil {
|
if err != nil && !k8s_err.IsNotFound(err) {
|
||||||
// Try to adopt orphan deployment created by the old executor.
|
return nil, err
|
||||||
if existingDepl.Annotations[fv1.EXECUTOR_INSTANCEID_LABEL] != cn.instanceID {
|
}
|
||||||
existingDepl.Annotations = deployment.Annotations
|
|
||||||
existingDepl.Labels = deployment.Labels
|
|
||||||
existingDepl.Spec.Template.Spec.Containers = deployment.Spec.Template.Spec.Containers
|
|
||||||
existingDepl.Spec.Template.Spec.ServiceAccountName = deployment.Spec.Template.Spec.ServiceAccountName
|
|
||||||
existingDepl.Spec.Template.Spec.TerminationGracePeriodSeconds = deployment.Spec.Template.Spec.TerminationGracePeriodSeconds
|
|
||||||
|
|
||||||
// Update with the latest deployment spec. Kubernetes will trigger
|
// Create new deployment if one does not previously exist
|
||||||
// rolling update if spec is different from the one in the cluster.
|
if k8s_err.IsNotFound(err) {
|
||||||
existingDepl, err = cn.kubernetesClient.AppsV1().Deployments(deployNamespace).Update(ctx, existingDepl, metav1.UpdateOptions{})
|
|
||||||
if err != nil {
|
|
||||||
logger.Warn("error adopting cn", zap.Error(err),
|
|
||||||
zap.String("cn", deployName), zap.String("ns", deployNamespace))
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// In this case, we just return without waiting for it for fast bootstraping.
|
|
||||||
return existingDepl, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if *existingDepl.Spec.Replicas < minScale {
|
|
||||||
err = cn.scaleDeployment(ctx, existingDepl.Namespace, existingDepl.Name, minScale)
|
|
||||||
if err != nil {
|
|
||||||
logger.Error("error scaling up function deployment", zap.Error(err), zap.String("function", fn.ObjectMeta.Name))
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if existingDepl.Status.AvailableReplicas < minScale {
|
|
||||||
existingDepl, err = cn.waitForDeploy(ctx, existingDepl, minScale, specializationTimeout)
|
|
||||||
}
|
|
||||||
|
|
||||||
return existingDepl, err
|
|
||||||
} else if k8s_err.IsNotFound(err) {
|
|
||||||
depl, err := cn.kubernetesClient.AppsV1().Deployments(deployNamespace).Create(ctx, deployment, metav1.CreateOptions{})
|
depl, err := cn.kubernetesClient.AppsV1().Deployments(deployNamespace).Create(ctx, deployment, metav1.CreateOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if k8s_err.IsAlreadyExists(err) {
|
if k8s_err.IsAlreadyExists(err) {
|
||||||
@@ -109,7 +81,39 @@ func (cn *Container) createOrGetDeployment(ctx context.Context, fn *fv1.Function
|
|||||||
}
|
}
|
||||||
return depl, err
|
return depl, err
|
||||||
}
|
}
|
||||||
return nil, err
|
|
||||||
|
// Try to adopt orphan deployment created by the old executor.
|
||||||
|
if existingDepl.Annotations[fv1.EXECUTOR_INSTANCEID_LABEL] != cn.instanceID {
|
||||||
|
existingDepl.Annotations = deployment.Annotations
|
||||||
|
existingDepl.Labels = deployment.Labels
|
||||||
|
existingDepl.Spec.Template.Spec.Containers = deployment.Spec.Template.Spec.Containers
|
||||||
|
existingDepl.Spec.Template.Spec.ServiceAccountName = deployment.Spec.Template.Spec.ServiceAccountName
|
||||||
|
existingDepl.Spec.Template.Spec.TerminationGracePeriodSeconds = deployment.Spec.Template.Spec.TerminationGracePeriodSeconds
|
||||||
|
|
||||||
|
// Update with the latest deployment spec. Kubernetes will trigger
|
||||||
|
// rolling update if spec is different from the one in the cluster.
|
||||||
|
existingDepl, err = cn.kubernetesClient.AppsV1().Deployments(deployNamespace).Update(ctx, existingDepl, metav1.UpdateOptions{})
|
||||||
|
if err != nil {
|
||||||
|
logger.Warn("error adopting cn", zap.Error(err),
|
||||||
|
zap.String("cn", deployName), zap.String("ns", deployNamespace))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// In this case, we just return without waiting for it for fast bootstraping.
|
||||||
|
return existingDepl, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if *existingDepl.Spec.Replicas < minScale {
|
||||||
|
err = cn.scaleDeployment(ctx, existingDepl.Namespace, existingDepl.Name, minScale)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("error scaling up function deployment", zap.Error(err), zap.String("function", fn.ObjectMeta.Name))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if existingDepl.Status.AvailableReplicas < minScale {
|
||||||
|
existingDepl, err = cn.waitForDeploy(ctx, existingDepl, minScale, specializationTimeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
return existingDepl, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cn *Container) updateDeployment(ctx context.Context, deployment *appsv1.Deployment, ns string) error {
|
func (cn *Container) updateDeployment(ctx context.Context, deployment *appsv1.Deployment, ns string) error {
|
||||||
@@ -119,7 +123,7 @@ func (cn *Container) updateDeployment(ctx context.Context, deployment *appsv1.De
|
|||||||
|
|
||||||
func (cn *Container) deleteDeployment(ctx context.Context, ns string, name string) error {
|
func (cn *Container) deleteDeployment(ctx context.Context, ns string, name string) error {
|
||||||
// DeletePropagationBackground deletes the object immediately and dependent are deleted later
|
// DeletePropagationBackground deletes the object immediately and dependent are deleted later
|
||||||
// DeletePropagationForeground not advisable; it marks for deleteion and API can still serve those objects
|
// DeletePropagationForeground not advisable; it marks for deletion and API can still serve those objects
|
||||||
deletePropagation := metav1.DeletePropagationBackground
|
deletePropagation := metav1.DeletePropagationBackground
|
||||||
return cn.kubernetesClient.AppsV1().Deployments(ns).Delete(ctx, name, metav1.DeleteOptions{
|
return cn.kubernetesClient.AppsV1().Deployments(ns).Delete(ctx, name, metav1.DeleteOptions{
|
||||||
PropagationPolicy: &deletePropagation,
|
PropagationPolicy: &deletePropagation,
|
||||||
@@ -168,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),
|
||||||
@@ -174,7 +174,7 @@ func (deploy *NewDeploy) updateDeployment(ctx context.Context, deployment *appsv
|
|||||||
|
|
||||||
func (deploy *NewDeploy) deleteDeployment(ctx context.Context, ns string, name string) error {
|
func (deploy *NewDeploy) deleteDeployment(ctx context.Context, ns string, name string) error {
|
||||||
// DeletePropagationBackground deletes the object immediately and dependent are deleted later
|
// DeletePropagationBackground deletes the object immediately and dependent are deleted later
|
||||||
// DeletePropagationForeground not advisable; it marks for deleteion and API can still serve those objects
|
// DeletePropagationForeground not advisable; it marks for deletion and API can still serve those objects
|
||||||
deletePropagation := metav1.DeletePropagationBackground
|
deletePropagation := metav1.DeletePropagationBackground
|
||||||
return deploy.kubernetesClient.AppsV1().Deployments(ns).Delete(ctx, name, metav1.DeleteOptions{
|
return deploy.kubernetesClient.AppsV1().Deployments(ns).Delete(ctx, name, metav1.DeleteOptions{
|
||||||
PropagationPolicy: &deletePropagation,
|
PropagationPolicy: &deletePropagation,
|
||||||
|
|||||||
@@ -712,7 +712,7 @@ func (deploy *NewDeploy) getObjName(fn *fv1.Function) string {
|
|||||||
functionMetadata = functionMetadata + "-" + fn.ObjectMeta.Namespace
|
functionMetadata = functionMetadata + "-" + fn.ObjectMeta.Namespace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// contructed name should be 63 characters long, as it is a valid k8s name
|
// constructed name should be 63 characters long, as it is a valid k8s name
|
||||||
// functionMetadata should be 35 characters long, as we take 17 characters from functionUid
|
// functionMetadata should be 35 characters long, as we take 17 characters from functionUid
|
||||||
// with newdeploy 10 character prefix
|
// with newdeploy 10 character prefix
|
||||||
return strings.ToLower(fmt.Sprintf("newdeploy-%s-%s", functionMetadata, uid))
|
return strings.ToLower(fmt.Sprintf("newdeploy-%s-%s", functionMetadata, uid))
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ func (gp *GenericPool) getDeployAnnotations(env *fv1.Environment) map[string]str
|
|||||||
func (gp *GenericPool) checkMetricsApi() bool {
|
func (gp *GenericPool) checkMetricsApi() bool {
|
||||||
apiGroups, err := gp.metricsClient.DiscoveryClient.ServerGroups()
|
apiGroups, err := gp.metricsClient.DiscoveryClient.ServerGroups()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gp.logger.Error("faied to discover API groups", zap.Error(err))
|
gp.logger.Error("failed to discover API groups", zap.Error(err))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return utils.SupportedMetricsAPIVersionAvailable(apiGroups)
|
return utils.SupportedMetricsAPIVersionAvailable(apiGroups)
|
||||||
@@ -263,7 +263,13 @@ func (gp *GenericPool) choosePod(ctx context.Context, newLabels map[string]strin
|
|||||||
pod, err := gp.readyPodLister.Pods(namespace).Get(name)
|
pod, err := gp.readyPodLister.Pods(namespace).Get(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("fetching object from store failed", zap.String("key", key), zap.Error(err))
|
logger.Error("fetching object from store failed", zap.String("key", key), zap.Error(err))
|
||||||
return "", nil, err
|
gp.readyPodQueue.Done(key)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if utils.IsPodTerminated(pod) {
|
||||||
|
logger.Error("pod is terminated", zap.String("key", key))
|
||||||
|
gp.readyPodQueue.Done(key)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
if !utils.IsReadyPod(pod) {
|
if !utils.IsReadyPod(pod) {
|
||||||
logger.Warn("pod not ready, pod will be checked again", zap.String("key", key), zap.Duration("delay", expoDelay))
|
logger.Warn("pod not ready, pod will be checked again", zap.String("key", key), zap.Duration("delay", expoDelay))
|
||||||
|
|||||||
@@ -690,7 +690,7 @@ func (gpm *GenericPoolManager) WebsocketStartEventChecker(kubeClient *kubernetes
|
|||||||
if fsvc, ok := gpm.fsCache.PodToFsvc.Load(strings.TrimSuffix(podName[0], ".")); ok {
|
if fsvc, ok := gpm.fsCache.PodToFsvc.Load(strings.TrimSuffix(podName[0], ".")); ok {
|
||||||
fsvc, ok := fsvc.(*fscache.FuncSvc)
|
fsvc, ok := fsvc.(*fscache.FuncSvc)
|
||||||
if !ok {
|
if !ok {
|
||||||
gpm.logger.Error("could not covert item from PodToFsvc")
|
gpm.logger.Error("could not convert item from PodToFsvc")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
gpm.fsCache.WebsocketFsvc.Store(fsvc.Name, true)
|
gpm.fsCache.WebsocketFsvc.Store(fsvc.Name, true)
|
||||||
@@ -731,7 +731,7 @@ func (gpm *GenericPoolManager) NoActiveConnectionEventChecker(kubeClient *kubern
|
|||||||
if fsvc, ok := gpm.fsCache.PodToFsvc.Load(strings.TrimSuffix(podName[0], ".")); ok {
|
if fsvc, ok := gpm.fsCache.PodToFsvc.Load(strings.TrimSuffix(podName[0], ".")); ok {
|
||||||
fsvc, ok := fsvc.(*fscache.FuncSvc)
|
fsvc, ok := fsvc.(*fscache.FuncSvc)
|
||||||
if !ok {
|
if !ok {
|
||||||
gpm.logger.Error("could not covert value from PodToFsvc")
|
gpm.logger.Error("could not convert value from PodToFsvc")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ func (p *PoolPodController) handleRSDelete(obj interface{}) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
tombstone, ok := obj.(k8sCache.DeletedFinalStateUnknown)
|
tombstone, ok := obj.(k8sCache.DeletedFinalStateUnknown)
|
||||||
if !ok {
|
if !ok {
|
||||||
p.logger.Error("couldnt get object from tombstone", zap.Any("obj", obj))
|
p.logger.Error("couldn't get object from tombstone", zap.Any("obj", obj))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
rs, ok = tombstone.Obj.(*apps.ReplicaSet)
|
rs, ok = tombstone.Obj.(*apps.ReplicaSet)
|
||||||
@@ -411,7 +411,7 @@ func (p *PoolPodController) spCleanupPodQueueProcessFunc() bool {
|
|||||||
p.gpm.fsCache.DeleteFunctionSvc(ctx, fsvc)
|
p.gpm.fsCache.DeleteFunctionSvc(ctx, fsvc)
|
||||||
p.gpm.fsCache.DeleteEntry(fsvc)
|
p.gpm.fsCache.DeleteEntry(fsvc)
|
||||||
} else {
|
} else {
|
||||||
p.logger.Error("could not covert item from PodToFsvc", zap.String("key", key))
|
p.logger.Error("could not convert item from PodToFsvc", zap.String("key", key))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = p.kubernetesClient.CoreV1().Pods(p.namespace).Delete(context.TODO(), pod.Name, metav1.DeleteOptions{})
|
err = p.kubernetesClient.CoreV1().Pods(p.namespace).Delete(context.TODO(), pod.Name, metav1.DeleteOptions{})
|
||||||
|
|||||||
@@ -401,7 +401,7 @@ func (fsc *FunctionServiceCache) ListOld(age time.Duration) ([]*FuncSvc, error)
|
|||||||
return resp.objects, resp.error
|
return resp.objects, resp.error
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListOldForPool returns a list of aged function serices in cache for pooling.
|
// ListOldForPool returns a list of aged function services in cache for pooling.
|
||||||
func (fsc *FunctionServiceCache) ListOldForPool(age time.Duration) ([]*FuncSvc, error) {
|
func (fsc *FunctionServiceCache) ListOldForPool(age time.Duration) ([]*FuncSvc, error) {
|
||||||
responseChannel := make(chan *fscResponse)
|
responseChannel := make(chan *fscResponse)
|
||||||
fsc.requestChannel <- &fscRequest{
|
fsc.requestChannel <- &fscRequest{
|
||||||
|
|||||||
@@ -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"`
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ func (cfg *Config) NewSpecializeRequest(fn *fv1.Function, env *fv1.Environment)
|
|||||||
if env.Spec.AllowedFunctionsPerContainer == fv1.AllowedFunctionsPerContainerInfinite {
|
if env.Spec.AllowedFunctionsPerContainer == fv1.AllowedFunctionsPerContainerInfinite {
|
||||||
// workflow loads multiple functions into one function pod,
|
// workflow loads multiple functions into one function pod,
|
||||||
// we have to use a Function UID to separate the function code
|
// we have to use a Function UID to separate the function code
|
||||||
// to avoid overwritting.
|
// to avoid overwriting.
|
||||||
targetFilename = string(fn.ObjectMeta.UID)
|
targetFilename = string(fn.ObjectMeta.UID)
|
||||||
} else {
|
} else {
|
||||||
// set target file name to fix pattern for
|
// set target file name to fix pattern for
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ type (
|
|||||||
// to "/".
|
// to "/".
|
||||||
URL string `json:"url"`
|
URL string `json:"url"`
|
||||||
|
|
||||||
// Metatdata
|
// Metadata
|
||||||
FunctionMetadata *metav1.ObjectMeta
|
FunctionMetadata *metav1.ObjectMeta
|
||||||
|
|
||||||
EnvVersion int `json:"envVersion"`
|
EnvVersion int `json:"envVersion"`
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -45,7 +45,7 @@ type (
|
|||||||
Usage string
|
Usage string
|
||||||
DefaultValue interface{}
|
DefaultValue interface{}
|
||||||
|
|
||||||
// If a flag is marked as deprecated, it will hided from
|
// If a flag is marked as deprecated, it will hidden from
|
||||||
// the help message automatically. Hence, a flag cannot be
|
// the help message automatically. Hence, a flag cannot be
|
||||||
// marked as hidden and deprecated at the same time.
|
// marked as hidden and deprecated at the same time.
|
||||||
Hidden bool
|
Hidden bool
|
||||||
@@ -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 ingored 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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package kafka
|
package kafka
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -28,7 +29,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/Shopify/sarama"
|
"github.com/Shopify/sarama"
|
||||||
cluster "github.com/bsm/sarama-cluster"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
@@ -65,6 +65,183 @@ type (
|
|||||||
Factory struct{}
|
Factory struct{}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type MqtConsumerGroupHandler struct {
|
||||||
|
version sarama.KafkaVersion
|
||||||
|
logger *zap.Logger
|
||||||
|
trigger *fv1.MessageQueueTrigger
|
||||||
|
fissionHeaders map[string]string
|
||||||
|
producer sarama.SyncProducer
|
||||||
|
fnUrl string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMqtConsumerGroupHandler(version sarama.KafkaVersion,
|
||||||
|
logger *zap.Logger,
|
||||||
|
trigger *fv1.MessageQueueTrigger,
|
||||||
|
producer sarama.SyncProducer,
|
||||||
|
routerUrl string) MqtConsumerGroupHandler {
|
||||||
|
ch := MqtConsumerGroupHandler{
|
||||||
|
version: version,
|
||||||
|
logger: logger,
|
||||||
|
trigger: trigger,
|
||||||
|
producer: producer,
|
||||||
|
}
|
||||||
|
// Support other function ref types
|
||||||
|
if ch.trigger.Spec.FunctionReference.Type != fv1.FunctionReferenceTypeFunctionName {
|
||||||
|
ch.logger.Fatal("unsupported function reference type for trigger",
|
||||||
|
zap.Any("function_reference_type", ch.trigger.Spec.FunctionReference.Type),
|
||||||
|
zap.String("trigger", ch.trigger.ObjectMeta.Name))
|
||||||
|
}
|
||||||
|
// Generate the Headers
|
||||||
|
ch.fissionHeaders = map[string]string{
|
||||||
|
"X-Fission-MQTrigger-Topic": ch.trigger.Spec.Topic,
|
||||||
|
"X-Fission-MQTrigger-RespTopic": ch.trigger.Spec.ResponseTopic,
|
||||||
|
"X-Fission-MQTrigger-ErrorTopic": ch.trigger.Spec.ErrorTopic,
|
||||||
|
"Content-Type": ch.trigger.Spec.ContentType,
|
||||||
|
}
|
||||||
|
ch.fnUrl = routerUrl + "/" + strings.TrimPrefix(utils.UrlForFunction(ch.trigger.Spec.FunctionReference.Name, ch.trigger.ObjectMeta.Namespace), "/")
|
||||||
|
ch.logger.Debug("function HTTP URL", zap.String("url", ch.fnUrl))
|
||||||
|
return ch
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ch MqtConsumerGroupHandler) Setup(sarama.ConsumerGroupSession) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ch MqtConsumerGroupHandler) Cleanup(sarama.ConsumerGroupSession) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ch MqtConsumerGroupHandler) ConsumeClaim(session sarama.ConsumerGroupSession, claim sarama.ConsumerGroupClaim) error {
|
||||||
|
for msg := range claim.Messages() {
|
||||||
|
ch.kafkaMsgHandler(session, msg)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//func (ch *MqtConsumerGroupHandler) kafkaMsgHandler(kafka *Kafka, producer sarama.SyncProducer, trigger *fv1.MessageQueueTrigger, msg *sarama.ConsumerMessage, consumer *cluster.Consumer) {
|
||||||
|
|
||||||
|
func (ch *MqtConsumerGroupHandler) kafkaMsgHandler(session sarama.ConsumerGroupSession, msg *sarama.ConsumerMessage) {
|
||||||
|
var value string = string(msg.Value[:])
|
||||||
|
|
||||||
|
// Create request
|
||||||
|
req, err := http.NewRequest("POST", ch.fnUrl, strings.NewReader(value))
|
||||||
|
if err != nil {
|
||||||
|
ch.logger.Error("failed to create HTTP request to invoke function",
|
||||||
|
zap.Error(err),
|
||||||
|
zap.String("function_url", ch.fnUrl))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the headers came from Kafka record
|
||||||
|
// Using Header.Add() as msg.Headers may have keys with more than one value
|
||||||
|
if ch.version.IsAtLeast(sarama.V0_11_0_0) {
|
||||||
|
for _, h := range msg.Headers {
|
||||||
|
req.Header.Add(string(h.Key), string(h.Value))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ch.logger.Warn("headers are not supported by current Kafka version, needs v0.11+: no record headers to add in HTTP request",
|
||||||
|
zap.Any("current_version", ch.version))
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range ch.fissionHeaders {
|
||||||
|
req.Header.Set(k, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make the request
|
||||||
|
var resp *http.Response
|
||||||
|
for attempt := 0; attempt <= ch.trigger.Spec.MaxRetries; attempt++ {
|
||||||
|
// Make the request
|
||||||
|
resp, err = http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
ch.logger.Error("sending function invocation request failed",
|
||||||
|
zap.Error(err),
|
||||||
|
zap.String("function_url", ch.fnUrl),
|
||||||
|
zap.String("trigger", ch.trigger.ObjectMeta.Name))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err == nil && resp.StatusCode == http.StatusOK {
|
||||||
|
// Success, quit retrying
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
generateErrorHeaders := func(errString string) []sarama.RecordHeader {
|
||||||
|
var errorHeaders []sarama.RecordHeader
|
||||||
|
if ch.version.IsAtLeast(sarama.V0_11_0_0) {
|
||||||
|
if count, ok := errorMessageMap[errString]; ok {
|
||||||
|
errorMessageMap[errString] = count + 1
|
||||||
|
} else {
|
||||||
|
errorMessageMap[errString] = 1
|
||||||
|
}
|
||||||
|
errorHeaders = append(errorHeaders, sarama.RecordHeader{Key: []byte("MessageSource"), Value: []byte(ch.trigger.Spec.Topic)})
|
||||||
|
errorHeaders = append(errorHeaders, sarama.RecordHeader{Key: []byte("RecycleCounter"), Value: []byte(strconv.Itoa(errorMessageMap[errString]))})
|
||||||
|
}
|
||||||
|
return errorHeaders
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp == nil {
|
||||||
|
errorString := fmt.Sprintf("request exceed retries: %v", ch.trigger.Spec.MaxRetries)
|
||||||
|
errorHeaders := generateErrorHeaders(errorString)
|
||||||
|
errorHandler(ch.logger, ch.trigger, ch.producer, ch.fnUrl,
|
||||||
|
fmt.Errorf(errorString), errorHeaders)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
|
||||||
|
ch.logger.Debug("got response from function invocation",
|
||||||
|
zap.String("function_url", ch.fnUrl),
|
||||||
|
zap.String("trigger", ch.trigger.ObjectMeta.Name),
|
||||||
|
zap.String("body", string(body)))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
errorString := "request body error: " + string(body)
|
||||||
|
errorHeaders := generateErrorHeaders(errorString)
|
||||||
|
errorHandler(ch.logger, ch.trigger, ch.producer, ch.fnUrl,
|
||||||
|
errors.Wrapf(err, errorString), errorHeaders)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
errorString := fmt.Sprintf("request returned failure: %v, request body error: %v", resp.StatusCode, body)
|
||||||
|
errorHeaders := generateErrorHeaders(errorString)
|
||||||
|
errorHandler(ch.logger, ch.trigger, ch.producer, ch.fnUrl,
|
||||||
|
fmt.Errorf("request returned failure: %v", resp.StatusCode), errorHeaders)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(ch.trigger.Spec.ResponseTopic) > 0 {
|
||||||
|
// Generate Kafka record headers
|
||||||
|
var kafkaRecordHeaders []sarama.RecordHeader
|
||||||
|
if ch.version.IsAtLeast(sarama.V0_11_0_0) {
|
||||||
|
for k, v := range resp.Header {
|
||||||
|
// One key may have multiple values
|
||||||
|
for _, v := range v {
|
||||||
|
kafkaRecordHeaders = append(kafkaRecordHeaders, sarama.RecordHeader{Key: []byte(k), Value: []byte(v)})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ch.logger.Warn("headers are not supported by current Kafka version, needs v0.11+: no record headers to add in HTTP request",
|
||||||
|
zap.Any("current_version", ch.version))
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err := ch.producer.SendMessage(&sarama.ProducerMessage{
|
||||||
|
Topic: ch.trigger.Spec.ResponseTopic,
|
||||||
|
Value: sarama.StringEncoder(body),
|
||||||
|
Headers: kafkaRecordHeaders,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ch.logger.Warn("failed to publish response body from function invocation to topic",
|
||||||
|
zap.Error(err),
|
||||||
|
zap.String("topic", ch.trigger.Spec.Topic),
|
||||||
|
zap.String("function_url", ch.fnUrl))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
session.MarkMessage(msg, "")
|
||||||
|
}
|
||||||
|
|
||||||
func (factory *Factory) Create(logger *zap.Logger, mqCfg messageQueue.Config, routerUrl string) (messageQueue.MessageQueue, error) {
|
func (factory *Factory) Create(logger *zap.Logger, mqCfg messageQueue.Config, routerUrl string) (messageQueue.MessageQueue, error) {
|
||||||
return New(logger, mqCfg, routerUrl)
|
return New(logger, mqCfg, routerUrl)
|
||||||
}
|
}
|
||||||
@@ -116,10 +293,9 @@ func (kafka Kafka) Subscribe(trigger *fv1.MessageQueueTrigger) (messageQueue.Sub
|
|||||||
kafka.logger.Info("brokers set", zap.Strings("brokers", kafka.brokers))
|
kafka.logger.Info("brokers set", zap.Strings("brokers", kafka.brokers))
|
||||||
|
|
||||||
// Create new consumer
|
// Create new consumer
|
||||||
consumerConfig := cluster.NewConfig()
|
consumerConfig := sarama.NewConfig()
|
||||||
consumerConfig.Consumer.Return.Errors = true
|
consumerConfig.Consumer.Return.Errors = true
|
||||||
consumerConfig.Group.Return.Notifications = true
|
consumerConfig.Version = kafka.version
|
||||||
consumerConfig.Config.Version = kafka.version
|
|
||||||
|
|
||||||
// Create new producer
|
// Create new producer
|
||||||
producerConfig := sarama.NewConfig()
|
producerConfig := sarama.NewConfig()
|
||||||
@@ -142,7 +318,8 @@ func (kafka Kafka) Subscribe(trigger *fv1.MessageQueueTrigger) (messageQueue.Sub
|
|||||||
consumerConfig.Net.TLS.Config = tlsConfig
|
consumerConfig.Net.TLS.Config = tlsConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
consumer, err := cluster.NewConsumer(kafka.brokers, string(trigger.ObjectMeta.UID), []string{trigger.Spec.Topic}, consumerConfig)
|
consumer, err := sarama.NewConsumerGroup(kafka.brokers, string(trigger.ObjectMeta.UID), consumerConfig)
|
||||||
|
// consumer, err := cluster.NewConsumer(kafka.brokers, string(trigger.ObjectMeta.UID), []string{trigger.Spec.Topic}, consumerConfig)
|
||||||
kafka.logger.Info("created a new consumer", zap.Strings("brokers", kafka.brokers),
|
kafka.logger.Info("created a new consumer", zap.Strings("brokers", kafka.brokers),
|
||||||
zap.String("input topic", trigger.Spec.Topic),
|
zap.String("input topic", trigger.Spec.Topic),
|
||||||
zap.String("output topic", trigger.Spec.ResponseTopic),
|
zap.String("output topic", trigger.Spec.ResponseTopic),
|
||||||
@@ -174,18 +351,14 @@ func (kafka Kafka) Subscribe(trigger *fv1.MessageQueueTrigger) (messageQueue.Sub
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// consume notifications
|
ch := NewMqtConsumerGroupHandler(kafka.version, kafka.logger, trigger, producer, kafka.routerUrl)
|
||||||
go func() {
|
|
||||||
for ntf := range consumer.Notifications() {
|
|
||||||
kafka.logger.Info("consumer notification", zap.Any("notification", ntf))
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// consume messages
|
// consume messages
|
||||||
go func() {
|
go func() {
|
||||||
for msg := range consumer.Messages() {
|
topic := []string{trigger.Spec.Topic}
|
||||||
kafka.logger.Debug("calling message handler", zap.String("message", string(msg.Value[:])))
|
ctx := context.Background()
|
||||||
go kafkaMsgHandler(&kafka, producer, trigger, msg, consumer)
|
err = consumer.Consume(ctx, topic, ch)
|
||||||
|
if err != nil {
|
||||||
|
kafka.logger.Error("consumer error", zap.Error(err))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -217,146 +390,7 @@ func (kafka Kafka) getTLSConfig() (*tls.Config, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (kafka Kafka) Unsubscribe(subscription messageQueue.Subscription) error {
|
func (kafka Kafka) Unsubscribe(subscription messageQueue.Subscription) error {
|
||||||
return subscription.(*cluster.Consumer).Close()
|
return subscription.(sarama.ConsumerGroup).Close()
|
||||||
}
|
|
||||||
|
|
||||||
func kafkaMsgHandler(kafka *Kafka, producer sarama.SyncProducer, trigger *fv1.MessageQueueTrigger, msg *sarama.ConsumerMessage, consumer *cluster.Consumer) {
|
|
||||||
var value string = string(msg.Value[:])
|
|
||||||
// Support other function ref types
|
|
||||||
if trigger.Spec.FunctionReference.Type != fv1.FunctionReferenceTypeFunctionName {
|
|
||||||
kafka.logger.Fatal("unsupported function reference type for trigger",
|
|
||||||
zap.Any("function_reference_type", trigger.Spec.FunctionReference.Type),
|
|
||||||
zap.String("trigger", trigger.ObjectMeta.Name))
|
|
||||||
}
|
|
||||||
|
|
||||||
url := kafka.routerUrl + "/" + strings.TrimPrefix(utils.UrlForFunction(trigger.Spec.FunctionReference.Name, trigger.ObjectMeta.Namespace), "/")
|
|
||||||
kafka.logger.Debug("making HTTP request", zap.String("url", url))
|
|
||||||
|
|
||||||
// Generate the Headers
|
|
||||||
fissionHeaders := map[string]string{
|
|
||||||
"X-Fission-MQTrigger-Topic": trigger.Spec.Topic,
|
|
||||||
"X-Fission-MQTrigger-RespTopic": trigger.Spec.ResponseTopic,
|
|
||||||
"X-Fission-MQTrigger-ErrorTopic": trigger.Spec.ErrorTopic,
|
|
||||||
"Content-Type": trigger.Spec.ContentType,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create request
|
|
||||||
req, err := http.NewRequest("POST", url, strings.NewReader(value))
|
|
||||||
if err != nil {
|
|
||||||
kafka.logger.Error("failed to create HTTP request to invoke function",
|
|
||||||
zap.Error(err),
|
|
||||||
zap.String("function_url", url))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the headers came from Kafka record
|
|
||||||
// Using Header.Add() as msg.Headers may have keys with more than one value
|
|
||||||
if kafka.version.IsAtLeast(sarama.V0_11_0_0) {
|
|
||||||
for _, h := range msg.Headers {
|
|
||||||
req.Header.Add(string(h.Key), string(h.Value))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
kafka.logger.Warn("headers are not supported by current Kafka version, needs v0.11+: no record headers to add in HTTP request",
|
|
||||||
zap.Any("current_version", kafka.version))
|
|
||||||
}
|
|
||||||
|
|
||||||
for k, v := range fissionHeaders {
|
|
||||||
req.Header.Set(k, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make the request
|
|
||||||
var resp *http.Response
|
|
||||||
for attempt := 0; attempt <= trigger.Spec.MaxRetries; attempt++ {
|
|
||||||
// Make the request
|
|
||||||
resp, err = http.DefaultClient.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
kafka.logger.Error("sending function invocation request failed",
|
|
||||||
zap.Error(err),
|
|
||||||
zap.String("function_url", url),
|
|
||||||
zap.String("trigger", trigger.ObjectMeta.Name))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if resp == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err == nil && resp.StatusCode == http.StatusOK {
|
|
||||||
// Success, quit retrying
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
generateErrorHeaders := func(errString string) []sarama.RecordHeader {
|
|
||||||
var errorHeaders []sarama.RecordHeader
|
|
||||||
if kafka.version.IsAtLeast(sarama.V0_11_0_0) {
|
|
||||||
if count, ok := errorMessageMap[errString]; ok {
|
|
||||||
errorMessageMap[errString] = count + 1
|
|
||||||
} else {
|
|
||||||
errorMessageMap[errString] = 1
|
|
||||||
}
|
|
||||||
errorHeaders = append(errorHeaders, sarama.RecordHeader{Key: []byte("MessageSource"), Value: []byte(trigger.Spec.Topic)})
|
|
||||||
errorHeaders = append(errorHeaders, sarama.RecordHeader{Key: []byte("RecycleCounter"), Value: []byte(strconv.Itoa(errorMessageMap[errString]))})
|
|
||||||
}
|
|
||||||
return errorHeaders
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp == nil {
|
|
||||||
errorString := fmt.Sprintf("request exceed retries: %v", trigger.Spec.MaxRetries)
|
|
||||||
errorHeaders := generateErrorHeaders(errorString)
|
|
||||||
errorHandler(kafka.logger, trigger, producer, url,
|
|
||||||
fmt.Errorf(errorString), errorHeaders)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
body, err := io.ReadAll(resp.Body)
|
|
||||||
|
|
||||||
kafka.logger.Debug("got response from function invocation",
|
|
||||||
zap.String("function_url", url),
|
|
||||||
zap.String("trigger", trigger.ObjectMeta.Name),
|
|
||||||
zap.String("body", string(body)))
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
errorString := "request body error: " + string(body)
|
|
||||||
errorHeaders := generateErrorHeaders(errorString)
|
|
||||||
errorHandler(kafka.logger, trigger, producer, url,
|
|
||||||
errors.Wrapf(err, errorString), errorHeaders)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if resp.StatusCode != 200 {
|
|
||||||
errorString := fmt.Sprintf("request returned failure: %v, request body error: %v", resp.StatusCode, body)
|
|
||||||
errorHeaders := generateErrorHeaders(errorString)
|
|
||||||
errorHandler(kafka.logger, trigger, producer, url,
|
|
||||||
fmt.Errorf("request returned failure: %v", resp.StatusCode), errorHeaders)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(trigger.Spec.ResponseTopic) > 0 {
|
|
||||||
// Generate Kafka record headers
|
|
||||||
var kafkaRecordHeaders []sarama.RecordHeader
|
|
||||||
if kafka.version.IsAtLeast(sarama.V0_11_0_0) {
|
|
||||||
for k, v := range resp.Header {
|
|
||||||
// One key may have multiple values
|
|
||||||
for _, v := range v {
|
|
||||||
kafkaRecordHeaders = append(kafkaRecordHeaders, sarama.RecordHeader{Key: []byte(k), Value: []byte(v)})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
kafka.logger.Warn("headers are not supported by current Kafka version, needs v0.11+: no record headers to add in HTTP request",
|
|
||||||
zap.Any("current_version", kafka.version))
|
|
||||||
}
|
|
||||||
|
|
||||||
_, _, err := producer.SendMessage(&sarama.ProducerMessage{
|
|
||||||
Topic: trigger.Spec.ResponseTopic,
|
|
||||||
Value: sarama.StringEncoder(body),
|
|
||||||
Headers: kafkaRecordHeaders,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
kafka.logger.Warn("failed to publish response body from function invocation to topic",
|
|
||||||
zap.Error(err),
|
|
||||||
zap.String("topic", trigger.Spec.Topic),
|
|
||||||
zap.String("function_url", url))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
consumer.MarkOffset(msg, "") // mark message as processed
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func errorHandler(logger *zap.Logger, trigger *fv1.MessageQueueTrigger, producer sarama.SyncProducer, funcUrl string, err error, errorTopicHeaders []sarama.RecordHeader) {
|
func errorHandler(logger *zap.Logger, trigger *fv1.MessageQueueTrigger, producer sarama.SyncProducer, funcUrl string, err error, errorTopicHeaders []sarama.RecordHeader) {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ func (c *Cache) service() {
|
|||||||
}
|
}
|
||||||
if value.activeRequests == 0 {
|
if value.activeRequests == 0 {
|
||||||
if debugLevel {
|
if debugLevel {
|
||||||
otelUtils.LoggerWithTraceID(req.ctx, c.logger).Debug("Function service with no acitve requests", zap.String("function", key1.(string)), zap.String("address", key2.(string)), zap.Int("activeRequests", value.activeRequests))
|
otelUtils.LoggerWithTraceID(req.ctx, c.logger).Debug("Function service with no active requests", zap.String("function", key1.(string)), zap.String("address", key2.(string)), zap.Int("activeRequests", value.activeRequests))
|
||||||
}
|
}
|
||||||
vals = append(vals, value.val)
|
vals = append(vals, value.val)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ func (w *fakeCloseReadCloser) RealClose() error {
|
|||||||
// In such a case, the RoundTripper will retry requests against the new address and give up after maxRetries.
|
// In such a case, the RoundTripper will retry requests against the new address and give up after maxRetries.
|
||||||
// However, the subsequent http call for this function will ensure the cache is invalidated.
|
// However, the subsequent http call for this function will ensure the cache is invalidated.
|
||||||
//
|
//
|
||||||
// If GetServiceForFunction returns an error or if RoundTripper exits with an error, it get's translated into 502
|
// If GetServiceForFunction returns an error or if RoundTripper exits with an error, it gets translated into 502
|
||||||
// inside ServeHttp function of the reverseProxy.
|
// inside ServeHttp function of the reverseProxy.
|
||||||
// Earlier, GetServiceForFunction was called inside handler function and fission explicitly set http status code to 500
|
// Earlier, GetServiceForFunction was called inside handler function and fission explicitly set http status code to 500
|
||||||
// if it returned an error.
|
// if it returned an error.
|
||||||
|
|||||||
+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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package storagesvc
|
package storagesvc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"os"
|
"os"
|
||||||
@@ -36,7 +37,7 @@ type (
|
|||||||
storage Storage
|
storage Storage
|
||||||
}
|
}
|
||||||
|
|
||||||
//StowClient is the wraper client for stow (Cloud storage abstraction package)
|
//StowClient is the wrapper client for stow (Cloud storage abstraction package)
|
||||||
StowClient struct {
|
StowClient struct {
|
||||||
logger *zap.Logger
|
logger *zap.Logger
|
||||||
config *storageConfig
|
config *storageConfig
|
||||||
@@ -62,6 +63,43 @@ var (
|
|||||||
ErrWritingFileIntoResponse = errors.New("unable to copy item into http response")
|
ErrWritingFileIntoResponse = errors.New("unable to copy item into http response")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func getContainer(loc stow.Location, containerName string, cursor string) (stow.Container, error) {
|
||||||
|
// use location.Containers to find containers that match the prefix (container name)
|
||||||
|
cons, cursorNew, err := loc.Containers(containerName, cursor, 1)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var con stow.Container
|
||||||
|
for _, v := range cons {
|
||||||
|
c, err := loc.Container(v.ID())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if c.Name() == containerName {
|
||||||
|
con = cons[0]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if con == nil && !stow.IsCursorEnd(cursorNew) {
|
||||||
|
_, err := getContainer(loc, containerName, cursorNew)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return con, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getOrCreateContainer(loc stow.Location, containerName string, cursor string) (stow.Container, error) {
|
||||||
|
con, err := loc.CreateContainer(containerName)
|
||||||
|
if err != nil && (os.IsExist(err) || strings.Contains(err.Error(), "BucketAlreadyOwnedByYou")) {
|
||||||
|
con, err = getContainer(loc, containerName, stow.CursorStart)
|
||||||
|
}
|
||||||
|
if con == nil && err == nil {
|
||||||
|
err = fmt.Errorf("Storage container %s not found", containerName)
|
||||||
|
}
|
||||||
|
return con, err
|
||||||
|
}
|
||||||
|
|
||||||
// MakeStowClient create a new StowClient for given storage
|
// MakeStowClient create a new StowClient for given storage
|
||||||
func MakeStowClient(logger *zap.Logger, storage Storage) (*StowClient, error) {
|
func MakeStowClient(logger *zap.Logger, storage Storage) (*StowClient, error) {
|
||||||
storageType := getStorageType(storage)
|
storageType := getStorageType(storage)
|
||||||
@@ -84,23 +122,7 @@ func MakeStowClient(logger *zap.Logger, storage Storage) (*StowClient, error) {
|
|||||||
}
|
}
|
||||||
stowClient.location = loc
|
stowClient.location = loc
|
||||||
|
|
||||||
con, err := loc.CreateContainer(config.storage.getContainerName())
|
con, err := getOrCreateContainer(loc, config.storage.getContainerName(), stow.CursorStart)
|
||||||
if err != nil && (os.IsExist(err) || strings.Contains(err.Error(), "BucketAlreadyOwnedByYou")) {
|
|
||||||
var cons []stow.Container
|
|
||||||
var cursor string
|
|
||||||
|
|
||||||
// use location.Containers to find containers that match the prefix (container name)
|
|
||||||
cons, cursor, err = loc.Containers(config.storage.getContainerName(), stow.CursorStart, 1)
|
|
||||||
if err == nil {
|
|
||||||
con = cons[0]
|
|
||||||
if !stow.IsCursorEnd(cursor) {
|
|
||||||
// Should only have one storage container
|
|
||||||
err = errors.New("Found more than one matched storage containers")
|
|
||||||
} else {
|
|
||||||
con = cons[0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user