Compare commits

...
19 Commits
Author SHA1 Message Date
Sanket SudakeandGitHub 8110f9ac13 Fix code/doc generators and deepgen code (#2353)
Signed-off-by: Sanket Sudake <sanketsudake@gmail.com>
2022-02-12 12:04:08 +05:30
Sanket SudakeandGitHub 4f8a60b498 Update version to v1.16.0-rc1 in chart (#2350)
Signed-off-by: Sanket Sudake <sanketsudake@gmail.com>
2022-02-11 15:19:44 +05:30
Shubham NazareandGitHub 667629d265 dump HTTP request/response for function test (#2348) 2022-02-11 14:35:21 +05:30
Ankit ChawlaandGitHub b06ff625e0 Fix validation for secret & configmap reference with function (#2349) 2022-02-11 09:00:47 +05:30
Ankit ChawlaandGitHub 8ee74161fc Added validation to keda types and updated help (#2346)
* Added validation to keda types and updated help

* Changed formatting of help

* Changed variable name
2022-02-09 19:55:14 +05:30
Ankit ChawlaandGitHub e1fb5a7411 Changed deletion order in spec destroy according to dependency (#2344) 2022-02-08 13:54:28 +05:30
Ankit ChawlaandGitHub e8ff79e448 Prevent env deletion if any function exists (#2343)
* Added force deletion flag for env
2022-02-07 16:20:54 +05:30
Shubham NazareandGitHub 5cb3ebf262 CLI Check (#2341)
* added checks for kubernetes-version, fission-services and fission-version

* refactor kuberntes and fission version check
2022-02-07 11:01:20 +05:30
Ankit ChawlaandGitHub 3ac188124e [Feature] Force spec apply even if conflicting resources exist with different deployment ID (#2338)
* Added allowconflicts flag to specs
* Made changes for all resources
* Added help for allowconflicts flag
* Changed function isObjectMetaEqual
2022-02-02 12:28:41 +05:30
Pradeep Lakshmi NarasimhaandGitHub 590eefaa52 feature: Basic auth support with fission router (#2292) 2022-02-01 19:40:40 +05:30
Sanket SudakeandGitHub 4b307be939 Change URL structure for CLI docs with reference (#2339)
Signed-off-by: Sanket Sudake <sanketsudake@gmail.com>
2022-01-31 14:12:13 +05:30
Shubham NazareandGitHub 260de05a63 make graceperiod configurable for container functions (#2337) 2022-01-28 10:18:20 +05:30
Shubham NazareandGitHub e06aa25245 show error while creating mqtrigger if given function is not present (#2306) 2022-01-25 10:41:09 +05:30
Sanket SudakeandGitHub 353453e9a7 Rbac resources per release for multiple installation on same cluster (#2302)
* Change RBAC resource names work for multiple Fission release
* Fetch secret configmap and package cluster role based on the release name
* Remove default namespace hardcoding from helm chart

Signed-off-by: Sanket Sudake <sanketsudake@gmail.com>
2022-01-18 09:18:53 +05:30
Sanket SudakeandGitHub 85084249cf ci(Mergify): configuration update (#2303)
Signed-off-by:  Sanket Sudake <sanketsudake@gmail.com>
2022-01-17 19:00:04 +05:30
Ankit ChawlaandGitHub 89aeddaf3a Minor bug fixes (#2298) 2022-01-11 17:06:21 +05:30
Pradeep Lakshmi NarasimhaandGitHub 89f80c6f25 Apply commit label on resources created/updated when '--commitlabel' flag is passed (#2279) 2022-01-11 12:31:59 +05:30
Ankit ChawlaandGitHub b27043518f Added ignorenotfound flag for all resources' deletion (#2293)
Treat \"resource not found\" as a successful delete if ignorenotfound flag passed while deletion of Fission resource.
2022-01-06 17:30:05 +05:30
Sanket SudakeandGitHub f54bd6a703 Update changelog for 1.15.1 release (#2289)
Signed-off-by: Sanket Sudake <sanketsudake@gmail.com>
2021-12-29 10:33:52 +05:30
79 changed files with 1473 additions and 165 deletions
+7 -2
View File
@@ -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
+13
View File
@@ -1,5 +1,18 @@
# Changelog # Changelog
## [v1.15.1](https://github.com/fission/fission/tree/v1.15.1) (2021-12-28)
[Full Changelog](https://github.com/fission/fission/compare/v1.15.0...v1.15.1)
**Merged pull requests:**
- MQT Kafka: Use Sarama Group Consumer instead of bsm/sarama-cluster library [\#2286](https://github.com/fission/fission/pull/2286) ([sanketsudake](https://github.com/sanketsudake))
- Capture error from schema check in preupgrade verification [\#2285](https://github.com/fission/fission/pull/2285) ([sanketsudake](https://github.com/sanketsudake))
- chore: Update dependency opencontainers/runc v1.0.3 [\#2281](https://github.com/fission/fission/pull/2281) ([sanketsudake](https://github.com/sanketsudake))
- Allow user to use existing bucket with same name via fission storage service [\#2275](https://github.com/fission/fission/pull/2275) ([YachikaRalhan](https://github.com/YachikaRalhan))
- Retry pod choose if we get terminated or deleted pod from ready pod controller [\#2274](https://github.com/fission/fission/pull/2274) ([sanketsudake](https://github.com/sanketsudake))
- Add support for generating CRD docs [\#2273](https://github.com/fission/fission/pull/2273) ([sanketsudake](https://github.com/sanketsudake))
## [v1.15.0](https://github.com/fission/fission/tree/v1.15.0) (2021-11-23) ## [v1.15.0](https://github.com/fission/fission/tree/v1.15.0) (2021-11-23)
[Full Changelog](https://github.com/fission/fission/compare/v1.15.0-rc2...v1.15.0) [Full Changelog](https://github.com/fission/fission/compare/v1.15.0-rc2...v1.15.0)
+2 -2
View File
@@ -80,14 +80,14 @@ generate-swagger-doc:
@./hack/update-swagger-docs.sh @./hack/update-swagger-docs.sh
generate-cli-docs: generate-cli-docs:
go run tools/cmd-docs/main.go -o "../fission.io/content/en/docs/fission-cli" go run tools/cmd-docs/main.go -o "../fission.io/content/en/docs/reference/fission-cli"
generate-crd-ref-docs: generate-crd-ref-docs:
# crd-ref-docs: https://github.com/elastic/crd-ref-docs # crd-ref-docs: https://github.com/elastic/crd-ref-docs
crd-ref-docs --source-path=pkg/apis/core/v1 --config=tools/crd-ref-docs/config.yaml --renderer markdown crd-ref-docs --source-path=pkg/apis/core/v1 --config=tools/crd-ref-docs/config.yaml --renderer markdown
cp tools/crd-ref-docs/header.md crd_docs.md cp tools/crd-ref-docs/header.md crd_docs.md
cat out.md >> crd_docs.md && rm out.md cat out.md >> crd_docs.md && rm out.md
cp crd_docs.md ../fission.io/content/en/docs/crd/_index.md mv crd_docs.md ../fission.io/content/en/docs/reference/crd-reference.md
all-generators: codegen generate-crds generate-swagger-doc all-generators: codegen generate-crds generate-swagger-doc
+2 -2
View File
@@ -1,7 +1,7 @@
apiVersion: v2 apiVersion: v2
name: fission-all name: fission-all
version: v1.15.1 version: v1.16.0-rc1
appVersion: v1.15.1 appVersion: v1.16.0-rc1
description: Fission is a fast serverless framework for Kubernetes. description: Fission is a fast serverless framework for Kubernetes.
home: https://fission.io/ home: https://fission.io/
icon: https://fission.io/images/fission-logo-white.svg icon: https://fission.io/images/fission-logo-white.svg
+9
View File
@@ -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 }}
+38 -4
View File
@@ -25,7 +25,7 @@ image: fission/fission-bundle
## It is also used by the chart to identify version of the few more images apart from fission-bundle. ## It is also used by the chart to identify version of the few more images apart from fission-bundle.
## Keep it empty for using latest tag. ## Keep it empty for using latest tag.
## ##
imageTag: v1.15.1 imageTag: v1.16.0-rc1
## pullPolicy represents the pull policy to use for images in the chart. ## pullPolicy represents the pull policy to use for images in the chart.
## ##
@@ -68,6 +68,10 @@ functionNamespace: fission-function
## ##
builderNamespace: fission-builder builderNamespace: fission-builder
## defaultNamespace represents the default namespace in Kubernetes.
##
defaultNamespace: default
## createNamespace decides to create namespaces by the chart. ## createNamespace decides to create namespaces by the chart.
## If set to true, functionNamespace and builderNamespace namespaces mentioned above will be created by the chart. ## If set to true, functionNamespace and builderNamespace namespaces mentioned above will be created by the chart.
## Set to false if you want to create the namespaces manually. ## Set to false if you want to create the namespaces manually.
@@ -85,7 +89,7 @@ fetcher:
## image represents the image of the fetcher component. ## image represents the image of the fetcher component.
image: fission/fetcher image: fission/fetcher
## imageTag represents the tag of the image of the fetcher component. ## imageTag represents the tag of the image of the fetcher component.
imageTag: v1.15.1 imageTag: v1.16.0-rc1
## Fetcher is only for to downloading or uploading archive. ## Fetcher is only for to downloading or uploading archive.
## Normally, you don't need to change the value here, unless necessary. ## Normally, you don't need to change the value here, unless necessary.
@@ -157,7 +161,6 @@ router:
## router resource utilization when under heavy workloads. ## router resource utilization when under heavy workloads.
## ##
displayAccessLog: false displayAccessLog: false
## svcAnnotations is the annotations to be added to the service resource created for router. ## svcAnnotations is the annotations to be added to the service resource created for router.
## ##
# svcAnnotations: # svcAnnotations:
@@ -451,7 +454,7 @@ preUpgradeChecks:
image: fission/pre-upgrade-checks image: fission/pre-upgrade-checks
## pre-install/pre-upgrade checks image version ## pre-install/pre-upgrade checks image version
## ##
imageTag: v1.15.1 imageTag: v1.16.0-rc1
## Fission post-install/post-upgrade reporting live in this image ## Fission post-install/post-upgrade reporting live in this image
## ##
@@ -479,6 +482,37 @@ prometheus:
canaryDeployment: canaryDeployment:
enabled: false enabled: false
## Enable authentication for fission function invocation via Fission router
##
authentication:
## set this flag to true if you need authentication
## for all function invocations
## default 'false'
##
enabled: false
## authUriPath defines authentication endpoint path
## via router
## default '/auth/login'
##
authUriPath:
## authUsername is used as a username for authentication
## default 'admin'
##
authUsername: admin
## jwtSigningKey is the signing key used for
## signing the JWT token
##
jwtSigningKey: serverless
## jwtExpiryTime is the JWT expiry time
## in seconds
## default '120'
##
jwtExpiryTime:
## jwtIssuer is the issuer of JWT
## default 'fission'
##
jwtIssuer: fission
## Use the following flags to enable OpenTracing. ## Use the following flags to enable OpenTracing.
## Note: OpenTracing support will be removed in an upcoming release. ## Note: OpenTracing support will be removed in an upcoming release.
## Please prefer using OpenTelemetry instead. ## Please prefer using OpenTelemetry instead.
+17 -1
View File
@@ -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...)
+1
View File
@@ -22,6 +22,7 @@ require (
github.com/go-git/go-git/v5 v5.4.2 github.com/go-git/go-git/v5 v5.4.2
github.com/go-ini/ini v1.63.2 // indirect github.com/go-ini/ini v1.63.2 // indirect
github.com/go-openapi/spec v0.20.4 github.com/go-openapi/spec v0.20.4
github.com/golang-jwt/jwt/v4 v4.2.0
github.com/gorilla/mux v1.8.0 github.com/gorilla/mux v1.8.0
github.com/gotestyourself/gotestyourself v2.2.0+incompatible // indirect github.com/gotestyourself/gotestyourself v2.2.0+incompatible // indirect
github.com/graymeta/stow v0.2.7 github.com/graymeta/stow v0.2.7
+3
View File
@@ -492,7 +492,10 @@ github.com/gogo/protobuf v1.2.2-0.20190730201129-28a6bbf47e48/go.mod h1:SlYgWuQ5
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c=
github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU=
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
+4 -2
View File
@@ -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"
+12
View File
@@ -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
+32
View File
@@ -47,6 +47,22 @@ func (in *Archive) DeepCopy() *Archive {
return out return out
} }
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AuthLogin) DeepCopyInto(out *AuthLogin) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthLogin.
func (in *AuthLogin) DeepCopy() *AuthLogin {
if in == nil {
return nil
}
out := new(AuthLogin)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Builder) DeepCopyInto(out *Builder) { func (in *Builder) DeepCopyInto(out *Builder) {
*out = *in *out = *in
@@ -883,6 +899,22 @@ func (in *PackageStatus) DeepCopy() *PackageStatus {
return out return out
} }
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *RouterAuthToken) DeepCopyInto(out *RouterAuthToken) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouterAuthToken.
func (in *RouterAuthToken) DeepCopy() *RouterAuthToken {
if in == nil {
return nil
}
out := new(RouterAuthToken)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Runtime) DeepCopyInto(out *Runtime) { func (in *Runtime) DeepCopyInto(out *Runtime) {
*out = *in *out = *in
@@ -22,6 +22,14 @@ func (Archive) SwaggerDoc() map[string]string {
return map_Archive return map_Archive
} }
var map_AuthLogin = map[string]string{
"": "AuthLogin defines the body for router login",
}
func (AuthLogin) SwaggerDoc() map[string]string {
return map_AuthLogin
}
var map_Builder = map[string]string{ var map_Builder = map[string]string{
"": "Builder is the setting for environment builder.", "": "Builder is the setting for environment builder.",
"image": "Image for containing the language compilation environment.", "image": "Image for containing the language compilation environment.",
@@ -370,6 +378,14 @@ func (PackageStatus) SwaggerDoc() map[string]string {
return map_PackageStatus return map_PackageStatus
} }
var map_RouterAuthToken = map[string]string{
"": "RouterAuthToken defines the authorization token for accessing router",
}
func (RouterAuthToken) SwaggerDoc() map[string]string {
return map_RouterAuthToken
}
var map_Runtime = map[string]string{ var map_Runtime = map[string]string{
"": "Runtime is the setting for environment runtime.", "": "Runtime is the setting for environment runtime.",
"image": "Image for containing the language runtime.", "image": "Image for containing the language runtime.",
+1 -1
View File
@@ -167,7 +167,7 @@ func (pkgw *packageWatcher) build(ctx context.Context, srcpkg *fv1.Package) {
// Add the package getter rolebinding to builder sa // Add the package getter rolebinding to builder sa
// we continue here if role binding was not setup successfully. this is because without this, the fetcher won't be able to fetch the source pkg into the container and // we continue here if role binding was not setup successfully. this is because without this, the fetcher won't be able to fetch the source pkg into the container and
// the build will fail eventually // the build will fail eventually
err := utils.SetupRoleBinding(ctx, pkgw.logger, pkgw.k8sClient, fv1.PackageGetterRB, pkg.ObjectMeta.Namespace, fv1.PackageGetterCR, fv1.ClusterRole, fv1.FissionBuilderSA, builderNs) err := utils.SetupRoleBinding(ctx, pkgw.logger, pkgw.k8sClient, fv1.PackageGetterRB, pkg.ObjectMeta.Namespace, utils.GetPackageGetterCR(), fv1.ClusterRole, fv1.FissionBuilderSA, builderNs)
if err != nil { if err != nil {
pkgw.logger.Error("error setting up role binding for package", pkgw.logger.Error("error setting up role binding for package",
zap.Error(err), zap.Error(err),
+8
View File
@@ -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
} }
+2
View File
@@ -60,6 +60,8 @@ func MakeErrorFromHTTP(resp *http.Response) error {
errCode = ErrorRequestTimeout errCode = ErrorRequestTimeout
case http.StatusTooManyRequests: case http.StatusTooManyRequests:
errCode = ErrorTooManyRequests errCode = ErrorTooManyRequests
case http.StatusUnauthorized:
errCode = ErrorNotAuthorized
default: default:
errCode = ErrorInternal errCode = ErrorInternal
} }
@@ -172,6 +172,9 @@ func (cn *Container) getDeploymentSpec(ctx context.Context, fn *fv1.Function, ta
} }
gracePeriodSeconds := int64(6 * 60) gracePeriodSeconds := int64(6 * 60)
if *fn.Spec.PodSpec.TerminationGracePeriodSeconds >= 0 {
gracePeriodSeconds = *fn.Spec.PodSpec.TerminationGracePeriodSeconds
}
podAnnotations := make(map[string]string) podAnnotations := make(map[string]string)
@@ -140,7 +140,7 @@ func (deploy *NewDeploy) setupRBACObjs(ctx context.Context, deployNamespace stri
} }
// create a cluster role binding for the fetcher SA, if not already created, granting access to do a get on packages in any ns // create a cluster role binding for the fetcher SA, if not already created, granting access to do a get on packages in any ns
err = utils.SetupRoleBinding(ctx, deploy.logger, deploy.kubernetesClient, fv1.PackageGetterRB, fn.Spec.Package.PackageRef.Namespace, fv1.PackageGetterCR, fv1.ClusterRole, fv1.FissionFetcherSA, deployNamespace) err = utils.SetupRoleBinding(ctx, deploy.logger, deploy.kubernetesClient, fv1.PackageGetterRB, fn.Spec.Package.PackageRef.Namespace, utils.GetPackageGetterCR(), fv1.ClusterRole, fv1.FissionFetcherSA, deployNamespace)
if err != nil { if err != nil {
deploy.logger.Error("error creating role binding for function", deploy.logger.Error("error creating role binding for function",
zap.Error(err), zap.Error(err),
@@ -151,7 +151,7 @@ func (deploy *NewDeploy) setupRBACObjs(ctx context.Context, deployNamespace stri
} }
// create rolebinding in function namespace for fetcherSA.envNamespace to be able to get secrets and configmaps // create rolebinding in function namespace for fetcherSA.envNamespace to be able to get secrets and configmaps
err = utils.SetupRoleBinding(ctx, deploy.logger, deploy.kubernetesClient, fv1.SecretConfigMapGetterRB, fn.ObjectMeta.Namespace, fv1.SecretConfigMapGetterCR, fv1.ClusterRole, fv1.FissionFetcherSA, deployNamespace) err = utils.SetupRoleBinding(ctx, deploy.logger, deploy.kubernetesClient, fv1.SecretConfigMapGetterRB, fn.ObjectMeta.Namespace, utils.GetSecretConfigMapGetterCR(), fv1.ClusterRole, fv1.FissionFetcherSA, deployNamespace)
if err != nil { if err != nil {
deploy.logger.Error("error creating role binding for function", deploy.logger.Error("error creating role binding for function",
zap.Error(err), zap.Error(err),
@@ -70,7 +70,7 @@ func FunctionEventHandlers(logger *zap.Logger, kubernetesClient *kubernetes.Clie
// setup rolebinding is tried, if it fails, we don't return. we just log an error and move on, because : // setup rolebinding is tried, if it fails, we don't return. we just log an error and move on, because :
// 1. not all functions have secrets and/or configmaps, so things will work without this rolebinding in that case. // 1. not all functions have secrets and/or configmaps, so things will work without this rolebinding in that case.
// 2. on the contrary, when the route is tried, the env fetcher logs will show a 403 forbidden message and same will be relayed to executor. // 2. on the contrary, when the route is tried, the env fetcher logs will show a 403 forbidden message and same will be relayed to executor.
err := utils.SetupRoleBinding(ctx, logger, kubernetesClient, fv1.SecretConfigMapGetterRB, fn.ObjectMeta.Namespace, fv1.SecretConfigMapGetterCR, fv1.ClusterRole, fv1.FissionFetcherSA, envNs) err := utils.SetupRoleBinding(ctx, logger, kubernetesClient, fv1.SecretConfigMapGetterRB, fn.ObjectMeta.Namespace, utils.GetSecretConfigMapGetterCR(), fv1.ClusterRole, fv1.FissionFetcherSA, envNs)
if err != nil { if err != nil {
logger.Error("error creating rolebinding", zap.Error(err), zap.String("role_binding", fv1.SecretConfigMapGetterRB)) logger.Error("error creating rolebinding", zap.Error(err), zap.String("role_binding", fv1.SecretConfigMapGetterRB))
} else { } else {
@@ -185,7 +185,7 @@ func FunctionEventHandlers(logger *zap.Logger, kubernetesClient *kubernetes.Clie
} }
ctx := context.Background() ctx := context.Background()
err := utils.SetupRoleBinding(ctx, logger, kubernetesClient, fv1.SecretConfigMapGetterRB, err := utils.SetupRoleBinding(ctx, logger, kubernetesClient, fv1.SecretConfigMapGetterRB,
newFunc.ObjectMeta.Namespace, fv1.SecretConfigMapGetterCR, fv1.ClusterRole, newFunc.ObjectMeta.Namespace, utils.GetSecretConfigMapGetterCR(), fv1.ClusterRole,
fv1.FissionFetcherSA, envNs) fv1.FissionFetcherSA, envNs)
if err != nil { if err != nil {
@@ -47,7 +47,7 @@ func PackageEventHandlers(logger *zap.Logger, kubernetesClient *kubernetes.Clien
ctx := context.Background() ctx := context.Background()
// here, we return if we hit an error during rolebinding setup. this is because this rolebinding is mandatory for // here, we return if we hit an error during rolebinding setup. this is because this rolebinding is mandatory for
// every function's package to be loaded into its env. without that, there's no point to move forward. // every function's package to be loaded into its env. without that, there's no point to move forward.
err := utils.SetupRoleBinding(ctx, logger, kubernetesClient, fv1.PackageGetterRB, pkg.ObjectMeta.Namespace, fv1.PackageGetterCR, fv1.ClusterRole, fv1.FissionFetcherSA, envNs) err := utils.SetupRoleBinding(ctx, logger, kubernetesClient, fv1.PackageGetterRB, pkg.ObjectMeta.Namespace, utils.GetPackageGetterCR(), fv1.ClusterRole, fv1.FissionFetcherSA, envNs)
if err != nil { if err != nil {
logger.Error("error creating rolebinding for package", logger.Error("error creating rolebinding for package",
zap.Error(err), zap.Error(err),
@@ -83,7 +83,7 @@ func PackageEventHandlers(logger *zap.Logger, kubernetesClient *kubernetes.Clien
ctx := context.Background() ctx := context.Background()
err := utils.SetupRoleBinding(ctx, logger, kubernetesClient, fv1.PackageGetterRB, err := utils.SetupRoleBinding(ctx, logger, kubernetesClient, fv1.PackageGetterRB,
newPkg.ObjectMeta.Namespace, fv1.PackageGetterCR, fv1.ClusterRole, newPkg.ObjectMeta.Namespace, utils.GetPackageGetterCR(), fv1.ClusterRole,
fv1.FissionFetcherSA, envNs) fv1.FissionFetcherSA, envNs)
if err != nil { if err != nil {
logger.Error("error updating rolebinding for package", logger.Error("error updating rolebinding for package",
+10
View File
@@ -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"`
}
) )
+1 -1
View File
@@ -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")
} }
+50
View File
@@ -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
}
+35
View File
@@ -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
}
+1 -1
View File
@@ -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{
+19
View File
@@ -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
} }
+2 -1
View File
@@ -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.
+2 -2
View File
@@ -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))
} }
+4
View File
@@ -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
+24
View File
@@ -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
} }
+1 -1
View File
@@ -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{
+1 -1
View File
@@ -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)")
} }
+1 -1
View File
@@ -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{
+1 -1
View File
@@ -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))
} }
+4
View File
@@ -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")
} }
+1 -1
View File
@@ -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{
+6 -1
View File
@@ -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{
+4
View File
@@ -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")
} }
+1 -1
View File
@@ -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{
+2 -2
View File
@@ -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")
} }
+4
View File
@@ -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")
} }
+1 -1
View File
@@ -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")
} }
+78 -47
View File
@@ -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)
}
+2 -2
View File
@@ -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{
+45 -2
View File
@@ -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
}
+1 -1
View File
@@ -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")
} }
+22 -3
View File
@@ -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;
+41 -13
View File
@@ -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)
+1 -1
View File
@@ -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{
+1 -1
View File
@@ -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")
} }
+45
View File
@@ -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
}
+114
View File
@@ -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
}
+25 -12
View File
@@ -74,8 +74,12 @@ var (
ClientOnly = Flag{Type: Bool, Name: flagkey.ClientOnly, Usage: "If set, the CLI won't connect to remote server"} ClientOnly = Flag{Type: Bool, Name: flagkey.ClientOnly, Usage: "If set, the CLI won't connect to remote server"}
PreCheckOnly = Flag{Type: Bool, Name: flagkey.PreCheckOnly, Usage: "Only run pre-installation checks, to determine if fission can be installed"}
KubeContext = Flag{Type: String, Name: flagkey.KubeContext, Usage: "Kubernetes context to be used for the execution of Fission commands", DefaultValue: ""} KubeContext = Flag{Type: String, Name: flagkey.KubeContext, Usage: "Kubernetes context to be used for the execution of Fission commands", DefaultValue: ""}
IgnoreNotFound = Flag{Type: Bool, Name: flagkey.IgnoreNotFound, Usage: "Treat \"resource not found\" as a successful delete.", DefaultValue: false}
Labels = Flag{Type: String, Name: flagkey.Labels, Usage: "Comma separated labels to apply to the function. E.g. --labels=\"environment=dev,application=analytics\""} Labels = Flag{Type: String, Name: flagkey.Labels, Usage: "Comma separated labels to apply to the function. E.g. --labels=\"environment=dev,application=analytics\""}
Annotation = Flag{Type: StringSlice, Name: flagkey.Annotation, Usage: "Annotation to apply to the function. To mention multiple annotations --annotation=\"abc.com/team=dev\" --annotation=\"foo=bar\""} Annotation = Flag{Type: StringSlice, Name: flagkey.Annotation, Usage: "Annotation to apply to the function. To mention multiple annotations --annotation=\"abc.com/team=dev\" --annotation=\"foo=bar\""}
@@ -123,6 +127,8 @@ var (
FnRequestsPerPod = Flag{Type: Int, Name: flagkey.FnRequestsPerPod, Aliases: []string{"rpp"}, Usage: "Maximum number of concurrent requests that can be served by a specialized pod", DefaultValue: 1} FnRequestsPerPod = Flag{Type: Int, Name: flagkey.FnRequestsPerPod, Aliases: []string{"rpp"}, Usage: "Maximum number of concurrent requests that can be served by a specialized pod", DefaultValue: 1}
FnOnceOnly = Flag{Type: Bool, Name: flagkey.FnOnceOnly, Aliases: []string{"yolo"}, Usage: "Specifies if specialized pod will serve exactly one request in its lifetime"} FnOnceOnly = Flag{Type: Bool, Name: flagkey.FnOnceOnly, Aliases: []string{"yolo"}, Usage: "Specifies if specialized pod will serve exactly one request in its lifetime"}
FnSubPath = Flag{Type: String, Name: flagkey.FnSubPath, Usage: "Sub Path to check if function internally supports routing"} FnSubPath = Flag{Type: String, Name: flagkey.FnSubPath, Usage: "Sub Path to check if function internally supports routing"}
// Termination Grace Period configurable at function creation/update only for container functions
FnTerminationGracePeriod = Flag{Type: Int64, Name: flagkey.FnGracePeriod, Usage: "Grace time (in seconds) for pod to perform connection draining before termination (default value will be used if negative value is given)", DefaultValue: 360}
HtName = Flag{Type: String, Name: flagkey.HtName, Usage: "HTTP trigger name"} HtName = Flag{Type: String, Name: flagkey.HtName, Usage: "HTTP trigger name"}
HtMethod = Flag{Type: StringSlice, Name: flagkey.HtMethod, Usage: "HTTP Methods: GET,POST,PUT,DELETE,HEAD. To mention single method: --method GET and for multiple methods --method GET --method POST. [DEPRECATED for 'fn create', use 'route create' instead]", DefaultValue: []string{http.MethodGet}} HtMethod = Flag{Type: StringSlice, Name: flagkey.HtMethod, Usage: "HTTP Methods: GET,POST,PUT,DELETE,HEAD. To mention single method: --method GET and for multiple methods --method GET --method POST. [DEPRECATED for 'fn create', use 'route create' instead]", DefaultValue: []string{http.MethodGet}}
@@ -138,6 +144,10 @@ var (
HtPrefix = Flag{Type: String, Name: flagkey.HtPrefix, Usage: "Prefix with which functions are exposed. NOTE: Prefix takes precedence over URL/RelativeURL [DEPRECATED for 'fn create', use 'route create' instead]"} HtPrefix = Flag{Type: String, Name: flagkey.HtPrefix, Usage: "Prefix with which functions are exposed. NOTE: Prefix takes precedence over URL/RelativeURL [DEPRECATED for 'fn create', use 'route create' instead]"}
HtKeepPrefix = Flag{Type: Bool, Name: flagkey.HtKeepPrefix, Usage: "Keep the prefix in the URL while forwarding request to the function"} HtKeepPrefix = Flag{Type: Bool, Name: flagkey.HtKeepPrefix, Usage: "Keep the prefix in the URL while forwarding request to the function"}
TokUsername = Flag{Type: String, Name: flagkey.TokUsername, Usage: "Username to generate token for function invocation"}
TokPassword = Flag{Type: String, Name: flagkey.TokPassword, Usage: "Password to generate token for function invocation"}
TokAuthURI = Flag{Type: String, Name: flagkey.TokAuthURI, Usage: "Relative URI path to generate token"}
TtName = Flag{Type: String, Name: flagkey.TtName, Usage: "Time Trigger name"} TtName = Flag{Type: String, Name: flagkey.TtName, Usage: "Time Trigger name"}
TtCron = Flag{Type: String, Name: flagkey.TtCron, Usage: "Time trigger cron spec with each asterisk representing respectively second, minute, hour, the day of the month, month and day of the week. Also supports readable formats like '@every 5m', '@hourly'"} TtCron = Flag{Type: String, Name: flagkey.TtCron, Usage: "Time trigger cron spec with each asterisk representing respectively second, minute, hour, the day of the month, month and day of the week. Also supports readable formats like '@every 5m', '@hourly'"}
TtFnName = Flag{Type: String, Name: flagkey.TtFnName, Usage: "Function name"} TtFnName = Flag{Type: String, Name: flagkey.TtFnName, Usage: "Function name"}
@@ -145,7 +155,7 @@ var (
MqtName = Flag{Type: String, Name: flagkey.MqtName, Usage: "Message queue trigger name"} MqtName = Flag{Type: String, Name: flagkey.MqtName, Usage: "Message queue trigger name"}
MqtFnName = Flag{Type: String, Name: flagkey.MqtFnName, Usage: "Function name"} MqtFnName = Flag{Type: String, Name: flagkey.MqtFnName, Usage: "Function name"}
MqtMQType = Flag{Type: String, Name: flagkey.MqtMQType, Usage: "Message queue type, e.g. nats-streaming, azure-storage-queue, kafka", DefaultValue: "nats-streaming"} MqtMQType = Flag{Type: String, Name: flagkey.MqtMQType, Usage: "For mqtype \"fission\" => nats-streaming, azure-storage-queue, kafka\n\t\t\t\t\t For mqtype \"keda\" => kafka, aws-sqs-queue, aws-kinesis-stream, gcp-pubsub, stan, rabbitmq, redis", DefaultValue: "kafka"}
MqtTopic = Flag{Type: String, Name: flagkey.MqtTopic, Usage: "Message queue Topic the trigger listens on"} MqtTopic = Flag{Type: String, Name: flagkey.MqtTopic, Usage: "Message queue Topic the trigger listens on"}
MqtRespTopic = Flag{Type: String, Name: flagkey.MqtRespTopic, Usage: "Topic that the function response is sent on (response discarded if unspecified)"} MqtRespTopic = Flag{Type: String, Name: flagkey.MqtRespTopic, Usage: "Topic that the function response is sent on (response discarded if unspecified)"}
MqtErrorTopic = Flag{Type: String, Name: flagkey.MqtErrorTopic, Usage: "Topic that the function error messages are sent to (errors discarded if unspecified"} MqtErrorTopic = Flag{Type: String, Name: flagkey.MqtErrorTopic, Usage: "Topic that the function error messages are sent to (errors discarded if unspecified"}
@@ -157,7 +167,7 @@ var (
MqtMaxReplicaCount = Flag{Type: Int, Name: flagkey.MqtMaxReplicaCount, Usage: "Maximum number of replicas of consumers to scale up to", DefaultValue: 100} MqtMaxReplicaCount = Flag{Type: Int, Name: flagkey.MqtMaxReplicaCount, Usage: "Maximum number of replicas of consumers to scale up to", DefaultValue: 100}
MqtMetadata = Flag{Type: StringSlice, Name: flagkey.MqtMetadata, Usage: "Metadata needed for connecting to source system in format: --metadata key1=value1 --metadata key2=value2"} MqtMetadata = Flag{Type: StringSlice, Name: flagkey.MqtMetadata, Usage: "Metadata needed for connecting to source system in format: --metadata key1=value1 --metadata key2=value2"}
MqtSecret = Flag{Type: String, Name: flagkey.MqtSecret, Usage: "Name of secret object", DefaultValue: ""} MqtSecret = Flag{Type: String, Name: flagkey.MqtSecret, Usage: "Name of secret object", DefaultValue: ""}
MqtKind = Flag{Type: String, Name: flagkey.MqtKind, Usage: "Kind of Message Queue Trigger, e.g. fission, keda", DefaultValue: "fission"} MqtKind = Flag{Type: String, Name: flagkey.MqtKind, Usage: "Kind of Message Queue Trigger, e.g. fission, keda", DefaultValue: "keda"}
EnvName = Flag{Type: String, Name: flagkey.EnvName, Usage: "Environment name"} EnvName = Flag{Type: String, Name: flagkey.EnvName, Usage: "Environment name"}
EnvPoolsize = Flag{Type: Int, Name: flagkey.EnvPoolsize, Usage: "Size of the pool", DefaultValue: 3} EnvPoolsize = Flag{Type: Int, Name: flagkey.EnvPoolsize, Usage: "Size of the pool", DefaultValue: 3}
@@ -170,6 +180,7 @@ var (
EnvVersion = Flag{Type: Int, Name: flagkey.EnvVersion, Usage: "Environment API version (1 means v1 interface)", DefaultValue: 1} EnvVersion = Flag{Type: Int, Name: flagkey.EnvVersion, Usage: "Environment API version (1 means v1 interface)", DefaultValue: 1}
EnvImagePullSecret = Flag{Type: String, Name: flagkey.EnvImagePullSecret, Usage: "Secret for Kubernetes to pull an image from a private registry"} EnvImagePullSecret = Flag{Type: String, Name: flagkey.EnvImagePullSecret, Usage: "Secret for Kubernetes to pull an image from a private registry"}
EnvExecutorType = Flag{Type: String, Name: flagkey.EnvExecutorType, Usage: "Executor type of pod in environment; one of 'poolmgr', 'newdeploy', 'container'"} EnvExecutorType = Flag{Type: String, Name: flagkey.EnvExecutorType, Usage: "Executor type of pod in environment; one of 'poolmgr', 'newdeploy', 'container'"}
EnvForce = Flag{Type: Bool, Name: flagkey.EnvForce, Short: "f", Usage: "Force delete env even if one or more functions exist", DefaultValue: false}
KwName = Flag{Type: String, Name: flagkey.KwName, Usage: "Watch name"} KwName = Flag{Type: String, Name: flagkey.KwName, Usage: "Watch name"}
KwFnName = Flag{Type: String, Name: flagkey.KwFnName, Usage: "Function name"} KwFnName = Flag{Type: String, Name: flagkey.KwFnName, Usage: "Function name"}
@@ -191,16 +202,18 @@ var (
PkgSrcChecksum = Flag{Type: String, Name: flagkey.PkgSrcChecksum, Usage: "SHA256 checksum of source archive when providing URL"} PkgSrcChecksum = Flag{Type: String, Name: flagkey.PkgSrcChecksum, Usage: "SHA256 checksum of source archive when providing URL"}
PkgInsecure = Flag{Type: Bool, Name: flagkey.PkgInsecure, Usage: "Skip generating SHA256 checksum for file integrity validation"} PkgInsecure = Flag{Type: Bool, Name: flagkey.PkgInsecure, Usage: "Skip generating SHA256 checksum for file integrity validation"}
SpecSave = Flag{Type: Bool, Name: flagkey.SpecSave, Usage: "Save to the spec directory instead of creating on cluster"} SpecSave = Flag{Type: Bool, Name: flagkey.SpecSave, Usage: "Save to the spec directory instead of creating on cluster"}
SpecDir = Flag{Type: String, Name: flagkey.SpecDir, Usage: "Directory to store specs, defaults to ./specs"} SpecDir = Flag{Type: String, Name: flagkey.SpecDir, Usage: "Directory to store specs, defaults to ./specs"}
SpecName = Flag{Type: String, Name: flagkey.SpecName, Usage: "Name for the app, applied to resources as a Kubernetes annotation"} SpecName = Flag{Type: String, Name: flagkey.SpecName, Usage: "Name for the app, applied to resources as a Kubernetes annotation"}
SpecDeployID = Flag{Type: String, Name: flagkey.SpecDeployID, Aliases: []string{"id"}, Usage: "Deployment ID for the spec deployment config"} SpecDeployID = Flag{Type: String, Name: flagkey.SpecDeployID, Aliases: []string{"id"}, Usage: "Deployment ID for the spec deployment config"}
SpecWait = Flag{Type: Bool, Name: flagkey.SpecWait, Usage: "Wait for package builds"} SpecWait = Flag{Type: Bool, Name: flagkey.SpecWait, Usage: "Wait for package builds"}
SpecWatch = Flag{Type: Bool, Name: flagkey.SpecWatch, Usage: "Watch local files for change, and re-apply specs as necessary"} SpecWatch = Flag{Type: Bool, Name: flagkey.SpecWatch, Usage: "Watch local files for change, and re-apply specs as necessary"}
SpecDelete = Flag{Type: Bool, Name: flagkey.SpecDelete, Usage: "Allow apply to delete resources that no longer exist in the specification"} SpecDelete = Flag{Type: Bool, Name: flagkey.SpecDelete, Usage: "Allow apply to delete resources that no longer exist in the specification"}
SpecDry = Flag{Type: Bool, Name: flagkey.SpecDry, Usage: "View the generated specs"} SpecDry = Flag{Type: Bool, Name: flagkey.SpecDry, Usage: "View the generated specs"}
SpecValidation = Flag{Type: String, Name: flagkey.SpecValidate, Usage: "Turns server side validations of Fission objects on/off"} SpecValidation = Flag{Type: String, Name: flagkey.SpecValidate, Usage: "Turns server side validations of Fission objects on/off"}
SpecIgnore = Flag{Type: String, Name: flagkey.SpecIgnore, Usage: fmt.Sprintf("File containing specs to be ignored inside --specdir, defaults to %v", util.SPEC_IGNORE_FILE)} SpecIgnore = Flag{Type: String, Name: flagkey.SpecIgnore, Usage: fmt.Sprintf("File containing specs to be ingored inside --specdir, defaults to %v", util.SPEC_IGNORE_FILE)}
SpecApplyCommitLabel = Flag{Type: Bool, Name: flagkey.SpecApplyCommitLabel, Usage: "Apply commit label to the resources"}
SpecAllowConflicts = Flag{Type: Bool, Name: flagkey.SpecAllowConflicts, Usage: "If true, spec apply will be forced even if conflicting resources exist", DefaultValue: false}
SupportOutput = Flag{Type: String, Name: flagkey.SupportOutput, Short: "o", Usage: "Output directory to save dump archive/files", DefaultValue: flagkey.DefaultSpecOutputDir} SupportOutput = Flag{Type: String, Name: flagkey.SupportOutput, Short: "o", Usage: "Output directory to save dump archive/files", DefaultValue: flagkey.DefaultSpecOutputDir}
SupportNoZip = Flag{Type: Bool, Name: flagkey.SupportNoZip, Usage: "Save dump information into multiple files instead of single zip file"} SupportNoZip = Flag{Type: Bool, Name: flagkey.SupportNoZip, Usage: "Save dump information into multiple files instead of single zip file"}
+22 -10
View 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"
+4 -1
View File
@@ -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"
) )
+25
View File
@@ -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 {
+243
View File
@@ -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")
}
}
}
+5 -5
View File
@@ -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
+12 -3
View File
@@ -21,8 +21,17 @@ import (
) )
var ( var (
topicValidators = make(map[string]TopicValidator) topicValidators = make(map[string]TopicValidator)
lock = sync.Mutex{} lock = sync.Mutex{}
kedaMqTypeValidators = map[string]bool{
"kafka": true,
"aws-sqs-queue": true,
"aws-kinesis-stream": true,
"gcp-pubsub": true,
"stan": true,
"rabbitmq": true,
"redis": true,
}
) )
type ( type (
@@ -58,7 +67,7 @@ func IsValidTopic(mqType, topic, mqtKind string) bool {
func IsValidMessageQueue(mqType, mqtKind string) bool { func IsValidMessageQueue(mqType, mqtKind string) bool {
if mqtKind == "keda" { if mqtKind == "keda" {
return true return kedaMqTypeValidators[mqType]
} }
_, registered := topicValidators[mqType] _, registered := topicValidators[mqType]
return registered return registered
+172 -3
View File
@@ -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
} }
+157
View File
@@ -0,0 +1,157 @@
/*
Copyright 2022 The Fission Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package gitrepo
import (
"fmt"
"os"
"strings"
"github.com/go-git/go-git/v5"
"github.com/pkg/errors"
)
type GitRepo struct {
setupDone bool
isGitRepo bool
repo *git.Repository
status git.Status
dirPath string
gitRepoRootPath string // absolute path of the root of the git repository
commitID string // commit ID the HEAD of the repository is poitning to
}
// NewGitRepo creates new GitRepo struct
// checks if the given directory path is part of git repository
// accordingly updates the fields of GitRepo struct and returns it
func NewGitRepo(dirPath string) *GitRepo {
var g *GitRepo = &GitRepo{}
var err error
g.dirPath = dirPath
g.setupDone = true
// check if directory is tracked by git repo
g.repo, err = git.PlainOpenWithOptions(dirPath, &git.PlainOpenOptions{DetectDotGit: true})
if err != nil {
return g
}
workTree, err := g.repo.Worktree()
if err != nil {
return g
}
g.status, err = workTree.Status()
if err != nil {
return g
}
if g.status == nil {
return g
}
plumbRef, err := g.repo.Head()
if err != nil {
return g
}
// extract short commit ID
g.commitID = plumbRef.Hash().String()[:7]
// get the root path of git repository
g.gitRepoRootPath = workTree.Filesystem.Root()
g.isGitRepo = true
return g
}
// IsGitRepo returns if the initialized directory path is tracked by git repo
func (g *GitRepo) IsGitRepo() bool {
return g.setupDone && g.isGitRepo
}
// getFileCommitLabel returns the value of 'commit' label
// for the resources present in the file
/*
The value of the `commit` label for different status of the file is as follows:
| Git File Status | Label Value |
|---------------------------------------|----------------------|
| New untracked file | untracked |
| New staged file | staged |
| Tracked file with changes in worktree | <commitID>-unstaged |
| Tracked file with changes staged | <commitID>-staged |
| Tracked file with clean commit | <commitID> |
*/
func (g *GitRepo) GetFileCommitLabel(filePath string) (string, error) {
if !g.setupDone {
return "", errors.New(`GitRepo is not setup. It has to be created by calling 'NewGitRepo' function,
then this function has to be called.`)
}
if !g.isGitRepo {
return "", errors.Errorf(`directory: %s doesn't belong to git repository.`, g.dirPath)
}
// filepath in the git repository
splitPathList := strings.Split(filePath, g.gitRepoRootPath+string(os.PathSeparator))
if len(splitPathList) != 2 {
return "", errors.Errorf("error finding the git repository path of %s", filePath)
}
gitFilePath := splitPathList[1]
gitFileStatus := g.status.File(gitFilePath)
// check if file is tracked
if !g.status.IsUntracked(gitFilePath) {
// unstaged file
if gitFileStatus.Worktree == git.Modified {
return fmt.Sprintf("%s-unstaged", g.commitID), nil
}
// newly staged file
if gitFileStatus.Staging == git.Added {
return "staged", nil
}
// staged file
if gitFileStatus.Staging == git.Modified {
return fmt.Sprintf("%s-staged", g.commitID), nil
}
}
// check if file is committed already
oc, err := g.repo.Log(&git.LogOptions{FileName: &gitFilePath})
if err != nil {
return "", nil
}
_, err = oc.Next()
defer oc.Close()
if err != nil {
// File not tracked by git and/or not committed
return "untracked", nil
}
// File tracked by git and has been committed
return g.commitID, nil
}
+17
View File
@@ -19,6 +19,7 @@ package utils
import ( import (
"context" "context"
"fmt" "fmt"
"os"
"go.uber.org/zap" "go.uber.org/zap"
@@ -295,3 +296,19 @@ func DeleteRoleBinding(ctx context.Context, k8sClient *kubernetes.Clientset, rol
func MakeSAMapKey(saName, saNamespace string) string { func MakeSAMapKey(saName, saNamespace string) string {
return fmt.Sprintf("%s-%s", saName, saNamespace) return fmt.Sprintf("%s-%s", saName, saNamespace)
} }
func GetSecretConfigMapGetterCR() string {
releaseName := os.Getenv("HELM_RELEASE_NAME")
if len(releaseName) > 0 {
return fmt.Sprintf("%s-secret-configmap-getter", releaseName)
}
return "secret-configmap-getter"
}
func GetPackageGetterCR() string {
releaseName := os.Getenv("HELM_RELEASE_NAME")
if len(releaseName) > 0 {
return fmt.Sprintf("%s-package-getter", releaseName)
}
return "package-getter"
}
+1 -1
View File
@@ -20,7 +20,7 @@ url: %s
--- ---
` `
const baseURL = "/docs/fission-cli/" const baseURL = "/docs/reference/fission-cli/"
var filePrepender = func(filename string) string { var filePrepender = func(filename string) string {
name := filepath.Base(filename) name := filepath.Base(filename)
+1 -2
View File
@@ -1,7 +1,6 @@
--- ---
title: "Fission CRD Reference" title: "Fission CRD Reference"
weight: 99 weight: 8
description: > description: >
Fission Custom Resources Definition(CRD) Reference Fission Custom Resources Definition(CRD) Reference
url: /docs/crd-reference/
--- ---