Compare commits
19
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8110f9ac13 | ||
|
|
4f8a60b498 | ||
|
|
667629d265 | ||
|
|
b06ff625e0 | ||
|
|
8ee74161fc | ||
|
|
e1fb5a7411 | ||
|
|
e8ff79e448 | ||
|
|
5cb3ebf262 | ||
|
|
3ac188124e | ||
|
|
590eefaa52 | ||
|
|
4b307be939 | ||
|
|
260de05a63 | ||
|
|
e06aa25245 | ||
|
|
353453e9a7 | ||
|
|
85084249cf | ||
|
|
89aeddaf3a | ||
|
|
89f80c6f25 | ||
|
|
b27043518f | ||
|
|
f54bd6a703 |
+7
-2
@@ -5,9 +5,14 @@ pull_request_rules:
|
||||
- "#approved-reviews-by>=1"
|
||||
- label=ready-to-merge
|
||||
- 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:
|
||||
merge:
|
||||
method: squash
|
||||
commit_message: title+body
|
||||
strict: smart
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
# Changelog
|
||||
|
||||
## [v1.15.1](https://github.com/fission/fission/tree/v1.15.1) (2021-12-28)
|
||||
|
||||
[Full Changelog](https://github.com/fission/fission/compare/v1.15.0...v1.15.1)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- MQT Kafka: Use Sarama Group Consumer instead of bsm/sarama-cluster library [\#2286](https://github.com/fission/fission/pull/2286) ([sanketsudake](https://github.com/sanketsudake))
|
||||
- Capture error from schema check in preupgrade verification [\#2285](https://github.com/fission/fission/pull/2285) ([sanketsudake](https://github.com/sanketsudake))
|
||||
- chore: Update dependency opencontainers/runc v1.0.3 [\#2281](https://github.com/fission/fission/pull/2281) ([sanketsudake](https://github.com/sanketsudake))
|
||||
- Allow user to use existing bucket with same name via fission storage service [\#2275](https://github.com/fission/fission/pull/2275) ([YachikaRalhan](https://github.com/YachikaRalhan))
|
||||
- Retry pod choose if we get terminated or deleted pod from ready pod controller [\#2274](https://github.com/fission/fission/pull/2274) ([sanketsudake](https://github.com/sanketsudake))
|
||||
- Add support for generating CRD docs [\#2273](https://github.com/fission/fission/pull/2273) ([sanketsudake](https://github.com/sanketsudake))
|
||||
|
||||
## [v1.15.0](https://github.com/fission/fission/tree/v1.15.0) (2021-11-23)
|
||||
|
||||
[Full Changelog](https://github.com/fission/fission/compare/v1.15.0-rc2...v1.15.0)
|
||||
|
||||
@@ -80,14 +80,14 @@ generate-swagger-doc:
|
||||
@./hack/update-swagger-docs.sh
|
||||
|
||||
generate-cli-docs:
|
||||
go run tools/cmd-docs/main.go -o "../fission.io/content/en/docs/fission-cli"
|
||||
go run tools/cmd-docs/main.go -o "../fission.io/content/en/docs/reference/fission-cli"
|
||||
|
||||
generate-crd-ref-docs:
|
||||
# crd-ref-docs: https://github.com/elastic/crd-ref-docs
|
||||
crd-ref-docs --source-path=pkg/apis/core/v1 --config=tools/crd-ref-docs/config.yaml --renderer markdown
|
||||
cp tools/crd-ref-docs/header.md crd_docs.md
|
||||
cat out.md >> crd_docs.md && rm out.md
|
||||
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
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
apiVersion: v2
|
||||
name: fission-all
|
||||
version: v1.15.1
|
||||
appVersion: v1.15.1
|
||||
version: v1.16.0-rc1
|
||||
appVersion: v1.16.0-rc1
|
||||
description: Fission is a fast serverless framework for Kubernetes.
|
||||
home: https://fission.io/
|
||||
icon: https://fission.io/images/fission-logo-white.svg
|
||||
|
||||
@@ -20,6 +20,15 @@ Windows:
|
||||
# Register this function with Fission
|
||||
$ 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
|
||||
$ fission function test --name hello
|
||||
Hello, world!
|
||||
|
||||
|
||||
@@ -31,6 +31,13 @@ canary:
|
||||
prometheusSvc: {{ .Values.prometheus.serviceEndpoint | default "" | quote }}
|
||||
{{- end }}
|
||||
{{- 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 -}}
|
||||
|
||||
{{/*
|
||||
|
||||
@@ -46,6 +46,8 @@ spec:
|
||||
value: {{ .Values.debugEnv | quote }}
|
||||
- name: PPROF_ENABLED
|
||||
value: {{ .Values.pprof.enabled | quote }}
|
||||
- name: HELM_RELEASE_NAME
|
||||
value: {{ .Release.Name | quote }}
|
||||
{{- include "opentracing.envs" . | indent 8 }}
|
||||
{{- include "opentelemtry.envs" . | indent 8 }}
|
||||
{{- if .Values.terminationMessagePath }}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: fission-cr-admin
|
||||
name: {{ .Release.Name }}-fission-cr-admin
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
kind: ClusterRoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: fission-cr-admin
|
||||
name: {{ .Release.Name }}-fission-cr-admin
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: fission-svc
|
||||
namespace: {{ .Release.Namespace }}
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: fission-cr-admin
|
||||
name: {{ .Release.Name }}-fission-cr-admin
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
|
||||
@@ -54,6 +54,8 @@ spec:
|
||||
value: {{ .Values.debugEnv | quote }}
|
||||
- name: PPROF_ENABLED
|
||||
value: {{ .Values.pprof.enabled | quote }}
|
||||
- name: HELM_RELEASE_NAME
|
||||
value: {{ .Release.Name | quote }}
|
||||
{{- include "opentracing.envs" . | indent 8 }}
|
||||
{{- include "opentelemtry.envs" . | indent 8 }}
|
||||
readinessProbe:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: secret-configmap-getter
|
||||
name: {{ .Release.Name }}-secret-configmap-getter
|
||||
rules:
|
||||
- apiGroups:
|
||||
- "*"
|
||||
@@ -17,7 +17,7 @@ rules:
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: package-getter
|
||||
name: {{ .Release.Name }}-package-getter
|
||||
rules:
|
||||
- apiGroups:
|
||||
- "*"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: fission-fetcher
|
||||
namespace: default
|
||||
name: {{ .Release.Name }}-fission-fetcher
|
||||
namespace: {{ .Values.defaultNamespace }}
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
@@ -38,8 +38,8 @@ rules:
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: fission-builder
|
||||
namespace: default
|
||||
name: {{ .Release.Name }}-fission-builder
|
||||
namespace: {{ .Values.defaultNamespace }}
|
||||
rules:
|
||||
- apiGroups:
|
||||
- fission.io
|
||||
@@ -60,7 +60,7 @@ apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
namespace: {{ .Values.functionNamespace }}
|
||||
name: event-fetcher
|
||||
name: {{ .Release.Name }}-event-fetcher
|
||||
rules:
|
||||
- apiGroups: [""] # "" indicates the core API group
|
||||
resources: ["pods"]
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: fission-fetcher
|
||||
namespace: default
|
||||
name: {{ .Release.Name }}-fission-fetcher
|
||||
namespace: {{ .Values.defaultNamespace }}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: fission-fetcher
|
||||
name: {{ .Release.Name }}-fission-fetcher
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: fission-fetcher
|
||||
@@ -16,12 +16,12 @@ subjects:
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: fission-builder
|
||||
namespace: default
|
||||
name: {{ .Release.Name }}-fission-builder
|
||||
namespace: {{ .Values.defaultNamespace }}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: fission-builder
|
||||
name: {{ .Release.Name }}-fission-builder
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: fission-builder
|
||||
@@ -31,12 +31,12 @@ subjects:
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: fission-fetcher-pod-reader
|
||||
name: {{ .Release.Name }}-fission-fetcher-pod-reader
|
||||
namespace: {{ .Values.functionNamespace }}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: event-fetcher
|
||||
name: {{ .Release.Name }}-event-fetcher
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: fission-fetcher
|
||||
|
||||
@@ -35,6 +35,23 @@ spec:
|
||||
command: ["/fission-bundle"]
|
||||
args: ["--routerPort", "8888", "--executorUrl", "http://executor.{{ .Release.Namespace }}"]
|
||||
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
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
@@ -80,6 +97,10 @@ spec:
|
||||
port: 8888
|
||||
initialDelaySeconds: 35
|
||||
periodSeconds: 5
|
||||
volumeMounts:
|
||||
- name: config-volume
|
||||
mountPath: /etc/config/config.yaml
|
||||
subPath: config.yaml
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
name: metrics
|
||||
@@ -100,6 +121,10 @@ spec:
|
||||
terminationMessagePolicy: {{ .Values.terminationMessagePolicy }}
|
||||
{{- end }}
|
||||
serviceAccountName: fission-svc
|
||||
volumes:
|
||||
- name: config-volume
|
||||
configMap:
|
||||
name: feature-config
|
||||
{{- if .Values.router.priorityClassName }}
|
||||
priorityClassName: {{ .Values.router.priorityClassName }}
|
||||
{{- else if .Values.priorityClassName }}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
{{- if .Values.authentication.enabled }}
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: router
|
||||
labels:
|
||||
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
||||
annotations:
|
||||
"helm.sh/hook": pre-install
|
||||
data:
|
||||
username: {{ .Values.authentication.authUsername | b64enc | quote }}
|
||||
password: {{ randAlphaNum 20 | b64enc | quote }}
|
||||
jwtSigningKey: {{ .Values.authentication.jwtSigningKey | b64enc | quote }}
|
||||
{{- end }}
|
||||
@@ -25,7 +25,7 @@ image: fission/fission-bundle
|
||||
## It is also used by the chart to identify version of the few more images apart from fission-bundle.
|
||||
## 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.
|
||||
##
|
||||
@@ -68,6 +68,10 @@ functionNamespace: fission-function
|
||||
##
|
||||
builderNamespace: fission-builder
|
||||
|
||||
## defaultNamespace represents the default namespace in Kubernetes.
|
||||
##
|
||||
defaultNamespace: default
|
||||
|
||||
## createNamespace decides to create namespaces 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.
|
||||
@@ -85,7 +89,7 @@ fetcher:
|
||||
## image represents the image of the fetcher component.
|
||||
image: fission/fetcher
|
||||
## 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.
|
||||
## Normally, you don't need to change the value here, unless necessary.
|
||||
@@ -157,7 +161,6 @@ router:
|
||||
## router resource utilization when under heavy workloads.
|
||||
##
|
||||
displayAccessLog: false
|
||||
|
||||
## svcAnnotations is the annotations to be added to the service resource created for router.
|
||||
##
|
||||
# svcAnnotations:
|
||||
@@ -451,7 +454,7 @@ preUpgradeChecks:
|
||||
image: fission/pre-upgrade-checks
|
||||
## 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
|
||||
##
|
||||
@@ -479,6 +482,37 @@ prometheus:
|
||||
canaryDeployment:
|
||||
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.
|
||||
## Note: OpenTracing support will be removed in an upcoming release.
|
||||
## Please prefer using OpenTelemetry instead.
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
/*
|
||||
Copyright 2022 The Fission Authors.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package app
|
||||
|
||||
import (
|
||||
@@ -10,6 +23,7 @@ import (
|
||||
"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/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/function"
|
||||
"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/support"
|
||||
"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/console"
|
||||
"github.com/fission/fission/pkg/fission-cli/flag"
|
||||
@@ -77,11 +92,12 @@ func App() *cobra.Command {
|
||||
})
|
||||
|
||||
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("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("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)
|
||||
|
||||
flagExposer := helptemplate.ActsAsRootCommand(rootCmd, nil, groups...)
|
||||
|
||||
@@ -22,6 +22,7 @@ require (
|
||||
github.com/go-git/go-git/v5 v5.4.2
|
||||
github.com/go-ini/ini v1.63.2 // indirect
|
||||
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/gotestyourself/gotestyourself v2.2.0+incompatible // indirect
|
||||
github.com/graymeta/stow v0.2.7
|
||||
|
||||
@@ -492,7 +492,10 @@ github.com/gogo/protobuf v1.2.2-0.20190730201129-28a6bbf47e48/go.mod h1:SlYgWuQ5
|
||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
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/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/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
|
||||
@@ -16,6 +16,10 @@ limitations under the License.
|
||||
|
||||
package v1
|
||||
|
||||
var (
|
||||
MinimumKubernetesVersion = [3]int{1, 19, 0}
|
||||
)
|
||||
|
||||
const (
|
||||
EXECUTOR_INSTANCEID_LABEL string = "executorInstanceId"
|
||||
DEFAULT_FUNCTION_TIMEOUT int = 60
|
||||
@@ -140,10 +144,8 @@ const (
|
||||
FissionBuilderSA = "fission-builder"
|
||||
FissionFetcherSA = "fission-fetcher"
|
||||
|
||||
SecretConfigMapGetterCR = "secret-configmap-getter"
|
||||
SecretConfigMapGetterRB = "secret-configmap-getter-binding"
|
||||
|
||||
PackageGetterCR = "package-getter"
|
||||
PackageGetterRB = "package-getter-binding"
|
||||
|
||||
ClusterRole = "ClusterRole"
|
||||
|
||||
@@ -854,6 +854,18 @@ type (
|
||||
GetObjectKind() schema.ObjectKind
|
||||
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
|
||||
|
||||
@@ -47,6 +47,22 @@ func (in *Archive) DeepCopy() *Archive {
|
||||
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.
|
||||
func (in *Builder) DeepCopyInto(out *Builder) {
|
||||
*out = *in
|
||||
@@ -883,6 +899,22 @@ func (in *PackageStatus) DeepCopy() *PackageStatus {
|
||||
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.
|
||||
func (in *Runtime) DeepCopyInto(out *Runtime) {
|
||||
*out = *in
|
||||
|
||||
@@ -22,6 +22,14 @@ func (Archive) SwaggerDoc() map[string]string {
|
||||
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{
|
||||
"": "Builder is the setting for environment builder.",
|
||||
"image": "Image for containing the language compilation environment.",
|
||||
@@ -370,6 +378,14 @@ func (PackageStatus) SwaggerDoc() map[string]string {
|
||||
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{
|
||||
"": "Runtime is the setting for environment runtime.",
|
||||
"image": "Image for containing the language runtime.",
|
||||
|
||||
@@ -167,7 +167,7 @@ func (pkgw *packageWatcher) build(ctx context.Context, srcpkg *fv1.Package) {
|
||||
// Add the package getter rolebinding to builder sa
|
||||
// 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
|
||||
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 {
|
||||
pkgw.logger.Error("error setting up role binding for package",
|
||||
zap.Error(err),
|
||||
|
||||
@@ -23,7 +23,9 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
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/fission-cli/console"
|
||||
@@ -62,6 +64,9 @@ func (c *Misc) SecretExists(m *metav1.ObjectMeta) error {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode >= 400 {
|
||||
return k8serrors.NewNotFound(schema.GroupResource{Group: "", Resource: "secret"}, m.Name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -74,6 +79,9 @@ func (c *Misc) ConfigMapExists(m *metav1.ObjectMeta) error {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode >= 400 {
|
||||
return k8serrors.NewNotFound(schema.GroupResource{Group: "", Resource: "configmap"}, m.Name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,8 @@ func MakeErrorFromHTTP(resp *http.Response) error {
|
||||
errCode = ErrorRequestTimeout
|
||||
case http.StatusTooManyRequests:
|
||||
errCode = ErrorTooManyRequests
|
||||
case http.StatusUnauthorized:
|
||||
errCode = ErrorNotAuthorized
|
||||
default:
|
||||
errCode = ErrorInternal
|
||||
}
|
||||
|
||||
@@ -172,6 +172,9 @@ func (cn *Container) getDeploymentSpec(ctx context.Context, fn *fv1.Function, ta
|
||||
}
|
||||
|
||||
gracePeriodSeconds := int64(6 * 60)
|
||||
if *fn.Spec.PodSpec.TerminationGracePeriodSeconds >= 0 {
|
||||
gracePeriodSeconds = *fn.Spec.PodSpec.TerminationGracePeriodSeconds
|
||||
}
|
||||
|
||||
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
|
||||
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 {
|
||||
deploy.logger.Error("error creating role binding for function",
|
||||
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
|
||||
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 {
|
||||
deploy.logger.Error("error creating role binding for function",
|
||||
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 :
|
||||
// 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.
|
||||
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 {
|
||||
logger.Error("error creating rolebinding", zap.Error(err), zap.String("role_binding", fv1.SecretConfigMapGetterRB))
|
||||
} else {
|
||||
@@ -185,7 +185,7 @@ func FunctionEventHandlers(logger *zap.Logger, kubernetesClient *kubernetes.Clie
|
||||
}
|
||||
ctx := context.Background()
|
||||
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)
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -47,7 +47,7 @@ func PackageEventHandlers(logger *zap.Logger, kubernetesClient *kubernetes.Clien
|
||||
ctx := context.Background()
|
||||
// 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.
|
||||
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 {
|
||||
logger.Error("error creating rolebinding for package",
|
||||
zap.Error(err),
|
||||
@@ -83,7 +83,7 @@ func PackageEventHandlers(logger *zap.Logger, kubernetesClient *kubernetes.Clien
|
||||
|
||||
ctx := context.Background()
|
||||
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)
|
||||
if err != nil {
|
||||
logger.Error("error updating rolebinding for package",
|
||||
|
||||
@@ -16,6 +16,8 @@ limitations under the License.
|
||||
|
||||
package featureconfig
|
||||
|
||||
import "time"
|
||||
|
||||
const (
|
||||
FeatureConfigFile = "/etc/config/config.yaml"
|
||||
CanaryFeature = "canary"
|
||||
@@ -31,6 +33,7 @@ type (
|
||||
FeatureConfig struct {
|
||||
// In the future more such feature configs can be added here for each optional feature
|
||||
CanaryConfig CanaryFeatureConfig `json:"canary"`
|
||||
AuthConfig AuthFeatureConfig `json:"auth"`
|
||||
}
|
||||
|
||||
// specific feature config
|
||||
@@ -38,4 +41,11 @@ type (
|
||||
IsEnabled bool `json:"enabled"`
|
||||
PrometheusSvc string `json:"prometheusSvc"`
|
||||
}
|
||||
|
||||
AuthFeatureConfig struct {
|
||||
IsEnabled bool `json:"enabled"`
|
||||
AuthUriPath string `json:"authUriPath"`
|
||||
JWTExpiryTime time.Duration `json:"jwtExpiryTime"`
|
||||
JWTIssuer string `json:"jwtIssuer"`
|
||||
}
|
||||
)
|
||||
|
||||
@@ -65,7 +65,7 @@ func Commands() *cobra.Command {
|
||||
}
|
||||
wrapper.SetFlags(deleteCmd, flag.FlagSet{
|
||||
Required: []flag.Flag{flag.CanaryName},
|
||||
Optional: []flag.Flag{flag.NamespaceCanary},
|
||||
Optional: []flag.Flag{flag.NamespaceCanary, flag.IgnoreNotFound},
|
||||
})
|
||||
|
||||
listCmd := &cobra.Command{
|
||||
|
||||
@@ -25,6 +25,7 @@ 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/fission-cli/util"
|
||||
)
|
||||
|
||||
type DeleteSubCommand struct {
|
||||
@@ -43,6 +44,9 @@ func (opts *DeleteSubCommand) run(input cli.Input) error {
|
||||
|
||||
err := opts.Client().V1().CanaryConfig().Delete(m)
|
||||
if err != nil {
|
||||
if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(err, "error deleting canary config")
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
Copyright 2022 The Fission Authors.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package check
|
||||
|
||||
import (
|
||||
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
|
||||
"github.com/fission/fission/pkg/fission-cli/cmd"
|
||||
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
|
||||
"github.com/fission/fission/pkg/healthcheck"
|
||||
)
|
||||
|
||||
type CheckSubCommand struct {
|
||||
cmd.CommandActioner
|
||||
}
|
||||
|
||||
func Check(input cli.Input) error {
|
||||
return (&CheckSubCommand{}).do(input)
|
||||
}
|
||||
|
||||
func (opts *CheckSubCommand) do(input cli.Input) error {
|
||||
|
||||
kubeContext := input.String(flagkey.KubeContext)
|
||||
|
||||
checks := []healthcheck.CategoryID{}
|
||||
|
||||
if input.IsSet(flagkey.PreCheckOnly) {
|
||||
checks = append(checks, healthcheck.Kubernetes)
|
||||
} else {
|
||||
checks = append(checks, healthcheck.FissionServices, healthcheck.FissionVersion)
|
||||
}
|
||||
|
||||
hc := healthcheck.NewHealthChecker(checks, &healthcheck.Options{
|
||||
KubeContext: kubeContext,
|
||||
FissionClient: opts.Client(),
|
||||
})
|
||||
|
||||
healthcheck.RunChecks(hc)
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
Copyright 2022 The Fission Authors.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package check
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
wrapper "github.com/fission/fission/pkg/fission-cli/cliwrapper/driver/cobra"
|
||||
"github.com/fission/fission/pkg/fission-cli/flag"
|
||||
)
|
||||
|
||||
func Commands() *cobra.Command {
|
||||
command := &cobra.Command{
|
||||
Use: "check",
|
||||
Short: "Check the fission installation for potential problems",
|
||||
Long: `Check the fission installation for potential problems.`,
|
||||
RunE: wrapper.Wrapper(Check),
|
||||
}
|
||||
wrapper.SetFlags(command, flag.FlagSet{
|
||||
Optional: []flag.Flag{flag.PreCheckOnly},
|
||||
})
|
||||
|
||||
return command
|
||||
}
|
||||
@@ -72,7 +72,7 @@ func Commands() *cobra.Command {
|
||||
}
|
||||
wrapper.SetFlags(deleteCmd, flag.FlagSet{
|
||||
Required: []flag.Flag{flag.EnvName},
|
||||
Optional: []flag.Flag{flag.NamespaceEnvironment},
|
||||
Optional: []flag.Flag{flag.NamespaceEnvironment, flag.IgnoreNotFound, flag.EnvForce},
|
||||
})
|
||||
|
||||
listCmd := &cobra.Command{
|
||||
|
||||
@@ -25,6 +25,7 @@ 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/fission-cli/util"
|
||||
)
|
||||
|
||||
type DeleteSubCommand struct {
|
||||
@@ -41,11 +42,29 @@ func (opts *DeleteSubCommand) do(input cli.Input) error {
|
||||
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)
|
||||
if err != nil {
|
||||
if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(err, "error deleting environment")
|
||||
}
|
||||
|
||||
fmt.Printf("environment '%v' deleted\n", m.Name)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ func Commands() *cobra.Command {
|
||||
}
|
||||
wrapper.SetFlags(deleteCmd, flag.FlagSet{
|
||||
Required: []flag.Flag{flag.FnName},
|
||||
Optional: []flag.Flag{flag.NamespaceFunction},
|
||||
Optional: []flag.Flag{flag.NamespaceFunction, flag.IgnoreNotFound},
|
||||
})
|
||||
|
||||
listCmd := &cobra.Command{
|
||||
@@ -167,6 +167,7 @@ func Commands() *cobra.Command {
|
||||
flag.FnCfgMap, flag.FnSecret,
|
||||
flag.FnExecutionTimeout,
|
||||
flag.FnIdleTimeout,
|
||||
flag.FnTerminationGracePeriod,
|
||||
flag.Labels, flag.Annotation,
|
||||
|
||||
// flag for newdeploy to use.
|
||||
|
||||
@@ -128,7 +128,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
|
||||
|
||||
if toSpec {
|
||||
|
||||
fr, err := spec.ReadSpecs(specDir, specIgnore)
|
||||
fr, err := spec.ReadSpecs(specDir, specIgnore, false)
|
||||
if err != nil {
|
||||
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 {
|
||||
|
||||
fr, err := spec.ReadSpecs(specDir, specIgnore)
|
||||
fr, err := spec.ReadSpecs(specDir, specIgnore, false)
|
||||
if err != nil {
|
||||
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/cmd"
|
||||
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
|
||||
"github.com/fission/fission/pkg/fission-cli/util"
|
||||
)
|
||||
|
||||
type DeleteSubCommand struct {
|
||||
@@ -43,6 +44,9 @@ func (opts *DeleteSubCommand) do(input cli.Input) error {
|
||||
|
||||
err := opts.Client().V1().Function().Delete(m)
|
||||
if err != nil {
|
||||
if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
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 port int
|
||||
var command, args string
|
||||
@@ -205,7 +210,8 @@ func (opts *RunContainerSubCommand) complete(input cli.Input) error {
|
||||
}
|
||||
|
||||
opts.function.Spec.PodSpec = &apiv1.PodSpec{
|
||||
Containers: []apiv1.Container{*container},
|
||||
Containers: []apiv1.Container{*container},
|
||||
TerminationGracePeriodSeconds: &fnGracePeriod,
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -18,8 +18,10 @@ package function
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"os"
|
||||
"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")
|
||||
}
|
||||
|
||||
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 {
|
||||
headerKeyValue := strings.SplitN(header, ":", 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])
|
||||
}
|
||||
|
||||
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)}
|
||||
resp, err := hc.Do(req.WithContext(ctx))
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ func Commands() *cobra.Command {
|
||||
RunE: wrapper.Wrapper(Delete),
|
||||
}
|
||||
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{
|
||||
|
||||
@@ -135,7 +135,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
|
||||
if input.Bool(flagkey.SpecSave) {
|
||||
specDir := util.GetSpecDir(input)
|
||||
specIgnore := util.GetSpecIgnore(input)
|
||||
fr, err := spec.ReadSpecs(specDir, specIgnore)
|
||||
fr, err := spec.ReadSpecs(specDir, specIgnore, false)
|
||||
if err != nil {
|
||||
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/cmd"
|
||||
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
|
||||
"github.com/fission/fission/pkg/fission-cli/util"
|
||||
"github.com/fission/fission/pkg/utils"
|
||||
)
|
||||
|
||||
@@ -94,6 +95,9 @@ func (opts *DeleteSubCommand) run(input cli.Input) error {
|
||||
}
|
||||
|
||||
if errs.ErrorOrNil() != nil {
|
||||
if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(errs.ErrorOrNil(), "error deleting trigger(s)")
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ func Commands() *cobra.Command {
|
||||
}
|
||||
wrapper.SetFlags(deleteCmd, flag.FlagSet{
|
||||
Required: []flag.Flag{flag.KwFnName},
|
||||
Optional: []flag.Flag{flag.NamespaceTrigger},
|
||||
Optional: []flag.Flag{flag.NamespaceTrigger, flag.IgnoreNotFound},
|
||||
})
|
||||
|
||||
listCmd := &cobra.Command{
|
||||
|
||||
@@ -67,7 +67,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
|
||||
if input.Bool(flagkey.SpecSave) {
|
||||
specDir := util.GetSpecDir(input)
|
||||
specIgnore := util.GetSpecIgnore(input)
|
||||
fr, err := spec.ReadSpecs(specDir, specIgnore)
|
||||
fr, err := spec.ReadSpecs(specDir, specIgnore, false)
|
||||
if err != nil {
|
||||
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/cmd"
|
||||
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
|
||||
"github.com/fission/fission/pkg/fission-cli/util"
|
||||
)
|
||||
|
||||
type DeleteSubCommand struct {
|
||||
@@ -57,6 +58,9 @@ func (opts *DeleteSubCommand) run(input cli.Input) error {
|
||||
Namespace: opts.namespace,
|
||||
})
|
||||
if err != nil {
|
||||
if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(err, "error deleting kubewatch")
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ func Commands() *cobra.Command {
|
||||
}
|
||||
wrapper.SetFlags(deleteCmd, flag.FlagSet{
|
||||
Required: []flag.Flag{flag.MqtName},
|
||||
Optional: []flag.Flag{flag.NamespaceTrigger},
|
||||
Optional: []flag.Flag{flag.NamespaceTrigger, flag.IgnoreNotFound},
|
||||
})
|
||||
|
||||
listCmd := &cobra.Command{
|
||||
|
||||
@@ -128,7 +128,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
|
||||
if input.Bool(flagkey.SpecSave) {
|
||||
specDir := util.GetSpecDir(input)
|
||||
specIgnore := util.GetSpecIgnore(input)
|
||||
fr, err := spec.ReadSpecs(specDir, specIgnore)
|
||||
fr, err := spec.ReadSpecs(specDir, specIgnore, false)
|
||||
if err != nil {
|
||||
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",
|
||||
mqtName, fnName))
|
||||
}
|
||||
} else {
|
||||
err = util.CheckFunctionExistence(opts.Client(), []string{fnName}, fnNamespace)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
opts.trigger = &fv1.MessageQueueTrigger{
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
|
||||
"github.com/fission/fission/pkg/fission-cli/cmd"
|
||||
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
|
||||
"github.com/fission/fission/pkg/fission-cli/util"
|
||||
)
|
||||
|
||||
type DeleteSubCommand struct {
|
||||
@@ -55,6 +56,9 @@ func (opts *DeleteSubCommand) complete(input cli.Input) error {
|
||||
func (opts *DeleteSubCommand) run(input cli.Input) error {
|
||||
err := opts.Client().V1().MessageQueueTrigger().Delete(opts.metadata)
|
||||
if err != nil {
|
||||
if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(err, "error deleting message queue trigger")
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ func Commands() *cobra.Command {
|
||||
RunE: wrapper.Wrapper(Delete),
|
||||
}
|
||||
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{
|
||||
|
||||
@@ -87,7 +87,7 @@ func (opts *CreateSubCommand) run(input cli.Input) error {
|
||||
if input.Bool(flagkey.SpecSave) {
|
||||
specDir = util.GetSpecDir(input)
|
||||
specIgnore := util.GetSpecIgnore(input)
|
||||
fr, err := spec.ReadSpecs(specDir, specIgnore)
|
||||
fr, err := spec.ReadSpecs(specDir, specIgnore, false)
|
||||
if err != nil {
|
||||
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 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 {
|
||||
return nil, errors.Wrap(err, "error reading specs")
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
|
||||
"github.com/fission/fission/pkg/fission-cli/cmd"
|
||||
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
|
||||
"github.com/fission/fission/pkg/fission-cli/util"
|
||||
)
|
||||
|
||||
type DeleteSubCommand struct {
|
||||
@@ -68,6 +69,9 @@ func (opts *DeleteSubCommand) run(input cli.Input) error {
|
||||
Name: opts.name,
|
||||
})
|
||||
if err != nil {
|
||||
if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(err, "find package")
|
||||
}
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ func CreateArchive(client client.Interface, input cli.Input, includeFiles []stri
|
||||
} else if input.Bool(flagkey.SpecSave) {
|
||||
// check if this AUS exists in the specs; if so, don't create a new one
|
||||
specIgnore := util.GetSpecIgnore(input)
|
||||
fr, err := spec.ReadSpecs(specDir, specIgnore)
|
||||
fr, err := spec.ReadSpecs(specDir, specIgnore, false)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error reading specs")
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ func (opts *ApplySubCommand) do(input cli.Input) error {
|
||||
func (opts *ApplySubCommand) run(input cli.Input) error {
|
||||
specDir := util.GetSpecDir(input)
|
||||
specIgnore := util.GetSpecIgnore(input)
|
||||
|
||||
applyCommitLabel := input.Bool(flagkey.SpecApplyCommitLabel)
|
||||
deleteResources := input.Bool(flagkey.SpecDelete)
|
||||
watchResources := input.Bool(flagkey.SpecWatch)
|
||||
waitForBuild := input.Bool(flagkey.SpecWait)
|
||||
@@ -112,7 +112,7 @@ func (opts *ApplySubCommand) run(input cli.Input) error {
|
||||
|
||||
for {
|
||||
// read all specs
|
||||
fr, err := ReadSpecs(specDir, specIgnore)
|
||||
fr, err := ReadSpecs(specDir, specIgnore, applyCommitLabel)
|
||||
if err != nil {
|
||||
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
|
||||
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 {
|
||||
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.
|
||||
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)
|
||||
|
||||
@@ -367,13 +367,13 @@ func applyResources(fclient client.Interface, specDir string, fr *FissionResourc
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
_, ras, err := applyEnvironments(fclient, fr, delete)
|
||||
_, ras, err := applyEnvironments(fclient, fr, delete, specAllowConflicts)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "environment apply failed")
|
||||
}
|
||||
applyStatus["environment"] = *ras
|
||||
|
||||
pkgMeta, ras, err := applyPackages(fclient, fr, delete)
|
||||
pkgMeta, ras, err := applyPackages(fclient, fr, delete, specAllowConflicts)
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
|
||||
_, ras, err = applyFunctions(fclient, fr, delete)
|
||||
_, ras, err = applyFunctions(fclient, fr, delete, specAllowConflicts)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "function apply failed")
|
||||
}
|
||||
applyStatus["function"] = *ras
|
||||
|
||||
_, ras, err = applyHTTPTriggers(fclient, fr, delete)
|
||||
_, ras, err = applyHTTPTriggers(fclient, fr, delete, specAllowConflicts)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "HTTPTrigger apply failed")
|
||||
}
|
||||
applyStatus["HTTPTrigger"] = *ras
|
||||
|
||||
_, ras, err = applyKubernetesWatchTriggers(fclient, fr, delete)
|
||||
_, ras, err = applyKubernetesWatchTriggers(fclient, fr, delete, specAllowConflicts)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "KubernetesWatchTrigger apply failed")
|
||||
}
|
||||
applyStatus["KubernetesWatchTrigger"] = *ras
|
||||
|
||||
_, ras, err = applyTimeTriggers(fclient, fr, delete)
|
||||
_, ras, err = applyTimeTriggers(fclient, fr, delete, specAllowConflicts)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "TimeTrigger apply failed")
|
||||
}
|
||||
applyStatus["TimeTrigger"] = *ras
|
||||
|
||||
_, ras, err = applyMessageQueueTriggers(fclient, fr, delete)
|
||||
_, ras, err = applyMessageQueueTriggers(fclient, fr, delete, specAllowConflicts)
|
||||
if err != nil {
|
||||
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
|
||||
allObjs, err := fclient.V1().Package().List(metav1.NamespaceAll)
|
||||
if err != nil {
|
||||
@@ -585,9 +585,13 @@ func applyPackages(fclient client.Interface, fr *FissionResources, delete bool)
|
||||
|
||||
// filter
|
||||
objs := make([]fv1.Package, 0)
|
||||
for _, o := range allObjs {
|
||||
if hasDeploymentConfig(&o.ObjectMeta, fr) {
|
||||
objs = append(objs, o)
|
||||
if specAllowConflicts {
|
||||
objs = allObjs
|
||||
} 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
|
||||
}
|
||||
|
||||
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
|
||||
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
||||
} else {
|
||||
// update
|
||||
o.ObjectMeta.ResourceVersion = existingObj.ObjectMeta.ResourceVersion
|
||||
|
||||
// We may be racing against the package builder to update the
|
||||
// package (a previous version might have been getting built). So,
|
||||
// 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
|
||||
}
|
||||
|
||||
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
|
||||
allObjs, err := fclient.V1().Function().List(metav1.NamespaceAll)
|
||||
if err != nil {
|
||||
@@ -696,9 +699,13 @@ func applyFunctions(fclient client.Interface, fr *FissionResources, delete bool)
|
||||
|
||||
// filter
|
||||
objs := make([]fv1.Function, 0)
|
||||
for _, o := range allObjs {
|
||||
if hasDeploymentConfig(&o.ObjectMeta, fr) {
|
||||
objs = append(objs, o)
|
||||
if specAllowConflicts {
|
||||
objs = allObjs
|
||||
} 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)]
|
||||
if ok {
|
||||
// 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
|
||||
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
||||
} else {
|
||||
@@ -770,7 +777,7 @@ func applyFunctions(fclient client.Interface, fr *FissionResources, delete bool)
|
||||
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
|
||||
allObjs, err := fclient.V1().Environment().List(metav1.NamespaceAll)
|
||||
if err != nil {
|
||||
@@ -779,9 +786,13 @@ func applyEnvironments(fclient client.Interface, fr *FissionResources, delete bo
|
||||
|
||||
// filter
|
||||
objs := make([]fv1.Environment, 0)
|
||||
for _, o := range allObjs {
|
||||
if hasDeploymentConfig(&o.ObjectMeta, fr) {
|
||||
objs = append(objs, o)
|
||||
if specAllowConflicts {
|
||||
objs = allObjs
|
||||
} 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)]
|
||||
if ok {
|
||||
// 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
|
||||
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
||||
} else {
|
||||
@@ -853,7 +864,7 @@ func applyEnvironments(fclient client.Interface, fr *FissionResources, delete bo
|
||||
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
|
||||
allObjs, err := fclient.V1().HTTPTrigger().List(metav1.NamespaceAll)
|
||||
if err != nil {
|
||||
@@ -862,9 +873,13 @@ func applyHTTPTriggers(fclient client.Interface, fr *FissionResources, delete bo
|
||||
|
||||
// filter
|
||||
objs := make([]fv1.HTTPTrigger, 0)
|
||||
for _, o := range allObjs {
|
||||
if hasDeploymentConfig(&o.ObjectMeta, fr) {
|
||||
objs = append(objs, o)
|
||||
if specAllowConflicts {
|
||||
objs = allObjs
|
||||
} 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)]
|
||||
if ok {
|
||||
// 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
|
||||
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
||||
} else {
|
||||
@@ -936,7 +951,7 @@ func applyHTTPTriggers(fclient client.Interface, fr *FissionResources, delete bo
|
||||
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
|
||||
allObjs, err := fclient.V1().KubeWatcher().List(metav1.NamespaceAll)
|
||||
if err != nil {
|
||||
@@ -945,9 +960,13 @@ func applyKubernetesWatchTriggers(fclient client.Interface, fr *FissionResources
|
||||
|
||||
// filter
|
||||
objs := make([]fv1.KubernetesWatchTrigger, 0)
|
||||
for _, o := range allObjs {
|
||||
if hasDeploymentConfig(&o.ObjectMeta, fr) {
|
||||
objs = append(objs, o)
|
||||
if specAllowConflicts {
|
||||
objs = allObjs
|
||||
} 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)]
|
||||
if ok {
|
||||
// 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
|
||||
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
||||
} else {
|
||||
@@ -1019,7 +1038,7 @@ func applyKubernetesWatchTriggers(fclient client.Interface, fr *FissionResources
|
||||
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
|
||||
allObjs, err := fclient.V1().TimeTrigger().List(metav1.NamespaceAll)
|
||||
if err != nil {
|
||||
@@ -1028,9 +1047,13 @@ func applyTimeTriggers(fclient client.Interface, fr *FissionResources, delete bo
|
||||
|
||||
// filter
|
||||
objs := make([]fv1.TimeTrigger, 0)
|
||||
for _, o := range allObjs {
|
||||
if hasDeploymentConfig(&o.ObjectMeta, fr) {
|
||||
objs = append(objs, o)
|
||||
if specAllowConflicts {
|
||||
objs = allObjs
|
||||
} 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)]
|
||||
if ok {
|
||||
// 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
|
||||
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
||||
} else {
|
||||
@@ -1102,7 +1125,7 @@ func applyTimeTriggers(fclient client.Interface, fr *FissionResources, delete bo
|
||||
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
|
||||
allObjs, err := fclient.V1().MessageQueueTrigger().List("", metav1.NamespaceAll)
|
||||
if err != nil {
|
||||
@@ -1111,9 +1134,13 @@ func applyMessageQueueTriggers(fclient client.Interface, fr *FissionResources, d
|
||||
|
||||
// filter
|
||||
objs := make([]fv1.MessageQueueTrigger, 0)
|
||||
for _, o := range allObjs {
|
||||
if hasDeploymentConfig(&o.ObjectMeta, fr) {
|
||||
objs = append(objs, o)
|
||||
if specAllowConflicts {
|
||||
objs = allObjs
|
||||
} 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)]
|
||||
if ok {
|
||||
// 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
|
||||
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
||||
} else {
|
||||
@@ -1184,3 +1211,7 @@ func applyMessageQueueTriggers(fclient client.Interface, fr *FissionResources, d
|
||||
|
||||
return metadataMap, &ras, nil
|
||||
}
|
||||
|
||||
func isObjectMetaEqual(existingObj, newObj metav1.ObjectMeta) bool {
|
||||
return reflect.DeepEqual(existingObj.Labels, newObj.Labels) && reflect.DeepEqual(existingObj.Annotations, newObj.Annotations)
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ func Commands() *cobra.Command {
|
||||
RunE: wrapper.Wrapper(Validate),
|
||||
}
|
||||
wrapper.SetFlags(validateCmd, flag.FlagSet{
|
||||
Optional: []flag.Flag{flag.SpecDir, flag.SpecIgnore},
|
||||
Optional: []flag.Flag{flag.SpecDir, flag.SpecIgnore, flag.SpecAllowConflicts},
|
||||
})
|
||||
|
||||
applyCmd := &cobra.Command{
|
||||
@@ -48,7 +48,7 @@ func Commands() *cobra.Command {
|
||||
RunE: wrapper.Wrapper(Apply),
|
||||
}
|
||||
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{
|
||||
|
||||
@@ -19,6 +19,7 @@ package spec
|
||||
import (
|
||||
"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/cmd"
|
||||
"github.com/fission/fission/pkg/fission-cli/util"
|
||||
@@ -43,7 +44,7 @@ func (opts *DestroySubCommand) run(input cli.Input) error {
|
||||
specIgnore := util.GetSpecIgnore(input)
|
||||
|
||||
// read everything
|
||||
fr, err := ReadSpecs(specDir, specIgnore)
|
||||
fr, err := ReadSpecs(specDir, specIgnore, false)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error reading specs")
|
||||
}
|
||||
@@ -53,10 +54,52 @@ func (opts *DestroySubCommand) run(input cli.Input) error {
|
||||
emptyFr.DeploymentConfig = fr.DeploymentConfig
|
||||
|
||||
// "apply" the empty state
|
||||
_, _, err = applyResources(opts.Client(), specDir, &emptyFr, true)
|
||||
err = deleteResources(opts.Client(), &emptyFr)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error deleting resources")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteResources(fclient client.Interface, fr *FissionResources) error {
|
||||
|
||||
var err error
|
||||
|
||||
_, _, err = applyHTTPTriggers(fclient, fr, true, false)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "HTTPTrigger delete failed")
|
||||
}
|
||||
|
||||
_, _, err = applyKubernetesWatchTriggers(fclient, fr, true, false)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "KubernetesWatchTrigger delete failed")
|
||||
}
|
||||
|
||||
_, _, err = applyTimeTriggers(fclient, fr, true, false)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "TimeTrigger delete failed")
|
||||
}
|
||||
|
||||
_, _, err = applyMessageQueueTriggers(fclient, fr, true, false)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "MessageQueueTrigger delete failed")
|
||||
}
|
||||
|
||||
_, _, err = applyFunctions(fclient, fr, true, false)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "function delete failed")
|
||||
}
|
||||
|
||||
_, _, err = applyPackages(fclient, fr, true, false)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "package delete failed")
|
||||
}
|
||||
|
||||
_, _, err = applyEnvironments(fclient, fr, true, false)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "environment delete failed")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ func (opts *ListSubCommand) run(input cli.Input) error {
|
||||
// get specdir, specignore and read the deployID
|
||||
specDir := util.GetSpecDir(input)
|
||||
specIgnore := util.GetSpecIgnore(input)
|
||||
fr, err := ReadSpecs(specDir, specIgnore)
|
||||
fr, err := ReadSpecs(specDir, specIgnore, false)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error reading specs")
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ func SpecSave(resource interface{}, specFile string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
fr, err := ReadSpecs(specDir, util.SPEC_IGNORE_FILE)
|
||||
fr, err := ReadSpecs(specDir, util.SPEC_IGNORE_FILE, false)
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
|
||||
// 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
|
||||
// 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
|
||||
|
||||
// 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))
|
||||
}
|
||||
m = &v.ObjectMeta
|
||||
applyCommitLabel(commitLabelVal, m)
|
||||
fr.Packages = append(fr.Packages, v)
|
||||
case "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))
|
||||
}
|
||||
m = &v.ObjectMeta
|
||||
applyCommitLabel(commitLabelVal, m)
|
||||
fr.Functions = append(fr.Functions, v)
|
||||
case "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))
|
||||
}
|
||||
m = &v.ObjectMeta
|
||||
applyCommitLabel(commitLabelVal, m)
|
||||
fr.Environments = append(fr.Environments, v)
|
||||
case "HTTPTrigger":
|
||||
var v fv1.HTTPTrigger
|
||||
@@ -570,8 +583,8 @@ func (fr *FissionResources) ParseYaml(b []byte, loc *Location) error {
|
||||
if err != nil {
|
||||
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
||||
}
|
||||
|
||||
m = &v.ObjectMeta
|
||||
applyCommitLabel(commitLabelVal, m)
|
||||
fr.HttpTriggers = append(fr.HttpTriggers, v)
|
||||
case "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))
|
||||
}
|
||||
m = &v.ObjectMeta
|
||||
applyCommitLabel(commitLabelVal, m)
|
||||
fr.KubernetesWatchTriggers = append(fr.KubernetesWatchTriggers, v)
|
||||
case "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))
|
||||
}
|
||||
m = &v.ObjectMeta
|
||||
applyCommitLabel(commitLabelVal, m)
|
||||
fr.TimeTriggers = append(fr.TimeTriggers, v)
|
||||
case "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))
|
||||
}
|
||||
m = &v.ObjectMeta
|
||||
applyCommitLabel(commitLabelVal, m)
|
||||
fr.MessageQueueTriggers = append(fr.MessageQueueTriggers, v)
|
||||
|
||||
// The following are not CRDs
|
||||
@@ -606,6 +622,7 @@ func (fr *FissionResources) ParseYaml(b []byte, loc *Location) error {
|
||||
if err != nil {
|
||||
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
||||
}
|
||||
|
||||
fr.DeploymentConfig = v
|
||||
case "ArchiveUploadSpec":
|
||||
var v types.ArchiveUploadSpec
|
||||
@@ -613,10 +630,12 @@ func (fr *FissionResources) ParseYaml(b []byte, loc *Location) error {
|
||||
if err != nil {
|
||||
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
||||
}
|
||||
|
||||
m = &metav1.ObjectMeta{
|
||||
Name: v.Name,
|
||||
Namespace: "",
|
||||
}
|
||||
applyCommitLabel(commitLabelVal, m)
|
||||
fr.ArchiveUploadSpecs = append(fr.ArchiveUploadSpecs, v)
|
||||
default:
|
||||
// no need to error out just because there's some extra files around;
|
||||
|
||||
@@ -31,8 +31,10 @@ import (
|
||||
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
|
||||
"github.com/fission/fission/pkg/fission-cli/cmd"
|
||||
"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/utils"
|
||||
"github.com/fission/fission/pkg/utils/gitrepo"
|
||||
)
|
||||
|
||||
type ValidateSubCommand struct {
|
||||
@@ -54,7 +56,7 @@ func (opts *ValidateSubCommand) run(input cli.Input) error {
|
||||
// this will error on parse errors and on duplicates
|
||||
specDir := util.GetSpecDir(input)
|
||||
specIgnore := util.GetSpecIgnore(input)
|
||||
fr, err := ReadSpecs(specDir, specIgnore)
|
||||
fr, err := ReadSpecs(specDir, specIgnore, false)
|
||||
if err != nil {
|
||||
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")
|
||||
}
|
||||
|
||||
err = resourceConflictCheck(opts.Client(), fr)
|
||||
err = resourceConflictCheck(opts.Client(), fr, input.Bool(flagkey.SpecAllowConflicts))
|
||||
if err != nil {
|
||||
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.
|
||||
// If a same name resource exists in the same namespace, a name
|
||||
// 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
|
||||
result := utils.MultiErrorWithFormat()
|
||||
|
||||
@@ -98,7 +100,7 @@ func resourceConflictCheck(c client.Interface, fr *FissionResources) error {
|
||||
}
|
||||
for _, sObj := range fr.Functions {
|
||||
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)
|
||||
break
|
||||
}
|
||||
@@ -111,7 +113,7 @@ func resourceConflictCheck(c client.Interface, fr *FissionResources) error {
|
||||
}
|
||||
for _, sObj := range fr.Environments {
|
||||
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)
|
||||
break
|
||||
}
|
||||
@@ -124,7 +126,7 @@ func resourceConflictCheck(c client.Interface, fr *FissionResources) error {
|
||||
}
|
||||
for _, sObj := range fr.Packages {
|
||||
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)
|
||||
break
|
||||
}
|
||||
@@ -137,7 +139,7 @@ func resourceConflictCheck(c client.Interface, fr *FissionResources) error {
|
||||
}
|
||||
for _, sObj := range fr.HttpTriggers {
|
||||
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)
|
||||
break
|
||||
}
|
||||
@@ -150,7 +152,7 @@ func resourceConflictCheck(c client.Interface, fr *FissionResources) error {
|
||||
}
|
||||
for _, sObj := range fr.MessageQueueTriggers {
|
||||
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)
|
||||
break
|
||||
}
|
||||
@@ -163,7 +165,7 @@ func resourceConflictCheck(c client.Interface, fr *FissionResources) error {
|
||||
}
|
||||
for _, sObj := range fr.TimeTriggers {
|
||||
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)
|
||||
break
|
||||
}
|
||||
@@ -176,7 +178,7 @@ func resourceConflictCheck(c client.Interface, fr *FissionResources) error {
|
||||
}
|
||||
for _, sObj := range fr.KubernetesWatchTriggers {
|
||||
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)
|
||||
break
|
||||
}
|
||||
@@ -186,10 +188,13 @@ func resourceConflictCheck(c client.Interface, fr *FissionResources) error {
|
||||
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() &&
|
||||
specObj.GetObjectMeta().GetNamespace() == clusterObj.GetObjectMeta().GetNamespace() &&
|
||||
deployUID != clusterObj.GetObjectMeta().GetAnnotations()[FISSION_DEPLOYMENT_UID_KEY] {
|
||||
if specAllowConflicts {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("%v: '%v/%v' with different deploy uid already exists",
|
||||
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
|
||||
// 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
|
||||
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
|
||||
|
||||
// Users can organize the specdir into subdirs if they want to.
|
||||
@@ -239,16 +259,24 @@ func ReadSpecs(specDir, specIgnore string) (*FissionResources, error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// check if file matches any path in .specignore file
|
||||
if ignoreParser.MatchesPath(path) {
|
||||
return nil
|
||||
}
|
||||
|
||||
var fileCommitLabelVal string
|
||||
// check if applyCommitLabel is true and specdir is tracked by git repo
|
||||
if applyCommitLabel {
|
||||
fileCommitLabelVal, _ = gr.GetFileCommitLabel(path)
|
||||
}
|
||||
|
||||
// read
|
||||
b, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
result = multierror.Append(result, err)
|
||||
return nil
|
||||
}
|
||||
|
||||
// handle the case where there are multiple YAML docs per file. go-yaml
|
||||
// doesn't support this directly, yet.
|
||||
docs := bytes.Split(b, []byte("\n---"))
|
||||
@@ -260,7 +288,7 @@ func ReadSpecs(specDir, specIgnore string) (*FissionResources, error) {
|
||||
err = fr.ParseYaml(d, &Location{
|
||||
Path: path,
|
||||
Line: lines,
|
||||
})
|
||||
}, fileCommitLabelVal)
|
||||
if err != nil {
|
||||
// collect all errors so user can fix them all
|
||||
result = multierror.Append(result, err)
|
||||
|
||||
@@ -53,7 +53,7 @@ func Commands() *cobra.Command {
|
||||
}
|
||||
wrapper.SetFlags(deleteCmd, flag.FlagSet{
|
||||
Required: []flag.Flag{flag.TtName},
|
||||
Optional: []flag.Flag{flag.NamespaceTrigger},
|
||||
Optional: []flag.Flag{flag.NamespaceTrigger, flag.IgnoreNotFound},
|
||||
})
|
||||
|
||||
listCmd := &cobra.Command{
|
||||
|
||||
@@ -78,7 +78,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
|
||||
if input.Bool(flagkey.SpecSave) {
|
||||
specDir := util.GetSpecDir(input)
|
||||
specIgnore := util.GetSpecIgnore(input)
|
||||
fr, err := spec.ReadSpecs(specDir, specIgnore)
|
||||
fr, err := spec.ReadSpecs(specDir, specIgnore, false)
|
||||
if err != nil {
|
||||
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/cmd"
|
||||
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
|
||||
"github.com/fission/fission/pkg/fission-cli/util"
|
||||
)
|
||||
|
||||
type DeleteSubCommand struct {
|
||||
@@ -43,6 +44,9 @@ func (opts *DeleteSubCommand) do(input cli.Input) error {
|
||||
|
||||
err := opts.Client().V1().TimeTrigger().Delete(m)
|
||||
if err != nil {
|
||||
if input.Bool(flagkey.IgnoreNotFound) && util.IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(err, "error deleting trigger")
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright 2022 The Fission Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package token
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
wrapper "github.com/fission/fission/pkg/fission-cli/cliwrapper/driver/cobra"
|
||||
"github.com/fission/fission/pkg/fission-cli/flag"
|
||||
)
|
||||
|
||||
func Commands() *cobra.Command {
|
||||
createCmd := &cobra.Command{
|
||||
Use: "create",
|
||||
Short: "Create a JWT token for function invocation",
|
||||
RunE: wrapper.Wrapper(Create),
|
||||
}
|
||||
wrapper.SetFlags(createCmd, flag.FlagSet{
|
||||
Required: []flag.Flag{flag.TokUsername, flag.TokPassword},
|
||||
Optional: []flag.Flag{flag.TokAuthURI},
|
||||
})
|
||||
|
||||
command := &cobra.Command{
|
||||
Use: "token",
|
||||
Short: "Create a JWT token for function invocation",
|
||||
}
|
||||
|
||||
command.AddCommand(createCmd)
|
||||
|
||||
return command
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
Copyright 2022 The Fission Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package token
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
fv1 "github.com/fission/fission/pkg/apis/core/v1"
|
||||
"github.com/fission/fission/pkg/fission-cli/cliwrapper/cli"
|
||||
"github.com/fission/fission/pkg/fission-cli/cmd"
|
||||
flagkey "github.com/fission/fission/pkg/fission-cli/flag/key"
|
||||
"github.com/fission/fission/pkg/fission-cli/util"
|
||||
)
|
||||
|
||||
type CreateSubCommand struct {
|
||||
cmd.CommandActioner
|
||||
}
|
||||
|
||||
func Create(input cli.Input) error {
|
||||
return (&CreateSubCommand{}).do(input)
|
||||
}
|
||||
|
||||
func (opts *CreateSubCommand) do(input cli.Input) error {
|
||||
return opts.run(input)
|
||||
}
|
||||
|
||||
func (opts *CreateSubCommand) run(input cli.Input) error {
|
||||
|
||||
lb := &fv1.AuthLogin{}
|
||||
|
||||
username := input.String(flagkey.TokUsername)
|
||||
if len(username) != 0 {
|
||||
lb.Username = username
|
||||
}
|
||||
|
||||
password := input.String(flagkey.TokPassword)
|
||||
if len(password) != 0 {
|
||||
lb.Password = password
|
||||
}
|
||||
|
||||
values := map[string]string{"username": username, "password": password}
|
||||
|
||||
jsonValue, _ := json.Marshal(values)
|
||||
|
||||
kubeContext := input.String(flagkey.KubeContext)
|
||||
// Portforward to the fission router
|
||||
localRouterPort, err := util.SetupPortForward(util.GetFissionNamespace(), "application=fission-router", kubeContext)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
authURI, _ := os.LookupEnv("FISSION_AUTH_URI")
|
||||
|
||||
if input.IsSet(flagkey.TokAuthURI) {
|
||||
authURI = input.String(flagkey.TokAuthURI)
|
||||
}
|
||||
|
||||
if len(authURI) == 0 {
|
||||
authURI = util.FISSION_AUTH_URI
|
||||
}
|
||||
|
||||
relativeURL, _ := url.Parse(authURI)
|
||||
serverURL, _ := url.Parse("http://127.0.0.1:" + localRouterPort)
|
||||
authAuthenticatorUrl := serverURL.ResolveReference(relativeURL)
|
||||
|
||||
resp, err := http.Post(authAuthenticatorUrl.String(), "application/json", bytes.NewBuffer(jsonValue))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error creating token")
|
||||
}
|
||||
|
||||
if resp.StatusCode == http.StatusCreated {
|
||||
var rat fv1.RouterAuthToken
|
||||
err = json.Unmarshal(body, &rat)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(rat.AccessToken)
|
||||
} else if resp.StatusCode == http.StatusNotFound {
|
||||
fmt.Printf("%s. Please check if authentication is enabled and correct auth URI is mentioned via --authuri or FISSION_AUTH_URI.\n", resp.Status)
|
||||
} else {
|
||||
fmt.Println(resp.Status)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -74,8 +74,12 @@ var (
|
||||
|
||||
ClientOnly = Flag{Type: Bool, Name: flagkey.ClientOnly, Usage: "If set, the CLI won't connect to remote server"}
|
||||
|
||||
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: ""}
|
||||
|
||||
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\""}
|
||||
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}
|
||||
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"}
|
||||
// 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"}
|
||||
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]"}
|
||||
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"}
|
||||
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"}
|
||||
@@ -145,7 +155,7 @@ var (
|
||||
|
||||
MqtName = Flag{Type: String, Name: flagkey.MqtName, Usage: "Message queue trigger 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"}
|
||||
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"}
|
||||
@@ -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}
|
||||
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: ""}
|
||||
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"}
|
||||
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}
|
||||
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'"}
|
||||
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"}
|
||||
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"}
|
||||
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"}
|
||||
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"}
|
||||
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"}
|
||||
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"}
|
||||
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"}
|
||||
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)}
|
||||
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"}
|
||||
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"}
|
||||
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"}
|
||||
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"}
|
||||
SpecValidation = Flag{Type: String, Name: flagkey.SpecValidate, Usage: "Turns server side validations of Fission objects on/off"}
|
||||
SpecIgnore = Flag{Type: String, Name: flagkey.SpecIgnore, Usage: fmt.Sprintf("File containing specs to be ingored inside --specdir, defaults to %v", util.SPEC_IGNORE_FILE)}
|
||||
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}
|
||||
SupportNoZip = Flag{Type: Bool, Name: flagkey.SupportNoZip, Usage: "Save dump information into multiple files instead of single zip file"}
|
||||
|
||||
@@ -22,6 +22,8 @@ const (
|
||||
ClientOnly = "client-only"
|
||||
KubeContext = "kube-context"
|
||||
|
||||
PreCheckOnly = "pre"
|
||||
|
||||
resourceName = "name"
|
||||
force = "force"
|
||||
Output = "output"
|
||||
@@ -29,6 +31,8 @@ const (
|
||||
Labels = "labels"
|
||||
Annotation = "annotation"
|
||||
|
||||
IgnoreNotFound = "ignorenotfound"
|
||||
|
||||
NamespaceFunction = "fnNamespace"
|
||||
NamespaceEnvironment = "envNamespace"
|
||||
NamespacePackage = "pkgNamespace"
|
||||
@@ -74,6 +78,7 @@ const (
|
||||
FnRequestsPerPod = "requestsperpod"
|
||||
FnOnceOnly = "onceonly"
|
||||
FnSubPath = "subpath"
|
||||
FnGracePeriod = "graceperiod"
|
||||
|
||||
HtName = resourceName
|
||||
HtMethod = "method"
|
||||
@@ -89,6 +94,10 @@ const (
|
||||
HtPrefix = "prefix"
|
||||
HtKeepPrefix = "keepprefix"
|
||||
|
||||
TokUsername = "username"
|
||||
TokPassword = "password"
|
||||
TokAuthURI = "authuri"
|
||||
|
||||
TtName = resourceName
|
||||
TtCron = "cron"
|
||||
TtFnName = "function"
|
||||
@@ -121,6 +130,7 @@ const (
|
||||
EnvVersion = "version"
|
||||
EnvImagePullSecret = "imagepullsecret"
|
||||
EnvExecutorType = "executortype"
|
||||
EnvForce = force
|
||||
|
||||
KwName = resourceName
|
||||
KwFnName = "function"
|
||||
@@ -142,16 +152,18 @@ const (
|
||||
PkgStatus = "status"
|
||||
PkgOrphan = "orphan"
|
||||
|
||||
SpecSave = "spec"
|
||||
SpecDir = "specdir"
|
||||
SpecName = resourceName
|
||||
SpecDeployID = "deployid"
|
||||
SpecWait = "wait"
|
||||
SpecWatch = "watch"
|
||||
SpecDelete = "delete"
|
||||
SpecDry = "dry"
|
||||
SpecValidate = "validation"
|
||||
SpecIgnore = "specignore"
|
||||
SpecSave = "spec"
|
||||
SpecDir = "specdir"
|
||||
SpecName = resourceName
|
||||
SpecDeployID = "deployid"
|
||||
SpecWait = "wait"
|
||||
SpecWatch = "watch"
|
||||
SpecDelete = "delete"
|
||||
SpecDry = "dry"
|
||||
SpecValidate = "validation"
|
||||
SpecIgnore = "specignore"
|
||||
SpecApplyCommitLabel = "commitlabel"
|
||||
SpecAllowConflicts = "allowconflicts"
|
||||
|
||||
SupportOutput = Output
|
||||
SupportNoZip = "nozip"
|
||||
|
||||
@@ -18,5 +18,8 @@ package util
|
||||
|
||||
// fission-cli options
|
||||
const (
|
||||
SPEC_IGNORE_FILE = ".specignore"
|
||||
SPEC_IGNORE_FILE = ".specignore"
|
||||
COMMIT_LABEL = "commit"
|
||||
FISSION_AUTH_URI = "/auth/login"
|
||||
FISSION_AUTH_TOKEN = "FISSION_AUTH_TOKEN"
|
||||
)
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2021 The Fission Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func IsNotFound(err error) bool {
|
||||
return strings.HasSuffix(strings.TrimSpace(err.Error()), "not found")
|
||||
}
|
||||
@@ -74,10 +74,7 @@ func (c *Clientset) Tracker() testing.ObjectTracker {
|
||||
return c.tracker
|
||||
}
|
||||
|
||||
var (
|
||||
_ clientset.Interface = &Clientset{}
|
||||
_ testing.FakeClient = &Clientset{}
|
||||
)
|
||||
var _ clientset.Interface = &Clientset{}
|
||||
|
||||
// CoreV1 retrieves the CoreV1Client
|
||||
func (c *Clientset) CoreV1() corev1.CoreV1Interface {
|
||||
|
||||
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
Copyright 2022 The Fission Authors.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package healthcheck
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/fatih/color"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
|
||||
fv1 "github.com/fission/fission/pkg/apis/core/v1"
|
||||
"github.com/fission/fission/pkg/controller/client"
|
||||
"github.com/fission/fission/pkg/fission-cli/util"
|
||||
)
|
||||
|
||||
type CategoryID string
|
||||
|
||||
const (
|
||||
Kubernetes CategoryID = "kubernetes"
|
||||
FissionServices CategoryID = "fission-services"
|
||||
FissionVersion CategoryID = "fission-version"
|
||||
)
|
||||
|
||||
var (
|
||||
okStatus = color.New(color.FgGreen, color.Bold).SprintFunc()("\u221A") // √
|
||||
failStatus = color.New(color.FgRed, color.Bold).SprintFunc()("\u00D7") // ×
|
||||
)
|
||||
|
||||
// Category is a group of checkers
|
||||
type Category struct {
|
||||
ID CategoryID
|
||||
checkers []Checker
|
||||
enabled bool
|
||||
}
|
||||
|
||||
type Checker struct {
|
||||
successMsg string
|
||||
check func() error
|
||||
}
|
||||
|
||||
type Options struct {
|
||||
KubeContext string
|
||||
FissionClient client.Interface
|
||||
}
|
||||
|
||||
type HealthChecker struct {
|
||||
categories []*Category
|
||||
*Options
|
||||
|
||||
kubeAPI *kubernetes.Clientset
|
||||
fissionNamespace string
|
||||
}
|
||||
|
||||
func isCompatibleVersion(minimalRequirementVersion [3]int, actualVersion [3]int) bool {
|
||||
if minimalRequirementVersion[0] < actualVersion[0] {
|
||||
return true
|
||||
}
|
||||
|
||||
if (minimalRequirementVersion[0] == actualVersion[0]) && minimalRequirementVersion[1] < actualVersion[1] {
|
||||
return true
|
||||
}
|
||||
|
||||
if (minimalRequirementVersion[0] == actualVersion[0]) && (minimalRequirementVersion[1] == actualVersion[1]) && (minimalRequirementVersion[2] <= actualVersion[2]) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (hc *HealthChecker) CheckKubeVersion() (err error) {
|
||||
|
||||
version, err := hc.kubeAPI.ServerVersion()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
major, _ := strconv.Atoi(version.Major)
|
||||
minor, _ := strconv.Atoi(version.Minor)
|
||||
apiVersion := [3]int{major, minor, 0}
|
||||
|
||||
if !isCompatibleVersion(fv1.MinimumKubernetesVersion, apiVersion) {
|
||||
return fmt.Errorf("kubernetes is on version %d.%d.%d, but version %d.%d.%d or more recent is required",
|
||||
apiVersion[0], apiVersion[1], apiVersion[2],
|
||||
fv1.MinimumKubernetesVersion[0], fv1.MinimumKubernetesVersion[1], fv1.MinimumKubernetesVersion[2])
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (hc *HealthChecker) CheckServiceStatus(namespace string, name string) (err error) {
|
||||
depl, err := hc.kubeAPI.AppsV1().Deployments(namespace).Get(context.TODO(), name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get %s deployment status", name)
|
||||
}
|
||||
|
||||
if depl.Status.UnavailableReplicas > 0 || depl.Status.Replicas == 0 {
|
||||
return fmt.Errorf("%s deployment is not running", name)
|
||||
}
|
||||
|
||||
_, err = hc.kubeAPI.CoreV1().Services(namespace).Get(context.TODO(), name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get %s service status", name)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (hc *HealthChecker) CheckFissionVersion() error {
|
||||
ver := util.GetVersion(hc.FissionClient)
|
||||
|
||||
clientVersion := ver.Client["fission/core"].Version
|
||||
serverVersion := ver.Server["fission/core"].Version
|
||||
|
||||
if clientVersion != serverVersion {
|
||||
return fmt.Errorf("client version %s does not match with server version %s", clientVersion, serverVersion)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewCategory(id CategoryID, checkers []Checker, enabled bool) *Category {
|
||||
return &Category{
|
||||
ID: id,
|
||||
checkers: checkers,
|
||||
enabled: enabled,
|
||||
}
|
||||
}
|
||||
|
||||
func (hc *HealthChecker) allCategories() []*Category {
|
||||
return []*Category{
|
||||
NewCategory(
|
||||
Kubernetes,
|
||||
[]Checker{
|
||||
{
|
||||
successMsg: "kubernetes version is compatible",
|
||||
check: func() (err error) {
|
||||
return hc.CheckKubeVersion()
|
||||
},
|
||||
},
|
||||
},
|
||||
false,
|
||||
),
|
||||
NewCategory(
|
||||
FissionServices,
|
||||
[]Checker{
|
||||
{
|
||||
successMsg: "controller is running fine",
|
||||
check: func() error {
|
||||
return hc.CheckServiceStatus(hc.fissionNamespace, "controller")
|
||||
},
|
||||
},
|
||||
{
|
||||
successMsg: "executor is running fine",
|
||||
check: func() error {
|
||||
return hc.CheckServiceStatus(hc.fissionNamespace, "executor")
|
||||
},
|
||||
},
|
||||
{
|
||||
successMsg: "router is running fine",
|
||||
check: func() error {
|
||||
return hc.CheckServiceStatus(hc.fissionNamespace, "router")
|
||||
},
|
||||
},
|
||||
{
|
||||
successMsg: "storagesvc is running fine",
|
||||
check: func() error {
|
||||
return hc.CheckServiceStatus(hc.fissionNamespace, "storagesvc")
|
||||
},
|
||||
},
|
||||
},
|
||||
false,
|
||||
),
|
||||
NewCategory(
|
||||
FissionVersion,
|
||||
[]Checker{
|
||||
{
|
||||
successMsg: "fission is up-to-date",
|
||||
check: func() error {
|
||||
return hc.CheckFissionVersion()
|
||||
},
|
||||
},
|
||||
},
|
||||
false,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
func NewHealthChecker(categoryIDs []CategoryID, options *Options) *HealthChecker {
|
||||
hc := &HealthChecker{
|
||||
Options: options,
|
||||
}
|
||||
|
||||
_, clientset, _ := util.GetKubernetesClient(hc.KubeContext)
|
||||
hc.kubeAPI = clientset
|
||||
hc.fissionNamespace = "fission"
|
||||
|
||||
hc.categories = hc.allCategories()
|
||||
|
||||
checkMap := map[CategoryID]struct{}{}
|
||||
for _, category := range categoryIDs {
|
||||
checkMap[category] = struct{}{}
|
||||
}
|
||||
for i := range hc.categories {
|
||||
if _, ok := checkMap[hc.categories[i].ID]; ok {
|
||||
hc.categories[i].enabled = true
|
||||
}
|
||||
}
|
||||
|
||||
return hc
|
||||
}
|
||||
|
||||
func RunChecks(hc *HealthChecker) {
|
||||
for _, c := range hc.categories {
|
||||
if c.enabled {
|
||||
fmt.Println(c.ID)
|
||||
fmt.Println(strings.Repeat("-", 20))
|
||||
for _, checker := range c.checkers {
|
||||
err := checker.check()
|
||||
if err != nil {
|
||||
fmt.Printf("%s %s\n", failStatus, err)
|
||||
} else {
|
||||
fmt.Printf("%s %s\n", okStatus, checker.successMsg)
|
||||
}
|
||||
}
|
||||
fmt.Printf("\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -104,7 +104,7 @@ func mqTriggerEventHandlers(logger *zap.Logger, kubeClient *kubernetes.Clientset
|
||||
logger.Error("Failed to delete Authentication Trigger", zap.Error(err))
|
||||
}
|
||||
}
|
||||
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))
|
||||
}
|
||||
}
|
||||
@@ -453,7 +453,7 @@ func createDeployment(mqt *fv1.MessageQueueTrigger, routerURL string, kubeClient
|
||||
if err != nil {
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
@@ -465,16 +465,16 @@ func updateDeployment(mqt *fv1.MessageQueueTrigger, routerURL string, kubeClient
|
||||
if err != nil {
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteDeployment(name string, kubeClient *kubernetes.Clientset) error {
|
||||
func deleteDeployment(name string, namespace string, kubeClient *kubernetes.Clientset) error {
|
||||
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,
|
||||
}); err != nil {
|
||||
return err
|
||||
|
||||
@@ -21,8 +21,17 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
topicValidators = make(map[string]TopicValidator)
|
||||
lock = sync.Mutex{}
|
||||
topicValidators = make(map[string]TopicValidator)
|
||||
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 (
|
||||
@@ -58,7 +67,7 @@ func IsValidTopic(mqType, topic, mqtKind string) bool {
|
||||
|
||||
func IsValidMessageQueue(mqType, mqtKind string) bool {
|
||||
if mqtKind == "keda" {
|
||||
return true
|
||||
return kedaMqTypeValidators[mqType]
|
||||
}
|
||||
_, registered := topicValidators[mqType]
|
||||
return registered
|
||||
|
||||
+172
-3
@@ -18,10 +18,16 @@ package router
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/gorilla/mux"
|
||||
"go.uber.org/zap"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
@@ -31,6 +37,7 @@ import (
|
||||
fv1 "github.com/fission/fission/pkg/apis/core/v1"
|
||||
"github.com/fission/fission/pkg/crd"
|
||||
executorClient "github.com/fission/fission/pkg/executor/client"
|
||||
config "github.com/fission/fission/pkg/featureconfig"
|
||||
genInformer "github.com/fission/fission/pkg/generated/informers/externalversions"
|
||||
"github.com/fission/fission/pkg/throttler"
|
||||
"github.com/fission/fission/pkg/utils"
|
||||
@@ -38,6 +45,8 @@ import (
|
||||
"github.com/fission/fission/pkg/utils/tracing"
|
||||
)
|
||||
|
||||
var featureConfig *config.FeatureConfig
|
||||
|
||||
// HTTPTriggerSet represents an HTTP trigger set
|
||||
type HTTPTriggerSet struct {
|
||||
*functionServiceMap
|
||||
@@ -59,6 +68,20 @@ type HTTPTriggerSet struct {
|
||||
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,
|
||||
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)
|
||||
}
|
||||
|
||||
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) {
|
||||
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 {
|
||||
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))
|
||||
} 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...)
|
||||
if 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))
|
||||
}
|
||||
} 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...)
|
||||
if trigger.Spec.Host != "" {
|
||||
ht.Host(trigger.Spec.Host)
|
||||
@@ -259,17 +374,71 @@ func (ts *HTTPTriggerSet) getRouter(fnTimeoutMap map[types.UID]int) *mux.Router
|
||||
} else {
|
||||
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)
|
||||
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.
|
||||
muxRouter.HandleFunc("/router-healthz", routerHealthHandler).Methods("GET")
|
||||
|
||||
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) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
Copyright 2022 The Fission Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package gitrepo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/go-git/go-git/v5"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type GitRepo struct {
|
||||
setupDone bool
|
||||
isGitRepo bool
|
||||
repo *git.Repository
|
||||
status git.Status
|
||||
dirPath string
|
||||
gitRepoRootPath string // absolute path of the root of the git repository
|
||||
commitID string // commit ID the HEAD of the repository is poitning to
|
||||
}
|
||||
|
||||
// NewGitRepo creates new GitRepo struct
|
||||
// checks if the given directory path is part of git repository
|
||||
// accordingly updates the fields of GitRepo struct and returns it
|
||||
func NewGitRepo(dirPath string) *GitRepo {
|
||||
|
||||
var g *GitRepo = &GitRepo{}
|
||||
var err error
|
||||
|
||||
g.dirPath = dirPath
|
||||
g.setupDone = true
|
||||
|
||||
// check if directory is tracked by git repo
|
||||
g.repo, err = git.PlainOpenWithOptions(dirPath, &git.PlainOpenOptions{DetectDotGit: true})
|
||||
if err != nil {
|
||||
return g
|
||||
}
|
||||
|
||||
workTree, err := g.repo.Worktree()
|
||||
if err != nil {
|
||||
return g
|
||||
}
|
||||
|
||||
g.status, err = workTree.Status()
|
||||
if err != nil {
|
||||
return g
|
||||
}
|
||||
|
||||
if g.status == nil {
|
||||
return g
|
||||
}
|
||||
|
||||
plumbRef, err := g.repo.Head()
|
||||
if err != nil {
|
||||
return g
|
||||
}
|
||||
|
||||
// extract short commit ID
|
||||
g.commitID = plumbRef.Hash().String()[:7]
|
||||
|
||||
// get the root path of git repository
|
||||
g.gitRepoRootPath = workTree.Filesystem.Root()
|
||||
|
||||
g.isGitRepo = true
|
||||
return g
|
||||
}
|
||||
|
||||
// IsGitRepo returns if the initialized directory path is tracked by git repo
|
||||
func (g *GitRepo) IsGitRepo() bool {
|
||||
return g.setupDone && g.isGitRepo
|
||||
}
|
||||
|
||||
// getFileCommitLabel returns the value of 'commit' label
|
||||
// for the resources present in the file
|
||||
/*
|
||||
The value of the `commit` label for different status of the file is as follows:
|
||||
| Git File Status | Label Value |
|
||||
|---------------------------------------|----------------------|
|
||||
| New untracked file | untracked |
|
||||
| New staged file | staged |
|
||||
| Tracked file with changes in worktree | <commitID>-unstaged |
|
||||
| Tracked file with changes staged | <commitID>-staged |
|
||||
| Tracked file with clean commit | <commitID> |
|
||||
*/
|
||||
func (g *GitRepo) GetFileCommitLabel(filePath string) (string, error) {
|
||||
|
||||
if !g.setupDone {
|
||||
return "", errors.New(`GitRepo is not setup. It has to be created by calling 'NewGitRepo' function,
|
||||
then this function has to be called.`)
|
||||
}
|
||||
|
||||
if !g.isGitRepo {
|
||||
return "", errors.Errorf(`directory: %s doesn't belong to git repository.`, g.dirPath)
|
||||
}
|
||||
|
||||
// filepath in the git repository
|
||||
splitPathList := strings.Split(filePath, g.gitRepoRootPath+string(os.PathSeparator))
|
||||
if len(splitPathList) != 2 {
|
||||
return "", errors.Errorf("error finding the git repository path of %s", filePath)
|
||||
}
|
||||
gitFilePath := splitPathList[1]
|
||||
gitFileStatus := g.status.File(gitFilePath)
|
||||
|
||||
// check if file is tracked
|
||||
if !g.status.IsUntracked(gitFilePath) {
|
||||
|
||||
// unstaged file
|
||||
if gitFileStatus.Worktree == git.Modified {
|
||||
return fmt.Sprintf("%s-unstaged", g.commitID), nil
|
||||
}
|
||||
|
||||
// newly staged file
|
||||
if gitFileStatus.Staging == git.Added {
|
||||
return "staged", nil
|
||||
}
|
||||
|
||||
// staged file
|
||||
if gitFileStatus.Staging == git.Modified {
|
||||
return fmt.Sprintf("%s-staged", g.commitID), nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// check if file is committed already
|
||||
oc, err := g.repo.Log(&git.LogOptions{FileName: &gitFilePath})
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
_, err = oc.Next()
|
||||
defer oc.Close()
|
||||
|
||||
if err != nil {
|
||||
// File not tracked by git and/or not committed
|
||||
return "untracked", nil
|
||||
|
||||
}
|
||||
|
||||
// File tracked by git and has been committed
|
||||
return g.commitID, nil
|
||||
}
|
||||
@@ -19,6 +19,7 @@ package utils
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"go.uber.org/zap"
|
||||
|
||||
@@ -295,3 +296,19 @@ func DeleteRoleBinding(ctx context.Context, k8sClient *kubernetes.Clientset, rol
|
||||
func MakeSAMapKey(saName, saNamespace string) string {
|
||||
return fmt.Sprintf("%s-%s", saName, saNamespace)
|
||||
}
|
||||
|
||||
func GetSecretConfigMapGetterCR() string {
|
||||
releaseName := os.Getenv("HELM_RELEASE_NAME")
|
||||
if len(releaseName) > 0 {
|
||||
return fmt.Sprintf("%s-secret-configmap-getter", releaseName)
|
||||
}
|
||||
return "secret-configmap-getter"
|
||||
}
|
||||
|
||||
func GetPackageGetterCR() string {
|
||||
releaseName := os.Getenv("HELM_RELEASE_NAME")
|
||||
if len(releaseName) > 0 {
|
||||
return fmt.Sprintf("%s-package-getter", releaseName)
|
||||
}
|
||||
return "package-getter"
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ url: %s
|
||||
---
|
||||
`
|
||||
|
||||
const baseURL = "/docs/fission-cli/"
|
||||
const baseURL = "/docs/reference/fission-cli/"
|
||||
|
||||
var filePrepender = func(filename string) string {
|
||||
name := filepath.Base(filename)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
title: "Fission CRD Reference"
|
||||
weight: 99
|
||||
weight: 8
|
||||
description: >
|
||||
Fission Custom Resources Definition(CRD) Reference
|
||||
url: /docs/crd-reference/
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user