mirror of
https://github.com/kubevela/kubevela.git
synced 2026-03-02 17:50:58 +00:00
Compare commits
28 Commits
v1.5.0-bet
...
v1.5.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a3ee8eb01d | ||
|
|
84b4d0f685 | ||
|
|
4e370b940c | ||
|
|
110156aff0 | ||
|
|
62df98818e | ||
|
|
992e636211 | ||
|
|
3a7a8ac59f | ||
|
|
75fd38f1de | ||
|
|
8abd78e5f1 | ||
|
|
2d82e74c5b | ||
|
|
66dfcec0ad | ||
|
|
37dd176dd3 | ||
|
|
da9bd8ca63 | ||
|
|
bc1d24e034 | ||
|
|
bcce87c073 | ||
|
|
3a9e5ccd5d | ||
|
|
1b21db979f | ||
|
|
618596b98e | ||
|
|
db21d74a52 | ||
|
|
fafa18e8db | ||
|
|
acf923dd10 | ||
|
|
8fc94f057f | ||
|
|
6a6dfba79b | ||
|
|
3b7a997b3e | ||
|
|
e13a259bca | ||
|
|
58af7103e7 | ||
|
|
b329923f81 | ||
|
|
6f8cc0f5b4 |
15
.github/workflows/chart.yaml
vendored
15
.github/workflows/chart.yaml
vendored
@@ -21,7 +21,11 @@ jobs:
|
||||
MINIMAL_HELM_CHART: charts/vela-minimal
|
||||
LEGACY_HELM_CHART: legacy/charts/vela-core-legacy
|
||||
VELA_ROLLOUT_HELM_CHART: runtime/rollout/charts
|
||||
LOCAL_OSS_DIRECTORY: .oss/
|
||||
LOCAL_OSS_DIRECTORY: .oss
|
||||
HELM_CHART_NAME: vela-core
|
||||
MINIMAL_HELM_CHART_NAME: vela-minimal
|
||||
LEGACY_HELM_CHART_NAME: vela-core-legacy
|
||||
VELA_ROLLOUT_HELM_CHART_NAME: vela-rollout
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
@@ -86,4 +90,11 @@ jobs:
|
||||
helm package $VELA_ROLLOUT_HELM_CHART --destination $LOCAL_OSS_DIRECTORY
|
||||
helm repo index --url https://$BUCKET.$ENDPOINT/core $LOCAL_OSS_DIRECTORY
|
||||
- name: sync local to cloud
|
||||
run: ./ossutil --config-file .ossutilconfig sync $LOCAL_OSS_DIRECTORY oss://$BUCKET/core -f
|
||||
run: |
|
||||
image_tag=${{ steps.get_version.outputs.VERSION }}
|
||||
chart_semver=${image_tag#"v"}
|
||||
./ossutil --config-file .ossutilconfig cp -f $LOCAL_OSS_DIRECTORY/index.yaml oss://$BUCKET/core/index.yaml
|
||||
./ossutil --config-file .ossutilconfig cp -f $LOCAL_OSS_DIRECTORY/$HELM_CHART_NAME-${chart_semver}.tgz oss://$BUCKET/core/$HELM_CHART_NAME-${chart_semver}.tgz
|
||||
./ossutil --config-file .ossutilconfig cp -f $LOCAL_OSS_DIRECTORY/$MINIMAL_HELM_CHART_NAME-${chart_semver}.tgz oss://$BUCKET/core/$MINIMAL_HELM_CHART_NAME-${chart_semver}.tgz
|
||||
./ossutil --config-file .ossutilconfig cp -f $LOCAL_OSS_DIRECTORY/$LEGACY_HELM_CHART_NAME-${chart_semver}.tgz oss://$BUCKET/core/$LEGACY_HELM_CHART_NAME-${chart_semver}.tgz
|
||||
./ossutil --config-file .ossutilconfig cp -f $LOCAL_OSS_DIRECTORY/$VELA_ROLLOUT_HELM_CHART_NAME-${chart_semver}.tgz oss://$BUCKET/core/$VELA_ROLLOUT_HELM_CHART_NAME-${chart_semver}.tgz
|
||||
|
||||
19
.github/workflows/registry.yml
vendored
19
.github/workflows/registry.yml
vendored
@@ -167,25 +167,6 @@ jobs:
|
||||
docker.io/oamdev/vela-rollout:${{ steps.get_version.outputs.VERSION }}
|
||||
ghcr.io/${{ github.repository_owner }}/oamdev/vela-rollout:${{ steps.get_version.outputs.VERSION }}
|
||||
${{ secrets.ACR_DOMAIN }}/oamdev/vela-rollout:${{ steps.get_version.outputs.VERSION }}
|
||||
|
||||
- uses: docker/build-push-action@v2
|
||||
name: Build & Pushing CloudShell for Dockerhub, GHCR and ACR
|
||||
with:
|
||||
context: .
|
||||
file: Dockerfile.cloudshell
|
||||
labels: |-
|
||||
org.opencontainers.image.source=https://github.com/${{ github.repository }}
|
||||
org.opencontainers.image.revision=${{ github.sha }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
build-args: |
|
||||
GITVERSION=git-${{ steps.vars.outputs.git_revision }}
|
||||
VERSION=${{ steps.get_version.outputs.VERSION }}
|
||||
GOPROXY=https://proxy.golang.org
|
||||
tags: |-
|
||||
docker.io/oamdev/cloudshell:${{ steps.get_version.outputs.VERSION }}
|
||||
ghcr.io/${{ github.repository_owner }}/oamdev/cloudshell:${{ steps.get_version.outputs.VERSION }}
|
||||
${{ secrets.ACR_DOMAIN }}/oamdev/cloudshell:${{ steps.get_version.outputs.VERSION }}
|
||||
|
||||
publish-capabilities:
|
||||
env:
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
ARG BASE_IMAGE
|
||||
# Build the cli binary
|
||||
FROM --platform=${BUILDPLATFORM:-linux/amd64} golang:1.17-alpine as builder
|
||||
ARG GOPROXY
|
||||
ENV GOPROXY=${GOPROXY:-https://goproxy.cn}
|
||||
WORKDIR /workspace
|
||||
# Copy the Go Modules manifests
|
||||
COPY go.mod go.mod
|
||||
COPY go.sum go.sum
|
||||
# cache deps before building and copying source so that we don't need to re-download as much
|
||||
# and so that source changes don't invalidate our downloaded layer
|
||||
RUN go mod download
|
||||
|
||||
# Copy the go source
|
||||
COPY apis/ apis/
|
||||
COPY pkg/ pkg/
|
||||
COPY version/ version/
|
||||
COPY references/ references/
|
||||
|
||||
# Build
|
||||
ARG VERSION
|
||||
ARG GITVERSION
|
||||
|
||||
RUN GO111MODULE=on CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
|
||||
go build -a -ldflags "-s -w -X github.com/oam-dev/kubevela/version.VelaVersion=${VERSION:-undefined} -X github.com/oam-dev/kubevela/version.GitRevision=${GITVERSION:-undefined}" \
|
||||
-o vela ./references/cmd/cli/main.go
|
||||
|
||||
FROM ghcr.io/cloudtty/cloudshell:v0.2.0
|
||||
RUN apt-get install -y vim
|
||||
ENV API_TOKEN_PATH=/usr/local/kubeconfig/token
|
||||
COPY --from=builder /workspace/vela /usr/local/bin/vela
|
||||
@@ -62,12 +62,12 @@ type GarbageCollectPolicyRule struct {
|
||||
// if one resource is specified with conflict strategies, strategy as component go first.
|
||||
// 2) for ApplyOncePolicyRule only CompNames and ResourceTypes are used
|
||||
type ResourcePolicyRuleSelector struct {
|
||||
CompNames []string `json:"componentNames"`
|
||||
CompTypes []string `json:"componentTypes"`
|
||||
OAMResourceTypes []string `json:"oamTypes"`
|
||||
TraitTypes []string `json:"traitTypes"`
|
||||
ResourceTypes []string `json:"resourceTypes"`
|
||||
ResourceNames []string `json:"resourceNames"`
|
||||
CompNames []string `json:"componentNames,omitempty"`
|
||||
CompTypes []string `json:"componentTypes,omitempty"`
|
||||
OAMResourceTypes []string `json:"oamTypes,omitempty"`
|
||||
TraitTypes []string `json:"traitTypes,omitempty"`
|
||||
ResourceTypes []string `json:"resourceTypes,omitempty"`
|
||||
ResourceNames []string `json:"resourceNames,omitempty"`
|
||||
}
|
||||
|
||||
// Match check if current rule selector match the target resource
|
||||
|
||||
@@ -120,7 +120,7 @@ type TraitDefinitionSpec struct {
|
||||
PodDisruptive bool `json:"podDisruptive,omitempty"`
|
||||
|
||||
// AppliesToWorkloads specifies the list of workload kinds this trait
|
||||
// applies to. Workload kinds are specified in kind.group/version format,
|
||||
// applies to. Workload kinds are specified in resource.group/version format,
|
||||
// e.g. server.core.oam.dev/v1alpha2. Traits that omit this field apply to
|
||||
// all workload kinds.
|
||||
// +optional
|
||||
|
||||
@@ -82,6 +82,8 @@ type ManagedResource struct {
|
||||
Data *runtime.RawExtension `json:"raw,omitempty"`
|
||||
// Deleted marks the resource to be deleted
|
||||
Deleted bool `json:"deleted,omitempty"`
|
||||
// SkipGC marks the resource to skip gc
|
||||
SkipGC bool `json:"skipGC,omitempty"`
|
||||
}
|
||||
|
||||
// Equal check if two managed resource equals
|
||||
@@ -215,8 +217,9 @@ func (in *ResourceTracker) ContainsManagedResource(rsc client.Object) bool {
|
||||
}
|
||||
|
||||
// AddManagedResource add object to managed resources, if exists, update
|
||||
func (in *ResourceTracker) AddManagedResource(rsc client.Object, metaOnly bool, creator common.ResourceCreatorRole) (updated bool) {
|
||||
func (in *ResourceTracker) AddManagedResource(rsc client.Object, metaOnly bool, skipGC bool, creator common.ResourceCreatorRole) (updated bool) {
|
||||
mr := newManagedResourceFromResource(rsc)
|
||||
mr.SkipGC = skipGC
|
||||
if !metaOnly {
|
||||
mr.Data = &runtime.RawExtension{Object: rsc}
|
||||
}
|
||||
|
||||
@@ -156,16 +156,16 @@ func TestResourceTracker_ManagedResource(t *testing.T) {
|
||||
r := require.New(t)
|
||||
input := &ResourceTracker{}
|
||||
deploy1 := v12.Deployment{ObjectMeta: v13.ObjectMeta{Name: "deploy1"}}
|
||||
input.AddManagedResource(&deploy1, true, "")
|
||||
input.AddManagedResource(&deploy1, true, false, "")
|
||||
r.Equal(1, len(input.Spec.ManagedResources))
|
||||
cm2 := v1.ConfigMap{ObjectMeta: v13.ObjectMeta{Name: "cm2"}}
|
||||
input.AddManagedResource(&cm2, false, "")
|
||||
input.AddManagedResource(&cm2, false, false, "")
|
||||
r.Equal(2, len(input.Spec.ManagedResources))
|
||||
pod3 := v1.Pod{ObjectMeta: v13.ObjectMeta{Name: "pod3"}}
|
||||
input.AddManagedResource(&pod3, false, "")
|
||||
input.AddManagedResource(&pod3, false, false, "")
|
||||
r.Equal(3, len(input.Spec.ManagedResources))
|
||||
deploy1.Spec.Replicas = pointer.Int32(5)
|
||||
input.AddManagedResource(&deploy1, false, "")
|
||||
input.AddManagedResource(&deploy1, false, false, "")
|
||||
r.Equal(3, len(input.Spec.ManagedResources))
|
||||
input.DeleteManagedResource(&cm2, false)
|
||||
r.Equal(3, len(input.Spec.ManagedResources))
|
||||
|
||||
@@ -106,6 +106,7 @@ type Config map[string]string
|
||||
type EnvMeta struct {
|
||||
Name string `json:"name"`
|
||||
Namespace string `json:"namespace"`
|
||||
Labels string `json:"labels"`
|
||||
Current string `json:"current"`
|
||||
}
|
||||
|
||||
|
||||
@@ -3650,7 +3650,7 @@ spec:
|
||||
appliesToWorkloads:
|
||||
description: AppliesToWorkloads specifies the list of workload
|
||||
kinds this trait applies to. Workload kinds are specified
|
||||
in kind.group/version format, e.g. server.core.oam.dev/v1alpha2.
|
||||
in resource.group/version format, e.g. server.core.oam.dev/v1alpha2.
|
||||
Traits that omit this field apply to all workload kinds.
|
||||
items:
|
||||
type: string
|
||||
|
||||
@@ -708,7 +708,7 @@ spec:
|
||||
appliesToWorkloads:
|
||||
description: AppliesToWorkloads specifies the list of workload
|
||||
kinds this trait applies to. Workload kinds are specified
|
||||
in kind.group/version format, e.g. server.core.oam.dev/v1alpha2.
|
||||
in resource.group/version format, e.g. server.core.oam.dev/v1alpha2.
|
||||
Traits that omit this field apply to all workload kinds.
|
||||
items:
|
||||
type: string
|
||||
|
||||
@@ -105,6 +105,9 @@ spec:
|
||||
description: 'Specific resourceVersion to which this reference
|
||||
is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
|
||||
type: string
|
||||
skipGC:
|
||||
description: SkipGC marks the resource to skip gc
|
||||
type: boolean
|
||||
trait:
|
||||
type: string
|
||||
uid:
|
||||
|
||||
@@ -356,7 +356,7 @@ spec:
|
||||
properties:
|
||||
appliesToWorkloads:
|
||||
description: AppliesToWorkloads specifies the list of workload kinds
|
||||
this trait applies to. Workload kinds are specified in kind.group/version
|
||||
this trait applies to. Workload kinds are specified in resource.group/version
|
||||
format, e.g. server.core.oam.dev/v1alpha2. Traits that omit this
|
||||
field apply to all workload kinds.
|
||||
items:
|
||||
|
||||
@@ -11,7 +11,10 @@ metadata:
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
- daemonsets.apps
|
||||
- jobs.batch
|
||||
podDisruptive: true
|
||||
schematic:
|
||||
cue:
|
||||
|
||||
@@ -4,7 +4,7 @@ apiVersion: core.oam.dev/v1beta1
|
||||
kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Add annotations on K8s pod for your workload which follows the pod spec in path 'spec.template'.
|
||||
definition.oam.dev/description: Add annotations on your workload. if it generates pod, add same annotations for generated pods.
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: annotations
|
||||
|
||||
@@ -11,7 +11,10 @@ metadata:
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
- daemonsets.apps
|
||||
- jobs.batch
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
|
||||
@@ -11,7 +11,10 @@ metadata:
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
- daemonsets.apps
|
||||
- jobs.batch
|
||||
podDisruptive: true
|
||||
schematic:
|
||||
cue:
|
||||
|
||||
@@ -12,6 +12,7 @@ metadata:
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
|
||||
@@ -11,7 +11,10 @@ metadata:
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
- daemonsets.apps
|
||||
- jobs.batch
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
|
||||
@@ -10,6 +10,9 @@ metadata:
|
||||
name: expose
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
podDisruptive: false
|
||||
schematic:
|
||||
cue:
|
||||
|
||||
@@ -9,7 +9,8 @@ metadata:
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
podDisruptive: false
|
||||
schematic:
|
||||
cue:
|
||||
@@ -85,7 +86,7 @@ spec:
|
||||
// +usage=Set ingress class in '.spec.ingressClassName' instead of 'kubernetes.io/ingress.class' annotation.
|
||||
classInSpec: *false | bool
|
||||
|
||||
// +usage=Specify the secret name you want to quote.
|
||||
// +usage=Specify the secret name you want to quote to use tls.
|
||||
secretName?: string
|
||||
|
||||
// +usage=Specify the host of the ingress gateway, which is used to generate the endpoints when the host is empty.
|
||||
|
||||
@@ -11,7 +11,10 @@ metadata:
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
- daemonsets.apps
|
||||
- jobs.batch
|
||||
podDisruptive: false
|
||||
schematic:
|
||||
cue:
|
||||
|
||||
@@ -12,6 +12,9 @@ metadata:
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
- daemonsets.apps
|
||||
- jobs.batch
|
||||
podDisruptive: true
|
||||
schematic:
|
||||
cue:
|
||||
|
||||
@@ -4,7 +4,7 @@ apiVersion: core.oam.dev/v1beta1
|
||||
kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Add labels on K8s pod for your workload which follows the pod spec in path 'spec.template'.
|
||||
definition.oam.dev/description: Add labels on your workload. if it generates pod, add same label for generated pods.
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: labels
|
||||
|
||||
@@ -11,7 +11,10 @@ metadata:
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
- daemonsets.apps
|
||||
- jobs.batch
|
||||
podDisruptive: true
|
||||
schematic:
|
||||
cue:
|
||||
|
||||
@@ -11,7 +11,10 @@ metadata:
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
- daemonsets.apps
|
||||
- jobs.batch
|
||||
podDisruptive: true
|
||||
schematic:
|
||||
cue:
|
||||
|
||||
@@ -6,11 +6,13 @@ metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Enable public web traffic for the component without creating a Service.
|
||||
labels:
|
||||
custom.definition.oam.dev/deprecated: "true"
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: pure-ingress
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads: []
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
conflictsWith: []
|
||||
podDisruptive: false
|
||||
schematic:
|
||||
|
||||
@@ -6,6 +6,7 @@ metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Add a datasource to Grafana
|
||||
labels:
|
||||
custom.definition.oam.dev/deprecated: "true"
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: register-grafana-datasource
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
|
||||
@@ -11,7 +11,10 @@ metadata:
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
- daemonsets.apps
|
||||
- jobs.batch
|
||||
podDisruptive: true
|
||||
schematic:
|
||||
cue:
|
||||
|
||||
@@ -9,7 +9,8 @@ metadata:
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
podDisruptive: false
|
||||
schematic:
|
||||
cue:
|
||||
|
||||
@@ -9,7 +9,10 @@ metadata:
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
- daemonsets.apps
|
||||
- jobs.batch
|
||||
podDisruptive: false
|
||||
schematic:
|
||||
cue:
|
||||
|
||||
@@ -11,7 +11,10 @@ metadata:
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
- daemonsets.apps
|
||||
- jobs.batch
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
|
||||
@@ -11,7 +11,10 @@ metadata:
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
- daemonsets.apps
|
||||
- jobs.batch
|
||||
podDisruptive: true
|
||||
schematic:
|
||||
cue:
|
||||
|
||||
@@ -10,6 +10,9 @@ metadata:
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
- daemonsets.apps
|
||||
- jobs.batch
|
||||
podDisruptive: true
|
||||
schematic:
|
||||
cue:
|
||||
|
||||
77
charts/vela-core/templates/velaql/component-pod.yaml
Normal file
77
charts/vela-core/templates/velaql/component-pod.yaml
Normal file
@@ -0,0 +1,77 @@
|
||||
{{- if not (lookup "v1" "ConfigMap" (include "systemDefinitionNamespace" .) "component-pod-view") }}
|
||||
apiVersion: v1
|
||||
data:
|
||||
template: |
|
||||
import (
|
||||
"vela/ql"
|
||||
)
|
||||
|
||||
parameter: {
|
||||
appName: string
|
||||
appNs: string
|
||||
name?: string
|
||||
cluster?: string
|
||||
clusterNs?: string
|
||||
}
|
||||
|
||||
result: ql.#CollectPods & {
|
||||
app: {
|
||||
name: parameter.appName
|
||||
namespace: parameter.appNs
|
||||
filter: {
|
||||
if parameter.cluster != _|_ {
|
||||
cluster: parameter.cluster
|
||||
}
|
||||
if parameter.clusterNs != _|_ {
|
||||
clusterNamespace: parameter.clusterNs
|
||||
}
|
||||
if parameter.name != _|_ {
|
||||
components: [parameter.name]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if result.err == _|_ {
|
||||
status: {
|
||||
podList: [ for pod in result.list if pod.object != _|_ {
|
||||
cluster: pod.cluster
|
||||
workload: pod.workload
|
||||
component: pod.component
|
||||
metadata: {
|
||||
name: pod.object.metadata.name
|
||||
namespace: pod.object.metadata.namespace
|
||||
creationTime: pod.object.metadata.creationTimestamp
|
||||
labels: pod.object.metadata.labels
|
||||
version: {
|
||||
if pod.publishVersion != _|_ {
|
||||
publishVersion: pod.publishVersion
|
||||
}
|
||||
if pod.deployVersion != _|_ {
|
||||
deployVersion: pod.deployVersion
|
||||
}
|
||||
}
|
||||
}
|
||||
status: {
|
||||
phase: pod.object.status.phase
|
||||
// refer to https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase
|
||||
if phase != "Pending" && phase != "Unknown" {
|
||||
podIP: pod.object.status.podIP
|
||||
hostIP: pod.object.status.hostIP
|
||||
nodeName: pod.object.spec.nodeName
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
if result.err != _|_ {
|
||||
status: {
|
||||
error: result.err
|
||||
}
|
||||
}
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: component-pod-view
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
{{- end }}
|
||||
50
charts/vela-core/templates/velaql/component-service.yaml
Normal file
50
charts/vela-core/templates/velaql/component-service.yaml
Normal file
@@ -0,0 +1,50 @@
|
||||
{{- if not (lookup "v1" "ConfigMap" (include "systemDefinitionNamespace" .) "component-service-view") }}
|
||||
apiVersion: v1
|
||||
data:
|
||||
template: |
|
||||
import (
|
||||
"vela/ql"
|
||||
)
|
||||
|
||||
parameter: {
|
||||
appName: string
|
||||
appNs: string
|
||||
name?: string
|
||||
cluster?: string
|
||||
clusterNs?: string
|
||||
}
|
||||
|
||||
result: ql.#CollectServices & {
|
||||
app: {
|
||||
name: parameter.appName
|
||||
namespace: parameter.appNs
|
||||
filter: {
|
||||
if parameter.cluster != _|_ {
|
||||
cluster: parameter.cluster
|
||||
}
|
||||
if parameter.clusterNs != _|_ {
|
||||
clusterNamespace: parameter.clusterNs
|
||||
}
|
||||
if parameter.name != _|_ {
|
||||
components: [parameter.name]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if result.err == _|_ {
|
||||
status: {
|
||||
services: result.list
|
||||
}
|
||||
}
|
||||
|
||||
if result.err != _|_ {
|
||||
status: {
|
||||
error: result.err
|
||||
}
|
||||
}
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: component-service-view
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
{{- end}}
|
||||
@@ -3650,7 +3650,7 @@ spec:
|
||||
appliesToWorkloads:
|
||||
description: AppliesToWorkloads specifies the list of workload
|
||||
kinds this trait applies to. Workload kinds are specified
|
||||
in kind.group/version format, e.g. server.core.oam.dev/v1alpha2.
|
||||
in resource.group/version format, e.g. server.core.oam.dev/v1alpha2.
|
||||
Traits that omit this field apply to all workload kinds.
|
||||
items:
|
||||
type: string
|
||||
|
||||
@@ -708,7 +708,7 @@ spec:
|
||||
appliesToWorkloads:
|
||||
description: AppliesToWorkloads specifies the list of workload
|
||||
kinds this trait applies to. Workload kinds are specified
|
||||
in kind.group/version format, e.g. server.core.oam.dev/v1alpha2.
|
||||
in resource.group/version format, e.g. server.core.oam.dev/v1alpha2.
|
||||
Traits that omit this field apply to all workload kinds.
|
||||
items:
|
||||
type: string
|
||||
|
||||
@@ -105,6 +105,9 @@ spec:
|
||||
description: 'Specific resourceVersion to which this reference
|
||||
is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
|
||||
type: string
|
||||
skipGC:
|
||||
description: SkipGC marks the resource to skip gc
|
||||
type: boolean
|
||||
trait:
|
||||
type: string
|
||||
uid:
|
||||
|
||||
@@ -356,7 +356,7 @@ spec:
|
||||
properties:
|
||||
appliesToWorkloads:
|
||||
description: AppliesToWorkloads specifies the list of workload kinds
|
||||
this trait applies to. Workload kinds are specified in kind.group/version
|
||||
this trait applies to. Workload kinds are specified in resource.group/version
|
||||
format, e.g. server.core.oam.dev/v1alpha2. Traits that omit this
|
||||
field apply to all workload kinds.
|
||||
items:
|
||||
|
||||
@@ -11,7 +11,10 @@ metadata:
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
- daemonsets.apps
|
||||
- jobs.batch
|
||||
podDisruptive: true
|
||||
schematic:
|
||||
cue:
|
||||
|
||||
@@ -4,7 +4,7 @@ apiVersion: core.oam.dev/v1beta1
|
||||
kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Add annotations on K8s pod for your workload which follows the pod spec in path 'spec.template'.
|
||||
definition.oam.dev/description: Add annotations on your workload. if it generates pod, add same annotations for generated pods.
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: annotations
|
||||
|
||||
@@ -11,7 +11,10 @@ metadata:
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
- daemonsets.apps
|
||||
- jobs.batch
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
|
||||
@@ -11,7 +11,10 @@ metadata:
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
- daemonsets.apps
|
||||
- jobs.batch
|
||||
podDisruptive: true
|
||||
schematic:
|
||||
cue:
|
||||
|
||||
@@ -12,6 +12,7 @@ metadata:
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
|
||||
@@ -11,7 +11,10 @@ metadata:
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
- daemonsets.apps
|
||||
- jobs.batch
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
|
||||
@@ -10,6 +10,9 @@ metadata:
|
||||
name: expose
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
podDisruptive: false
|
||||
schematic:
|
||||
cue:
|
||||
|
||||
@@ -9,7 +9,8 @@ metadata:
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
podDisruptive: false
|
||||
schematic:
|
||||
cue:
|
||||
@@ -85,7 +86,7 @@ spec:
|
||||
// +usage=Set ingress class in '.spec.ingressClassName' instead of 'kubernetes.io/ingress.class' annotation.
|
||||
classInSpec: *false | bool
|
||||
|
||||
// +usage=Specify the secret name you want to quote.
|
||||
// +usage=Specify the secret name you want to quote to use tls.
|
||||
secretName?: string
|
||||
|
||||
// +usage=Specify the host of the ingress gateway, which is used to generate the endpoints when the host is empty.
|
||||
|
||||
@@ -11,7 +11,10 @@ metadata:
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
- daemonsets.apps
|
||||
- jobs.batch
|
||||
podDisruptive: false
|
||||
schematic:
|
||||
cue:
|
||||
|
||||
@@ -12,6 +12,9 @@ metadata:
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
- daemonsets.apps
|
||||
- jobs.batch
|
||||
podDisruptive: true
|
||||
schematic:
|
||||
cue:
|
||||
|
||||
@@ -4,7 +4,7 @@ apiVersion: core.oam.dev/v1beta1
|
||||
kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Add labels on K8s pod for your workload which follows the pod spec in path 'spec.template'.
|
||||
definition.oam.dev/description: Add labels on your workload. if it generates pod, add same label for generated pods.
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: labels
|
||||
|
||||
@@ -11,7 +11,10 @@ metadata:
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
- daemonsets.apps
|
||||
- jobs.batch
|
||||
podDisruptive: true
|
||||
schematic:
|
||||
cue:
|
||||
|
||||
@@ -11,7 +11,10 @@ metadata:
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
- daemonsets.apps
|
||||
- jobs.batch
|
||||
podDisruptive: true
|
||||
schematic:
|
||||
cue:
|
||||
|
||||
@@ -6,11 +6,13 @@ metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Enable public web traffic for the component without creating a Service.
|
||||
labels:
|
||||
custom.definition.oam.dev/deprecated: "true"
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: pure-ingress
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads: []
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
conflictsWith: []
|
||||
podDisruptive: false
|
||||
schematic:
|
||||
|
||||
@@ -6,6 +6,7 @@ metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Add a datasource to Grafana
|
||||
labels:
|
||||
custom.definition.oam.dev/deprecated: "true"
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: register-grafana-datasource
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
|
||||
@@ -11,7 +11,10 @@ metadata:
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
- daemonsets.apps
|
||||
- jobs.batch
|
||||
podDisruptive: true
|
||||
schematic:
|
||||
cue:
|
||||
|
||||
@@ -9,7 +9,8 @@ metadata:
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
podDisruptive: false
|
||||
schematic:
|
||||
cue:
|
||||
|
||||
@@ -9,7 +9,10 @@ metadata:
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
- daemonsets.apps
|
||||
- jobs.batch
|
||||
podDisruptive: false
|
||||
schematic:
|
||||
cue:
|
||||
|
||||
@@ -11,7 +11,10 @@ metadata:
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
- daemonsets.apps
|
||||
- jobs.batch
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
|
||||
@@ -11,7 +11,10 @@ metadata:
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
- daemonsets.apps
|
||||
- jobs.batch
|
||||
podDisruptive: true
|
||||
schematic:
|
||||
cue:
|
||||
|
||||
@@ -10,6 +10,9 @@ metadata:
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
- daemonsets.apps
|
||||
- jobs.batch
|
||||
podDisruptive: true
|
||||
schematic:
|
||||
cue:
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"time"
|
||||
|
||||
restfulspec "github.com/emicklei/go-restful-openapi/v2"
|
||||
"github.com/fatih/color"
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/google/uuid"
|
||||
flag "github.com/spf13/pflag"
|
||||
@@ -82,6 +83,10 @@ func main() {
|
||||
return
|
||||
}
|
||||
|
||||
// The server is not terminal, there is no color default.
|
||||
// Force set to false, this is useful for the dry-run API.
|
||||
color.NoColor = false
|
||||
|
||||
errChan := make(chan error)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
50
e2e/addon/mock/testdata/mock-addon/definitions/json-patch.cue
vendored
Normal file
50
e2e/addon/mock/testdata/mock-addon/definitions/json-patch.cue
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
"kustomize-json-patch-mock-adddon": {
|
||||
attributes: {
|
||||
podDisruptive: false
|
||||
}
|
||||
description: "A list of JSON6902 patch to selected target"
|
||||
labels: {
|
||||
"ui-hidden": "true"
|
||||
}
|
||||
type: "trait"
|
||||
}
|
||||
|
||||
template: {
|
||||
patch: {
|
||||
spec: {
|
||||
patches: parameter.patchesJson
|
||||
}
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=A list of JSON6902 patch.
|
||||
patchesJson: [...#jsonPatchItem]
|
||||
}
|
||||
|
||||
// +usage=Contains a JSON6902 patch
|
||||
#jsonPatchItem: {
|
||||
target: #selector
|
||||
patch: [...{
|
||||
// +usage=operation to perform
|
||||
op: string | "add" | "remove" | "replace" | "move" | "copy" | "test"
|
||||
// +usage=operate path e.g. /foo/bar
|
||||
path: string
|
||||
// +usage=specify source path when op is copy/move
|
||||
from?: string
|
||||
// +usage=specify opraation value when op is test/add/replace
|
||||
value?: string
|
||||
}]
|
||||
}
|
||||
|
||||
// +usage=Selector specifies a set of resources
|
||||
#selector: {
|
||||
group?: string
|
||||
version?: string
|
||||
kind?: string
|
||||
namespace?: string
|
||||
name?: string
|
||||
annotationSelector?: string
|
||||
labelSelector?: string
|
||||
}
|
||||
|
||||
}
|
||||
1
e2e/addon/mock/testdata/mock-addon/readme.md
vendored
Normal file
1
e2e/addon/mock/testdata/mock-addon/readme.md
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Test addon readme.md file
|
||||
@@ -76,6 +76,8 @@ func ApplyMockServerConfig() error {
|
||||
} else {
|
||||
cm.ResourceVersion = originCm.ResourceVersion
|
||||
if err = k8sClient.Update(ctx, &cm); err != nil {
|
||||
fmt.Println("print errr------")
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,10 +42,10 @@ var (
|
||||
applicationName = "app-basic"
|
||||
traitAlias = "scaler"
|
||||
appNameForInit = "initmyapp"
|
||||
jsonAppFile = `{"name":"nginx-vela","services":{"nginx":{"type":"webservice","image":"nginx:1.9.4","port":80}}}`
|
||||
testDeleteJsonAppFile = `{"name":"test-vela-delete","services":{"nginx-test":{"type":"webservice","image":"nginx:1.9.4","port":80}}}`
|
||||
appbasicJsonAppFile = `{"name":"app-basic","services":{"app-basic":{"type":"webservice","image":"nginx:1.9.4","port":80}}}`
|
||||
appbasicAddTraitJsonAppFile = `{"name":"app-basic","services":{"app-basic":{"type":"webservice","image":"nginx:1.9.4","port":80,"scaler":{"replicas":2}}}}`
|
||||
jsonAppFile = `{"name":"nginx-vela","services":{"nginx":{"type":"webservice","image":"nginx:1.9.4","ports":[{port: 80, expose: true}]}}}`
|
||||
testDeleteJsonAppFile = `{"name":"test-vela-delete","services":{"nginx-test":{"type":"webservice","image":"nginx:1.9.4","ports":[{port: 80, expose: true}]}}}`
|
||||
appbasicJsonAppFile = `{"name":"app-basic","services":{"app-basic":{"type":"webservice","image":"nginx:1.9.4","ports":[{port: 80, expose: true}]}}}`
|
||||
appbasicAddTraitJsonAppFile = `{"name":"app-basic","services":{"app-basic":{"type":"webservice","image":"nginx:1.9.4","ports":[{port: 80, expose: true}],"scaler":{"replicas":2}}}}`
|
||||
velaQL = "test-component-pod-view{appNs=default,appName=nginx-vela,name=nginx}"
|
||||
)
|
||||
|
||||
@@ -303,7 +303,7 @@ var VelaQLPodListContext = func(context string, velaQL string) bool {
|
||||
gomega.Expect(v.Workload.ApiVersion).To(gomega.ContainSubstring("apps/v1"))
|
||||
}
|
||||
if v.Workload.Kind != "" {
|
||||
gomega.Expect(v.Workload.Kind).To(gomega.ContainSubstring("Deployment"))
|
||||
gomega.Expect(v.Workload.Kind).To(gomega.ContainSubstring("ReplicaSet"))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -7,7 +7,6 @@ data:
|
||||
template: |
|
||||
import (
|
||||
"vela/ql"
|
||||
"vela/op"
|
||||
)
|
||||
|
||||
parameter: {
|
||||
@@ -18,7 +17,7 @@ data:
|
||||
clusterNs?: string
|
||||
}
|
||||
|
||||
application: ql.#ListResourcesInApp & {
|
||||
result: ql.#CollectPods & {
|
||||
app: {
|
||||
name: parameter.appName
|
||||
namespace: parameter.appNs
|
||||
@@ -36,63 +35,41 @@ data:
|
||||
}
|
||||
}
|
||||
|
||||
if application.err != _|_ {
|
||||
status: error: application.err
|
||||
}
|
||||
|
||||
if application.err == _|_ {
|
||||
resources: application.list
|
||||
|
||||
podsMap: op.#Steps & {
|
||||
for i, resource in resources {
|
||||
"\(i)": ql.#CollectPods & {
|
||||
value: resource.object
|
||||
cluster: resource.cluster
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
podsWithCluster: [ for i, pods in podsMap for podObj in pods.list {
|
||||
cluster: pods.cluster
|
||||
obj: podObj
|
||||
}]
|
||||
|
||||
podStatus: op.#Steps & {
|
||||
for i, pod in podsWithCluster {
|
||||
"\(i)": op.#Steps & {
|
||||
name: pod.obj.metadata.name
|
||||
containers: {for container in pod.obj.status.containerStatuses {
|
||||
"\(container.name)": {
|
||||
image: container.image
|
||||
state: container.state
|
||||
}
|
||||
}}
|
||||
events: ql.#SearchEvents & {
|
||||
value: pod.obj
|
||||
cluster: pod.cluster
|
||||
}
|
||||
metrics: ql.#Read & {
|
||||
cluster: pod.cluster
|
||||
value: {
|
||||
apiVersion: "metrics.k8s.io/v1beta1"
|
||||
kind: "PodMetrics"
|
||||
metadata: {
|
||||
name: pod.obj.metadata.name
|
||||
namespace: pod.obj.metadata.namespace
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if result.err == _|_ {
|
||||
status: {
|
||||
podList: [ for podInfo in podStatus {
|
||||
name: podInfo.name
|
||||
containers: [ for containerName, container in podInfo.containers {
|
||||
containerName
|
||||
}]
|
||||
events: podInfo.events.list
|
||||
podList: [ for pod in result.list if pod.object != _|_ {
|
||||
cluster: pod.cluster
|
||||
workload: pod.workload
|
||||
component: pod.component
|
||||
metadata: {
|
||||
name: pod.object.metadata.name
|
||||
namespace: pod.object.metadata.namespace
|
||||
creationTime: pod.object.metadata.creationTimestamp
|
||||
labels: pod.object.metadata.labels
|
||||
version: {
|
||||
if pod.publishVersion != _|_ {
|
||||
publishVersion: pod.publishVersion
|
||||
}
|
||||
if pod.deployVersion != _|_ {
|
||||
deployVersion: pod.deployVersion
|
||||
}
|
||||
}
|
||||
}
|
||||
status: {
|
||||
phase: pod.object.status.phase
|
||||
// refer to https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase
|
||||
if phase != "Pending" && phase != "Unknown" {
|
||||
podIP: pod.object.status.podIP
|
||||
hostIP: pod.object.status.hostIP
|
||||
nodeName: pod.object.spec.nodeName
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
if result.err != _|_ {
|
||||
status: {
|
||||
error: result.err
|
||||
}
|
||||
}
|
||||
|
||||
3
go.mod
3
go.mod
@@ -124,6 +124,8 @@ require (
|
||||
sigs.k8s.io/gateway-api v0.4.3
|
||||
)
|
||||
|
||||
require github.com/rogpeppe/go-internal v1.8.0
|
||||
|
||||
require (
|
||||
cloud.google.com/go/compute v1.7.0 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||
@@ -256,7 +258,6 @@ require (
|
||||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
github.com/prometheus/common v0.28.0 // indirect
|
||||
github.com/prometheus/procfs v0.6.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.8.0 // indirect
|
||||
github.com/rubenv/sql-migrate v0.0.0-20210614095031-55d5740dbbcc // indirect
|
||||
github.com/russross/blackfriday v1.6.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
|
||||
@@ -86,7 +86,9 @@ func TraitDef(ctx context.Context, c common.Args, path, location *string, defdir
|
||||
},
|
||||
CustomDocHeader: CustomTraitHeaderEN,
|
||||
}
|
||||
ref.Remote = &docgen.FromCluster{Namespace: types.DefaultKubeVelaNS}
|
||||
ref.Local = &docgen.FromLocal{
|
||||
Path: TraitDefDir,
|
||||
}
|
||||
|
||||
if *path != "" {
|
||||
ref.I18N = &docgen.En
|
||||
@@ -99,22 +101,24 @@ func TraitDef(ctx context.Context, c common.Args, path, location *string, defdir
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("trait reference docs (%s) successfully generated in %s \n", ref.I18N.Language(), *path)
|
||||
}
|
||||
if *location == "" || *location == "en" {
|
||||
ref.I18N = &docgen.En
|
||||
if err := ref.GenerateReferenceDocs(ctx, c, TraitDefRefPath); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
} else {
|
||||
// Generate to default path depends on language
|
||||
if *location == "" || *location == "en" {
|
||||
ref.I18N = &docgen.En
|
||||
if err := ref.GenerateReferenceDocs(ctx, c, TraitDefRefPath); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("trait reference docs (%s) successfully generated in %s \n", ref.I18N.Language(), TraitDefRefPath)
|
||||
}
|
||||
fmt.Printf("trait reference docs (%s) successfully generated in %s \n", ref.I18N.Language(), TraitDefRefPath)
|
||||
}
|
||||
if *location == "" || *location == "zh" {
|
||||
ref.I18N = &docgen.Zh
|
||||
ref.CustomDocHeader = CustomTraitHeaderZH
|
||||
if err := ref.GenerateReferenceDocs(ctx, c, TraitDefRefPathZh); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
if *location == "" || *location == "zh" {
|
||||
ref.I18N = &docgen.Zh
|
||||
ref.CustomDocHeader = CustomTraitHeaderZH
|
||||
if err := ref.GenerateReferenceDocs(ctx, c, TraitDefRefPathZh); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("trait reference docs (%s) successfully generated in %s \n", ref.I18N.Language(), TraitDefRefPathZh)
|
||||
}
|
||||
fmt.Printf("trait reference docs (%s) successfully generated in %s \n", ref.I18N.Language(), TraitDefRefPathZh)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3650,7 +3650,7 @@ spec:
|
||||
appliesToWorkloads:
|
||||
description: AppliesToWorkloads specifies the list of workload
|
||||
kinds this trait applies to. Workload kinds are specified
|
||||
in kind.group/version format, e.g. server.core.oam.dev/v1alpha2.
|
||||
in resource.group/version format, e.g. server.core.oam.dev/v1alpha2.
|
||||
Traits that omit this field apply to all workload kinds.
|
||||
items:
|
||||
type: string
|
||||
|
||||
@@ -708,7 +708,7 @@ spec:
|
||||
appliesToWorkloads:
|
||||
description: AppliesToWorkloads specifies the list of workload
|
||||
kinds this trait applies to. Workload kinds are specified
|
||||
in kind.group/version format, e.g. server.core.oam.dev/v1alpha2.
|
||||
in resource.group/version format, e.g. server.core.oam.dev/v1alpha2.
|
||||
Traits that omit this field apply to all workload kinds.
|
||||
items:
|
||||
type: string
|
||||
|
||||
@@ -105,6 +105,9 @@ spec:
|
||||
description: 'Specific resourceVersion to which this reference
|
||||
is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
|
||||
type: string
|
||||
skipGC:
|
||||
description: SkipGC marks the resource to skip gc
|
||||
type: boolean
|
||||
trait:
|
||||
type: string
|
||||
uid:
|
||||
|
||||
@@ -356,7 +356,7 @@ spec:
|
||||
properties:
|
||||
appliesToWorkloads:
|
||||
description: AppliesToWorkloads specifies the list of workload kinds
|
||||
this trait applies to. Workload kinds are specified in kind.group/version
|
||||
this trait applies to. Workload kinds are specified in resource.group/version
|
||||
format, e.g. server.core.oam.dev/v1alpha2. Traits that omit this
|
||||
field apply to all workload kinds.
|
||||
items:
|
||||
|
||||
@@ -8,7 +8,8 @@ e2e-setup-core-post-hook:
|
||||
helm upgrade --install --namespace vela-system --wait oam-rollout --set image.repository=vela-runtime-rollout-test --set image.tag=$(GIT_COMMIT) ./runtime/rollout/charts
|
||||
go run ./e2e/addon/mock &
|
||||
sleep 15
|
||||
bin/vela addon enable rollout
|
||||
bin/vela addon enable ./e2e/addon/mock/testdata/fluxcd
|
||||
bin/vela addon enable ./e2e/addon/mock/testdata/rollout
|
||||
|
||||
.PHONY: e2e-setup-core-wo-auth
|
||||
e2e-setup-core-wo-auth:
|
||||
@@ -37,10 +38,10 @@ e2e-setup:
|
||||
|
||||
go run ./e2e/addon/mock &
|
||||
sleep 15
|
||||
bin/vela addon enable fluxcd
|
||||
bin/vela addon enable terraform
|
||||
bin/vela addon enable terraform-alibaba ALICLOUD_ACCESS_KEY=xxx ALICLOUD_SECRET_KEY=yyy ALICLOUD_REGION=cn-beijing
|
||||
bin/vela addon enable rollout
|
||||
bin/vela addon enable ./e2e/addon/mock/testdata/fluxcd
|
||||
bin/vela addon enable ./e2e/addon/mock/testdata/terraform
|
||||
bin/vela addon enable ./e2e/addon/mock/testdata/terraform-alibaba ALICLOUD_ACCESS_KEY=xxx ALICLOUD_SECRET_KEY=yyy ALICLOUD_REGION=cn-beijing
|
||||
bin/vela addon enable ./e2e/addon/mock/testdata/rollout
|
||||
ginkgo version
|
||||
ginkgo -v -r e2e/setup
|
||||
|
||||
|
||||
@@ -79,6 +79,9 @@ const (
|
||||
// ReadmeFileName is the addon readme file name
|
||||
ReadmeFileName string = "README.md"
|
||||
|
||||
// LegacyReadmeFileName is the addon readme lower case file name
|
||||
LegacyReadmeFileName string = "readme.md"
|
||||
|
||||
// MetadataFileName is the addon meatadata.yaml file name
|
||||
MetadataFileName string = "metadata.yaml"
|
||||
|
||||
@@ -205,7 +208,7 @@ type Pattern struct {
|
||||
var Patterns = []Pattern{
|
||||
{Value: ReadmeFileName}, {Value: MetadataFileName}, {Value: TemplateFileName},
|
||||
{Value: ParameterFileName}, {IsDir: true, Value: ResourcesDirName}, {IsDir: true, Value: DefinitionsDirName},
|
||||
{IsDir: true, Value: DefSchemaName}, {IsDir: true, Value: ViewDirName}, {Value: AppTemplateCueFileName}, {Value: GlobalParameterFileName}}
|
||||
{IsDir: true, Value: DefSchemaName}, {IsDir: true, Value: ViewDirName}, {Value: AppTemplateCueFileName}, {Value: GlobalParameterFileName}, {Value: LegacyReadmeFileName}}
|
||||
|
||||
// GetPatternFromItem will check if the file path has a valid pattern, return empty string if it's invalid.
|
||||
// AsyncReader is needed to calculate relative path
|
||||
@@ -285,6 +288,7 @@ func GetUIDataFromReader(r AsyncReader, meta *SourceMeta, opt ListOptions) (*UID
|
||||
read func(a *UIData, reader AsyncReader, readPath string) error
|
||||
}{
|
||||
ReadmeFileName: {!opt.GetDetail, readReadme},
|
||||
LegacyReadmeFileName: {!opt.GetDetail, readReadme},
|
||||
MetadataFileName: {false, readMetadata},
|
||||
DefinitionsDirName: {!opt.GetDefinition, readDefFile},
|
||||
ParameterFileName: {!opt.GetParameter, readParamFile},
|
||||
@@ -481,6 +485,10 @@ func readMetadata(a *UIData, reader AsyncReader, readPath string) error {
|
||||
}
|
||||
|
||||
func readReadme(a *UIData, reader AsyncReader, readPath string) error {
|
||||
// the detail will contain readme.md or README.md, if the content already is filled, don't read another.
|
||||
if len(a.Detail) != 0 {
|
||||
return nil
|
||||
}
|
||||
content, err := reader.ReadFile(readPath)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -675,7 +683,7 @@ func RenderDefinitions(addon *InstallPackage, config *rest.Config) ([]*unstructu
|
||||
for _, def := range addon.Definitions {
|
||||
obj, err := renderObject(def)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrapf(err, "render definition file %s", def.Name)
|
||||
}
|
||||
// we should ignore the namespace defined in definition yaml, override the filed by DefaultKubeVelaNS
|
||||
obj.SetNamespace(types.DefaultKubeVelaNS)
|
||||
@@ -704,7 +712,7 @@ func RenderDefinitionSchema(addon *InstallPackage) ([]*unstructured.Unstructured
|
||||
for _, teml := range addon.DefSchemas {
|
||||
u, err := renderSchemaConfigmap(teml)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrapf(err, "render uiSchema file %s", teml.Name)
|
||||
}
|
||||
schemaConfigmaps = append(schemaConfigmaps, u)
|
||||
}
|
||||
@@ -717,14 +725,14 @@ func RenderViews(addon *InstallPackage) ([]*unstructured.Unstructured, error) {
|
||||
for _, view := range addon.YAMLViews {
|
||||
obj, err := renderObject(view)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrapf(err, "render velaQL view file %s", view.Name)
|
||||
}
|
||||
views = append(views, obj)
|
||||
}
|
||||
for _, view := range addon.CUEViews {
|
||||
obj, err := renderCUEView(view)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrapf(err, "render velaQL view file %s", view.Name)
|
||||
}
|
||||
views = append(views, obj)
|
||||
}
|
||||
@@ -788,7 +796,7 @@ func renderK8sObjectsComponent(elems []ElementFile, addonName string) (*common2.
|
||||
for _, elem := range elems {
|
||||
obj, err := renderObject(elem)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrapf(err, "render resource file %s", elem.Name)
|
||||
}
|
||||
objects = append(objects, obj)
|
||||
}
|
||||
@@ -889,6 +897,7 @@ type Installer struct {
|
||||
cache *Cache
|
||||
dc *discovery.DiscoveryClient
|
||||
skipVersionValidate bool
|
||||
overrideDefs bool
|
||||
}
|
||||
|
||||
// NewAddonInstaller will create an installer for addon
|
||||
@@ -1069,6 +1078,16 @@ func (h *Installer) dispatchAddonResource(addon *InstallPackage) error {
|
||||
return errors.Wrap(err, "render addon definitions fail")
|
||||
}
|
||||
|
||||
if !h.overrideDefs {
|
||||
existDefs, err := checkConflictDefs(h.ctx, h.cli, defs, app.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(existDefs) != 0 {
|
||||
return produceDefConflictError(existDefs)
|
||||
}
|
||||
}
|
||||
|
||||
schemas, err := RenderDefinitionSchema(addon)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "render addon definitions' schema fail")
|
||||
@@ -1088,6 +1107,10 @@ func (h *Installer) dispatchAddonResource(addon *InstallPackage) error {
|
||||
}
|
||||
|
||||
for _, def := range defs {
|
||||
if !checkBondComponentExist(*def, *app) {
|
||||
continue
|
||||
}
|
||||
// if binding component exist, apply the definition
|
||||
addOwner(def, app)
|
||||
err = h.apply.Apply(h.ctx, def, apply.DisableUpdateAnnotation())
|
||||
if err != nil {
|
||||
@@ -1112,6 +1135,9 @@ func (h *Installer) dispatchAddonResource(addon *InstallPackage) error {
|
||||
}
|
||||
|
||||
for _, o := range auxiliaryOutputs {
|
||||
if !checkBondComponentExist(*o, *app) {
|
||||
continue
|
||||
}
|
||||
addOwner(o, app)
|
||||
err = h.apply.Apply(h.ctx, o, apply.DisableUpdateAnnotation())
|
||||
if err != nil {
|
||||
@@ -1286,26 +1312,30 @@ func checkSemVer(actual string, require string) (bool, error) {
|
||||
if len(require) == 0 {
|
||||
return true, nil
|
||||
}
|
||||
smeVer := strings.TrimPrefix(actual, "v")
|
||||
semVer := strings.TrimPrefix(actual, "v")
|
||||
l := strings.ReplaceAll(require, "v", " ")
|
||||
constraint, err := semver.NewConstraint(l)
|
||||
if err != nil {
|
||||
log.Logger.Errorf("fail to new constraint: %s", err.Error())
|
||||
return false, err
|
||||
}
|
||||
v, err := semver.NewVersion(smeVer)
|
||||
v, err := semver.NewVersion(semVer)
|
||||
if err != nil {
|
||||
log.Logger.Errorf("fail to new version %s: %s", smeVer, err.Error())
|
||||
log.Logger.Errorf("fail to new version %s: %s", semVer, err.Error())
|
||||
return false, err
|
||||
}
|
||||
if constraint.Check(v) {
|
||||
return true, nil
|
||||
}
|
||||
if strings.Contains(actual, "-") && !strings.Contains(require, "-") {
|
||||
smeVer := strings.TrimPrefix(actual[:strings.Index(actual, "-")], "v")
|
||||
v, err := semver.NewVersion(smeVer)
|
||||
semVer := strings.TrimPrefix(actual[:strings.Index(actual, "-")], "v")
|
||||
if strings.Contains(require, ">=") && require[strings.Index(require, "=")+1:] == semVer {
|
||||
// for case: `actual` is 1.5.0-beta.1 require is >=`1.5.0`
|
||||
return false, nil
|
||||
}
|
||||
v, err := semver.NewVersion(semVer)
|
||||
if err != nil {
|
||||
log.Logger.Errorf("fail to new version %s: %s", smeVer, err.Error())
|
||||
log.Logger.Errorf("fail to new version %s: %s", semVer, err.Error())
|
||||
return false, err
|
||||
}
|
||||
if constraint.Check(v) {
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
types2 "k8s.io/apimachinery/pkg/types"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
@@ -396,6 +397,60 @@ var _ = Describe("test enable addon which applies the views independently", func
|
||||
})
|
||||
})
|
||||
|
||||
var _ = Describe("test override defs of addon", func() {
|
||||
It("test compDef exist", func() {
|
||||
ctx := context.Background()
|
||||
comp := v1beta1.ComponentDefinition{TypeMeta: metav1.TypeMeta{APIVersion: v1beta1.SchemeGroupVersion.String(), Kind: v1beta1.ComponentDefinitionKind}}
|
||||
Expect(yaml.Unmarshal([]byte(helmCompDefYaml), &comp)).Should(BeNil())
|
||||
Expect(k8sClient.Create(ctx, &comp)).Should(BeNil())
|
||||
|
||||
comp2 := v1beta1.ComponentDefinition{TypeMeta: metav1.TypeMeta{APIVersion: v1beta1.SchemeGroupVersion.String(), Kind: v1beta1.ComponentDefinitionKind}}
|
||||
Expect(yaml.Unmarshal([]byte(kustomizeCompDefYaml), &comp2)).Should(BeNil())
|
||||
Expect(k8sClient.Create(ctx, &comp2)).Should(BeNil())
|
||||
app := v1beta1.Application{ObjectMeta: metav1.ObjectMeta{Name: "addon-fluxcd"}}
|
||||
|
||||
comp3 := v1beta1.ComponentDefinition{TypeMeta: metav1.TypeMeta{APIVersion: v1beta1.SchemeGroupVersion.String(), Kind: v1beta1.ComponentDefinitionKind}}
|
||||
Expect(yaml.Unmarshal([]byte(kustomizeCompDefYaml1), &comp3)).Should(BeNil())
|
||||
Expect(k8sClient.Create(ctx, &comp3)).Should(BeNil())
|
||||
|
||||
compUnstructured, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&comp)
|
||||
Expect(err).Should(BeNil())
|
||||
u := unstructured.Unstructured{Object: compUnstructured}
|
||||
u.SetAPIVersion(v1beta1.SchemeGroupVersion.String())
|
||||
u.SetKind(v1beta1.ComponentDefinitionKind)
|
||||
c, err := checkConflictDefs(ctx, k8sClient, []*unstructured.Unstructured{&u}, app.GetName())
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(len(c)).Should(BeEquivalentTo(1))
|
||||
|
||||
u.SetName("rollout")
|
||||
c, err = checkConflictDefs(ctx, k8sClient, []*unstructured.Unstructured{&u}, app.GetName())
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(len(c)).Should(BeEquivalentTo(0))
|
||||
|
||||
u.SetKind("NotExistKind")
|
||||
_, err = checkConflictDefs(ctx, k8sClient, []*unstructured.Unstructured{&u}, app.GetName())
|
||||
Expect(err).ShouldNot(BeNil())
|
||||
|
||||
compUnstructured2, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&comp2)
|
||||
Expect(err).Should(BeNil())
|
||||
u2 := &unstructured.Unstructured{Object: compUnstructured2}
|
||||
u2.SetAPIVersion(v1beta1.SchemeGroupVersion.String())
|
||||
u2.SetKind(v1beta1.ComponentDefinitionKind)
|
||||
c, err = checkConflictDefs(ctx, k8sClient, []*unstructured.Unstructured{u2}, app.GetName())
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(len(c)).Should(BeEquivalentTo(1))
|
||||
|
||||
compUnstructured3, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&comp3)
|
||||
Expect(err).Should(BeNil())
|
||||
u3 := &unstructured.Unstructured{Object: compUnstructured3}
|
||||
u3.SetAPIVersion(v1beta1.SchemeGroupVersion.String())
|
||||
u3.SetKind(v1beta1.ComponentDefinitionKind)
|
||||
c, err = checkConflictDefs(ctx, k8sClient, []*unstructured.Unstructured{u3}, app.GetName())
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(len(c)).Should(BeEquivalentTo(0))
|
||||
})
|
||||
})
|
||||
|
||||
const (
|
||||
appYaml = `apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
@@ -491,5 +546,49 @@ spec:
|
||||
properties:
|
||||
image: crccheck/hello-world
|
||||
port: 8000
|
||||
`
|
||||
helmCompDefYaml = `
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: ComponentDefinition
|
||||
metadata:
|
||||
name: helm
|
||||
namespace: vela-system
|
||||
ownerReferences:
|
||||
- apiVersion: core.oam.dev/v1beta1
|
||||
blockOwnerDeletion: true
|
||||
controller: true
|
||||
kind: Application
|
||||
name: addon-fluxcd-helm
|
||||
uid: 73c47933-002e-4182-a673-6da6a9dcf080
|
||||
spec:
|
||||
schematic:
|
||||
cue:
|
||||
`
|
||||
kustomizeCompDefYaml = `
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: ComponentDefinition
|
||||
metadata:
|
||||
name: kustomize
|
||||
namespace: vela-system
|
||||
spec:
|
||||
schematic:
|
||||
cue:
|
||||
`
|
||||
kustomizeCompDefYaml1 = `
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: ComponentDefinition
|
||||
metadata:
|
||||
name: kustomize-another
|
||||
namespace: vela-system
|
||||
ownerReferences:
|
||||
- apiVersion: core.oam.dev/v1beta1
|
||||
blockOwnerDeletion: true
|
||||
controller: true
|
||||
kind: Application
|
||||
name: addon-fluxcd
|
||||
uid: 73c47933-002e-4182-a673-6da6a9dcf080
|
||||
spec:
|
||||
schematic:
|
||||
cue:
|
||||
`
|
||||
)
|
||||
|
||||
@@ -945,6 +945,16 @@ func TestCheckSemVer(t *testing.T) {
|
||||
require: ">=v1.2.4-beta.3",
|
||||
res: false,
|
||||
},
|
||||
{
|
||||
actual: "1.5.0-beta.2",
|
||||
require: ">=1.5.0",
|
||||
res: false,
|
||||
},
|
||||
{
|
||||
actual: "1.5.0-alpha.2",
|
||||
require: ">=1.5.0",
|
||||
res: false,
|
||||
},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
result, err := checkSemVer(testCase.actual, testCase.require)
|
||||
@@ -1306,3 +1316,15 @@ func TestMergeAddonInstallArgs(t *testing.T) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestGenerateConflictError(t *testing.T) {
|
||||
confictAddon := map[string]string{
|
||||
"helm": "definition: helm already exist and not belong to any addon \n",
|
||||
"kustomize": "definition: kustomize in this addon already exist in fluxcd \n",
|
||||
}
|
||||
err := produceDefConflictError(confictAddon)
|
||||
assert.Error(t, err)
|
||||
strings.Contains(err.Error(), "in this addon already exist in fluxcd")
|
||||
|
||||
assert.NoError(t, produceDefConflictError(map[string]string{}))
|
||||
}
|
||||
|
||||
@@ -180,9 +180,7 @@ func (cmd *InitCmd) createRequiredFiles() {
|
||||
Description: "An addon for KubeVela.",
|
||||
Tags: []string{"my-tag"},
|
||||
Dependencies: []*Dependency{},
|
||||
DeployTo: &DeployTo{
|
||||
RuntimeCluster: false,
|
||||
},
|
||||
DeployTo: nil,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -507,10 +505,6 @@ parameter: {
|
||||
output: {
|
||||
apiVersion: "core.oam.dev/v1beta1"
|
||||
kind: "Application"
|
||||
metadata: {
|
||||
name: "my-addon-name"
|
||||
namespace: "vela-system"
|
||||
}
|
||||
spec: {
|
||||
components: []
|
||||
policies: []
|
||||
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/klog/v2"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
common2 "github.com/oam-dev/kubevela/apis/core.oam.dev/common"
|
||||
@@ -189,9 +190,17 @@ func generateAppFramework(addon *InstallPackage, parameters map[string]interface
|
||||
}
|
||||
}
|
||||
|
||||
app.Name = addonutil.Addon2AppName(addon.Name)
|
||||
// force override the namespace defined vela with DefaultVelaNS,this value can be modified by Env
|
||||
if app.Name != "" && app.Name != addonutil.Addon2AppName(addon.Name) {
|
||||
klog.Warningf("Application name %s will be overwritten with %s. Consider removing metadata.name in template.", app.Name, addonutil.Addon2AppName(addon.Name))
|
||||
}
|
||||
app.SetName(addonutil.Addon2AppName(addon.Name))
|
||||
|
||||
if app.Namespace != "" && app.Namespace != types.DefaultKubeVelaNS {
|
||||
klog.Warningf("Namespace %s will be overwritten with %s. Consider removing metadata.namespace in template.", app.Namespace, types.DefaultKubeVelaNS)
|
||||
}
|
||||
// force override the namespace defined vela with DefaultVelaNS. This value can be modified by env
|
||||
app.SetNamespace(types.DefaultKubeVelaNS)
|
||||
|
||||
if app.Labels == nil {
|
||||
app.Labels = make(map[string]string)
|
||||
}
|
||||
@@ -319,7 +328,7 @@ func renderResources(addon *InstallPackage, args map[string]interface{}) ([]comm
|
||||
if len(addon.YAMLTemplates) != 0 {
|
||||
comp, err := renderK8sObjectsComponent(addon.YAMLTemplates, addon.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrapf(err, "render components from yaml template")
|
||||
}
|
||||
resources = append(resources, *comp)
|
||||
}
|
||||
@@ -345,6 +354,7 @@ func checkNeedAttachTopologyPolicy(app *v1beta1.Application, addon *InstallPacka
|
||||
}
|
||||
for _, policy := range app.Spec.Policies {
|
||||
if policy.Type == v1alpha1.TopologyPolicyType {
|
||||
klog.Warningf("deployTo in metadata will NOT have any effect. It conflicts with %s policy named %s. Consider removing deployTo field in addon metadata.", v1alpha1.TopologyPolicyType, policy.Name)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ import (
|
||||
errors "github.com/pkg/errors"
|
||||
"helm.sh/helm/v3/pkg/chart"
|
||||
"helm.sh/helm/v3/pkg/chartutil"
|
||||
errors2 "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
rest "k8s.io/client-go/rest"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
@@ -36,6 +38,7 @@ import (
|
||||
"github.com/oam-dev/kubevela/pkg/definition"
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
"github.com/oam-dev/kubevela/pkg/oam/util"
|
||||
"github.com/oam-dev/kubevela/pkg/utils/addon"
|
||||
"github.com/oam-dev/kubevela/pkg/utils/common"
|
||||
)
|
||||
|
||||
@@ -43,13 +46,22 @@ const (
|
||||
compDefAnnotation = "addon.oam.dev/componentDefinitions"
|
||||
traitDefAnnotation = "addon.oam.dev/traitDefinitions"
|
||||
workflowStepDefAnnotation = "addon.oam.dev/workflowStepDefinitions"
|
||||
policyDefAnnotation = "addon.oam.dev/policyDefinitions"
|
||||
defKeytemplate = "addon-%s-%s"
|
||||
compMapKey = "comp"
|
||||
traitMapKey = "trait"
|
||||
wfStepMapKey = "wfStep"
|
||||
policyMapKey = "policy"
|
||||
)
|
||||
|
||||
// parse addon's created x-defs in addon-app's annotation, this will be used to check whether app still using it while disabling.
|
||||
func passDefInAppAnnotation(defs []*unstructured.Unstructured, app *v1beta1.Application) error {
|
||||
var comps, traits, workflowSteps []string
|
||||
var comps, traits, workflowSteps, policies []string
|
||||
for _, def := range defs {
|
||||
if !checkBondComponentExist(*def, *app) {
|
||||
// if the definition binding a component, and the component not exist, skip recording.
|
||||
continue
|
||||
}
|
||||
switch def.GetObjectKind().GroupVersionKind().Kind {
|
||||
case v1beta1.ComponentDefinitionKind:
|
||||
comps = append(comps, def.GetName())
|
||||
@@ -57,6 +69,8 @@ func passDefInAppAnnotation(defs []*unstructured.Unstructured, app *v1beta1.Appl
|
||||
traits = append(traits, def.GetName())
|
||||
case v1beta1.WorkflowStepDefinitionKind:
|
||||
workflowSteps = append(workflowSteps, def.GetName())
|
||||
case v1beta1.PolicyDefinitionKind:
|
||||
policies = append(policies, def.GetName())
|
||||
default:
|
||||
return fmt.Errorf("cannot handle definition types %s, name %s", def.GetObjectKind().GroupVersionKind().Kind, def.GetName())
|
||||
}
|
||||
@@ -70,6 +84,9 @@ func passDefInAppAnnotation(defs []*unstructured.Unstructured, app *v1beta1.Appl
|
||||
if len(workflowSteps) != 0 {
|
||||
app.SetAnnotations(util.MergeMapOverrideWithDst(app.GetAnnotations(), map[string]string{workflowStepDefAnnotation: strings.Join(workflowSteps, ",")}))
|
||||
}
|
||||
if len(policies) != 0 {
|
||||
app.SetAnnotations(util.MergeMapOverrideWithDst(app.GetAnnotations(), map[string]string{policyDefAnnotation: strings.Join(policies, ",")}))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -87,7 +104,7 @@ func checkAddonHasBeenUsed(ctx context.Context, k8sClient client.Client, name st
|
||||
createdDefs := make(map[string]bool)
|
||||
for key, defNames := range addonApp.GetAnnotations() {
|
||||
switch key {
|
||||
case compDefAnnotation, traitDefAnnotation, workflowStepDefAnnotation:
|
||||
case compDefAnnotation, traitDefAnnotation, workflowStepDefAnnotation, policyDefAnnotation:
|
||||
merge2DefMap(key, defNames, createdDefs)
|
||||
}
|
||||
}
|
||||
@@ -102,25 +119,34 @@ func checkAddonHasBeenUsed(ctx context.Context, k8sClient client.Client, name st
|
||||
CHECKNEXT:
|
||||
for _, app := range apps.Items {
|
||||
for _, component := range app.Spec.Components {
|
||||
if createdDefs[fmt.Sprintf(defKeytemplate, "comp", component.Type)] {
|
||||
if createdDefs[fmt.Sprintf(defKeytemplate, compMapKey, component.Type)] {
|
||||
res = append(res, app)
|
||||
// this app has used this addon, there is no need check other components
|
||||
continue CHECKNEXT
|
||||
}
|
||||
for _, trait := range component.Traits {
|
||||
if createdDefs[fmt.Sprintf(defKeytemplate, "trait", trait.Type)] {
|
||||
if createdDefs[fmt.Sprintf(defKeytemplate, traitMapKey, trait.Type)] {
|
||||
res = append(res, app)
|
||||
continue CHECKNEXT
|
||||
}
|
||||
}
|
||||
}
|
||||
if app.Spec.Workflow == nil || len(app.Spec.Workflow.Steps) == 0 {
|
||||
return res, nil
|
||||
|
||||
if app.Spec.Workflow != nil && len(app.Spec.Workflow.Steps) != 0 {
|
||||
for _, s := range app.Spec.Workflow.Steps {
|
||||
if createdDefs[fmt.Sprintf(defKeytemplate, wfStepMapKey, s.Type)] {
|
||||
res = append(res, app)
|
||||
continue CHECKNEXT
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, s := range app.Spec.Workflow.Steps {
|
||||
if createdDefs[fmt.Sprintf(defKeytemplate, "wfStep", s.Type)] {
|
||||
res = append(res, app)
|
||||
continue CHECKNEXT
|
||||
|
||||
if app.Spec.Policies != nil && len(app.Spec.Policies) != 0 {
|
||||
for _, p := range app.Spec.Policies {
|
||||
if createdDefs[fmt.Sprintf(defKeytemplate, policyMapKey, p.Type)] {
|
||||
res = append(res, app)
|
||||
continue CHECKNEXT
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -134,11 +160,13 @@ func merge2DefMap(defType string, defNames string, defMap map[string]bool) {
|
||||
for _, defName := range list {
|
||||
switch defType {
|
||||
case compDefAnnotation:
|
||||
defMap[fmt.Sprintf(template, "comp", defName)] = true
|
||||
defMap[fmt.Sprintf(template, compMapKey, defName)] = true
|
||||
case traitDefAnnotation:
|
||||
defMap[fmt.Sprintf(template, "trait", defName)] = true
|
||||
defMap[fmt.Sprintf(template, traitMapKey, defName)] = true
|
||||
case workflowStepDefAnnotation:
|
||||
defMap[fmt.Sprintf(template, "wfStep", defName)] = true
|
||||
defMap[fmt.Sprintf(template, wfStepMapKey, defName)] = true
|
||||
case policyDefAnnotation:
|
||||
defMap[fmt.Sprintf(template, policyMapKey, defName)] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -210,6 +238,8 @@ func findLegacyAddonDefs(ctx context.Context, k8sClient client.Client, addonName
|
||||
defs[fmt.Sprintf(defKeytemplate, "trait", defObject.GetName())] = true
|
||||
case v1beta1.WorkflowStepDefinitionKind:
|
||||
defs[fmt.Sprintf(defKeytemplate, "wfStep", defObject.GetName())] = true
|
||||
case v1beta1.PolicyDefinitionKind:
|
||||
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -242,6 +272,11 @@ func SkipValidateVersion(installer *Installer) {
|
||||
installer.skipVersionValidate = true
|
||||
}
|
||||
|
||||
// OverrideDefinitions menas override definitions within this addon if some of them already exist
|
||||
func OverrideDefinitions(installer *Installer) {
|
||||
installer.overrideDefs = true
|
||||
}
|
||||
|
||||
// IsAddonDir validates an addon directory.
|
||||
// It checks required files like metadata.yaml and template.yaml
|
||||
func IsAddonDir(dirName string) (bool, error) {
|
||||
@@ -409,3 +444,54 @@ func generateAnnotation(meta *Meta) map[string]string {
|
||||
func isErrorCueRenderPathNotFound(err error, path string) bool {
|
||||
return err.Error() == fmt.Sprintf("var(path=%s) not exist", path)
|
||||
}
|
||||
|
||||
func checkConflictDefs(ctx context.Context, k8sClient client.Client, defs []*unstructured.Unstructured, appName string) (map[string]string, error) {
|
||||
res := map[string]string{}
|
||||
for _, def := range defs {
|
||||
err := k8sClient.Get(ctx, client.ObjectKeyFromObject(def), def)
|
||||
if err == nil {
|
||||
owner := metav1.GetControllerOf(def)
|
||||
if owner == nil || owner.Kind != v1beta1.ApplicationKind {
|
||||
res[def.GetName()] = fmt.Sprintf("definition: %s already exist and not belong to any addon \n", def.GetName())
|
||||
continue
|
||||
}
|
||||
if owner.Name != appName {
|
||||
// if addon not belong to an addon or addon name is another one, we should put them in result
|
||||
res[def.GetName()] = fmt.Sprintf("definition: %s in this addon already exist in %s \n", def.GetName(), addon.AppName2Addon(appName))
|
||||
}
|
||||
}
|
||||
if err != nil && !errors2.IsNotFound(err) {
|
||||
return nil, errors.Wrapf(err, "check definition %s", def.GetName())
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func produceDefConflictError(conflictDefs map[string]string) error {
|
||||
if len(conflictDefs) == 0 {
|
||||
return nil
|
||||
}
|
||||
var errorInfo string
|
||||
for _, s := range conflictDefs {
|
||||
errorInfo += s
|
||||
}
|
||||
errorInfo += "if you want override them, please use argument '--override-definitions' to enable \n"
|
||||
return errors.New(errorInfo)
|
||||
}
|
||||
|
||||
// checkBondComponentExistt will check the ready-to-apply object(def or auxiliary outputs) whether bind to a component
|
||||
// if the target component not exist, return false.
|
||||
func checkBondComponentExist(u unstructured.Unstructured, app v1beta1.Application) bool {
|
||||
comp, existKey := u.GetAnnotations()[oam.AnnotationIgnoreWithoutCompKey]
|
||||
if !existKey {
|
||||
// if an object(def or auxiliary outputs ) binding no components return true
|
||||
return true
|
||||
}
|
||||
for _, component := range app.Spec.Components {
|
||||
if component.Name == comp {
|
||||
// the bond component exists, return ture
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
velatypes "github.com/oam-dev/kubevela/apis/types"
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
@@ -108,9 +109,13 @@ var _ = Describe("Test definition check", func() {
|
||||
Expect(yaml.Unmarshal([]byte(testApp3Yaml), &app3)).Should(BeNil())
|
||||
Expect(k8sClient.Create(ctx, &app3)).Should(BeNil())
|
||||
|
||||
app4 := v1beta1.Application{}
|
||||
Expect(yaml.Unmarshal([]byte(testApp4Yaml), &app4)).Should(BeNil())
|
||||
Expect(k8sClient.Create(ctx, &app4)).Should(BeNil())
|
||||
|
||||
usedApps, err := checkAddonHasBeenUsed(ctx, k8sClient, "my-addon", addonApp, cfg)
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(len(usedApps)).Should(BeEquivalentTo(3))
|
||||
Expect(len(usedApps)).Should(BeEquivalentTo(4))
|
||||
})
|
||||
|
||||
It("check fetch lagacy addon definitions", func() {
|
||||
@@ -283,6 +288,36 @@ func TestMakeChart(t *testing.T) {
|
||||
assert.Equal(t, isChartDir, true)
|
||||
}
|
||||
|
||||
func TestCheckObjectBindingComponent(t *testing.T) {
|
||||
existingBindingDef := unstructured.Unstructured{}
|
||||
existingBindingDef.SetAnnotations(map[string]string{oam.AnnotationIgnoreWithoutCompKey: "kustomize"})
|
||||
|
||||
emptyAnnoDef := unstructured.Unstructured{}
|
||||
emptyAnnoDef.SetAnnotations(map[string]string{"test": "onlyForTest"})
|
||||
testCases := map[string]struct {
|
||||
object unstructured.Unstructured
|
||||
app v1beta1.Application
|
||||
res bool
|
||||
}{
|
||||
"bindingExist": {object: existingBindingDef,
|
||||
app: v1beta1.Application{Spec: v1beta1.ApplicationSpec{Components: []common.ApplicationComponent{{Name: "kustomize"}}}},
|
||||
res: true},
|
||||
"NotExisting": {object: existingBindingDef,
|
||||
app: v1beta1.Application{Spec: v1beta1.ApplicationSpec{Components: []common.ApplicationComponent{{Name: "helm"}}}},
|
||||
res: false},
|
||||
"NoBidingAnnotation": {object: emptyAnnoDef,
|
||||
app: v1beta1.Application{Spec: v1beta1.ApplicationSpec{Components: []common.ApplicationComponent{{Name: "kustomize"}}}},
|
||||
res: true},
|
||||
"EmptyApp": {object: existingBindingDef,
|
||||
app: v1beta1.Application{Spec: v1beta1.ApplicationSpec{Components: []common.ApplicationComponent{}}},
|
||||
res: false},
|
||||
}
|
||||
for _, s := range testCases {
|
||||
result := checkBondComponentExist(s.object, s.app)
|
||||
assert.Equal(t, result, s.res)
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
compDefYaml = `
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
@@ -319,6 +354,7 @@ metadata:
|
||||
addon.oam.dev/componentDefinitions: "my-comp"
|
||||
addon.oam.dev/traitDefinitions: "my-trait"
|
||||
addon.oam.dev/workflowStepDefinitions: "my-wfstep"
|
||||
addon.oam.dev/policyDefinitions: "my-policy"
|
||||
name: addon-myaddon
|
||||
namespace: vela-system
|
||||
spec:
|
||||
@@ -367,6 +403,22 @@ spec:
|
||||
- type: my-wfstep
|
||||
name: deploy
|
||||
`
|
||||
testApp4Yaml = `
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: app-4
|
||||
namespace: test-ns
|
||||
spec:
|
||||
components:
|
||||
- name: podinfo
|
||||
type: webservice
|
||||
|
||||
policies:
|
||||
- type: my-policy
|
||||
name: topology
|
||||
`
|
||||
|
||||
registryCmYaml = `
|
||||
apiVersion: v1
|
||||
data:
|
||||
|
||||
@@ -86,6 +86,7 @@ func (i *versionedRegistry) GetAddonUIData(ctx context.Context, addonName, versi
|
||||
Detail: wholePackage.Detail,
|
||||
Definitions: wholePackage.Definitions,
|
||||
AvailableVersions: wholePackage.AvailableVersions,
|
||||
CUEDefinitions: wholePackage.CUEDefinitions,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -32,11 +32,12 @@ const (
|
||||
// SystemInfo systemInfo model
|
||||
type SystemInfo struct {
|
||||
BaseModel
|
||||
InstallID string `json:"installID"`
|
||||
EnableCollection bool `json:"enableCollection"`
|
||||
StatisticInfo StatisticInfo `json:"statisticInfo,omitempty"`
|
||||
LoginType string `json:"loginType"`
|
||||
DexUserDefaultProjects []ProjectRef `json:"projects"`
|
||||
InstallID string `json:"installID"`
|
||||
EnableCollection bool `json:"enableCollection"`
|
||||
StatisticInfo StatisticInfo `json:"statisticInfo,omitempty"`
|
||||
LoginType string `json:"loginType"`
|
||||
DexUserDefaultProjects []ProjectRef `json:"projects"`
|
||||
DexUserDefaultPlatformRoles []string `json:"dexUserDefaultPlatformRoles"`
|
||||
}
|
||||
|
||||
// ProjectRef set the project name and roles
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
errors3 "github.com/pkg/errors"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
errors2 "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
@@ -44,6 +45,7 @@ import (
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/utils"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/utils/bcode"
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/utils/log"
|
||||
"github.com/oam-dev/kubevela/pkg/definition"
|
||||
"github.com/oam-dev/kubevela/pkg/multicluster"
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
addonutil "github.com/oam-dev/kubevela/pkg/utils/addon"
|
||||
@@ -68,7 +70,7 @@ type AddonService interface {
|
||||
}
|
||||
|
||||
// AddonImpl2AddonRes convert pkgaddon.UIData to the type apiserver need
|
||||
func AddonImpl2AddonRes(impl *pkgaddon.UIData) (*apis.DetailAddonResponse, error) {
|
||||
func AddonImpl2AddonRes(impl *pkgaddon.UIData, config *rest.Config) (*apis.DetailAddonResponse, error) {
|
||||
var defs []*apis.AddonDefinition
|
||||
for _, def := range impl.Definitions {
|
||||
obj := &unstructured.Unstructured{}
|
||||
@@ -83,6 +85,20 @@ func AddonImpl2AddonRes(impl *pkgaddon.UIData) (*apis.DetailAddonResponse, error
|
||||
Description: obj.GetAnnotations()["definition.oam.dev/description"],
|
||||
})
|
||||
}
|
||||
|
||||
for _, cueDef := range impl.CUEDefinitions {
|
||||
def := definition.Definition{Unstructured: unstructured.Unstructured{}}
|
||||
err := def.FromCUEString(cueDef.Data, config)
|
||||
if err != nil {
|
||||
return nil, errors3.Wrapf(err, "fail to render definition: %s in cue's format", cueDef.Name)
|
||||
}
|
||||
defs = append(defs, &apis.AddonDefinition{
|
||||
Name: def.GetName(),
|
||||
DefType: def.GetKind(),
|
||||
Description: def.GetAnnotations()["definition.oam.dev/description"],
|
||||
})
|
||||
}
|
||||
|
||||
if impl.Meta.DeployTo != nil && impl.Meta.DeployTo.LegacyRuntimeCluster != impl.Meta.DeployTo.RuntimeCluster {
|
||||
impl.Meta.DeployTo.LegacyRuntimeCluster = impl.Meta.DeployTo.LegacyRuntimeCluster || impl.Meta.DeployTo.RuntimeCluster
|
||||
impl.Meta.DeployTo.RuntimeCluster = impl.Meta.DeployTo.LegacyRuntimeCluster || impl.Meta.DeployTo.RuntimeCluster
|
||||
@@ -175,7 +191,7 @@ func (u *addonServiceImpl) GetAddon(ctx context.Context, name string, registry s
|
||||
|
||||
addon.UISchema = renderAddonCustomUISchema(ctx, u.kubeClient, name, renderDefaultUISchema(addon.APISchema))
|
||||
|
||||
a, err := AddonImpl2AddonRes(addon)
|
||||
a, err := AddonImpl2AddonRes(addon, u.config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -284,7 +300,7 @@ func (u *addonServiceImpl) ListAddons(ctx context.Context, registry, query strin
|
||||
|
||||
var addonResources []*apis.DetailAddonResponse
|
||||
for _, a := range addons {
|
||||
addonRes, err := AddonImpl2AddonRes(a)
|
||||
addonRes, err := AddonImpl2AddonRes(a, u.config)
|
||||
if err != nil {
|
||||
log.Logger.Errorf("err while converting AddonImpl to DetailAddonResponse: %v", err)
|
||||
continue
|
||||
|
||||
@@ -484,6 +484,10 @@ func (d *dexHandlerImpl) login(ctx context.Context) (*apisv1.UserBase, error) {
|
||||
}
|
||||
userBase = convertUserBase(u)
|
||||
} else {
|
||||
systemInfo, err := d.systemInfoService.GetSystemInfo(ctx)
|
||||
if err != nil {
|
||||
log.Logger.Errorf("failed to get the system info %s", err.Error())
|
||||
}
|
||||
user := &model.User{
|
||||
Email: claims.Email,
|
||||
Name: strings.ToLower(claims.Sub),
|
||||
@@ -491,18 +495,17 @@ func (d *dexHandlerImpl) login(ctx context.Context) (*apisv1.UserBase, error) {
|
||||
Alias: claims.Name,
|
||||
LastLoginTime: time.Now(),
|
||||
}
|
||||
if systemInfo != nil {
|
||||
user.UserRoles = systemInfo.DexUserDefaultPlatformRoles
|
||||
}
|
||||
if err := d.Store.Add(ctx, user); err != nil {
|
||||
log.Logger.Errorf("failed to save the user from the dex: %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
systemInfo, err := d.systemInfoService.GetSystemInfo(ctx)
|
||||
if err != nil {
|
||||
log.Logger.Errorf("failed to get the system info %s", err.Error())
|
||||
}
|
||||
if systemInfo != nil {
|
||||
for _, project := range systemInfo.DexUserDefaultProjects {
|
||||
_, err := d.projectService.AddProjectUser(ctx, project.Name, apisv1.AddProjectUserRequest{
|
||||
UserName: claims.Sub,
|
||||
UserName: strings.ToLower(claims.Sub),
|
||||
UserRoles: project.Roles,
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"io/ioutil"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
. "github.com/agiledragon/gomonkey/v2"
|
||||
@@ -65,7 +66,7 @@ var _ = Describe("Test authentication service functions", func() {
|
||||
})
|
||||
It("Test Dex login", func() {
|
||||
testIDToken := &oidc.IDToken{}
|
||||
sub := "248289761001"
|
||||
sub := "248289761001Abv"
|
||||
patch := ApplyMethod(reflect.TypeOf(testIDToken), "Claims", func(_ *oidc.IDToken, v interface{}) error {
|
||||
return json.Unmarshal([]byte(fmt.Sprintf(`{"email":"test@test.com", "name":"show name", "sub": "%s"}`, sub)), v)
|
||||
})
|
||||
@@ -78,13 +79,14 @@ var _ = Describe("Test authentication service functions", func() {
|
||||
err = projectService.Init(context.TODO())
|
||||
Expect(err).Should(BeNil())
|
||||
|
||||
_, err = sysService.UpdateSystemInfo(context.TODO(), apisv1.SystemInfoRequest{
|
||||
LoginType: "local",
|
||||
DexUserDefaultProjects: []model.ProjectRef{{
|
||||
Name: "default",
|
||||
Roles: []string{"app-developer"},
|
||||
}},
|
||||
})
|
||||
info, err := sysService.Get(context.TODO())
|
||||
Expect(err).Should(BeNil())
|
||||
info.DexUserDefaultProjects = []model.ProjectRef{{
|
||||
Name: "default",
|
||||
Roles: []string{"app-developer"},
|
||||
}}
|
||||
info.DexUserDefaultPlatformRoles = []string{"admin"}
|
||||
err = ds.Put(context.TODO(), info)
|
||||
Expect(err).Should(BeNil())
|
||||
|
||||
dexHandler := dexHandlerImpl{
|
||||
@@ -96,9 +98,14 @@ var _ = Describe("Test authentication service functions", func() {
|
||||
resp, err := dexHandler.login(context.Background())
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(resp.Email).Should(Equal("test@test.com"))
|
||||
Expect(resp.Name).Should(Equal(sub))
|
||||
Expect(resp.Name).Should(Equal(strings.ToLower(sub)))
|
||||
Expect(resp.Alias).Should(Equal("show name"))
|
||||
|
||||
newUser, err := userService.GetUser(context.TODO(), resp.Name)
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(newUser.DexSub).Should(Equal(sub))
|
||||
Expect(newUser.UserRoles).Should(Equal([]string{"admin"}))
|
||||
|
||||
projects, err := projectService.ListUserProjects(context.TODO(), sub)
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(len(projects)).Should(Equal(1))
|
||||
|
||||
@@ -75,6 +75,7 @@ const (
|
||||
type CloudShellService interface {
|
||||
Prepare(ctx context.Context) (*apisv1.CloudShellPrepareResponse, error)
|
||||
GetCloudShellEndpoint(ctx context.Context) (string, error)
|
||||
Destroy(ctx context.Context) error
|
||||
}
|
||||
|
||||
// GenerateKubeConfig generate the kubeconfig for the cloudshell
|
||||
@@ -157,6 +158,32 @@ func (c *cloudShellServiceImpl) Prepare(ctx context.Context) (*apisv1.CloudShell
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Destroy destroy the cloud shell environment
|
||||
func (c *cloudShellServiceImpl) Destroy(ctx context.Context) error {
|
||||
var userName string
|
||||
if user := ctx.Value(&apisv1.CtxKeyUser); user != nil {
|
||||
if u, ok := user.(string); ok {
|
||||
userName = u
|
||||
}
|
||||
}
|
||||
if userName == "" {
|
||||
return bcode.ErrUnauthorized
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(ctx, time.Second*20)
|
||||
defer cancel()
|
||||
var cloudShell v1alpha1.CloudShell
|
||||
if err := c.KubeClient.Get(ctx, types.NamespacedName{Namespace: kubevelatypes.DefaultKubeVelaNS, Name: makeUserCloudShellName(userName)}, &cloudShell); err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
if meta.IsNoMatchError(err) {
|
||||
return bcode.ErrCloudShellAddonNotEnabled
|
||||
}
|
||||
return err
|
||||
}
|
||||
return c.KubeClient.Delete(ctx, &cloudShell)
|
||||
}
|
||||
|
||||
func (c *cloudShellServiceImpl) GetCloudShellEndpoint(ctx context.Context) (string, error) {
|
||||
var userName string
|
||||
if user := ctx.Value(&apisv1.CtxKeyUser); user != nil {
|
||||
@@ -182,7 +209,7 @@ func (c *cloudShellServiceImpl) GetCloudShellEndpoint(ctx context.Context) (stri
|
||||
return cloudShell.Status.AccessURL, nil
|
||||
}
|
||||
|
||||
// prepareKubeConfig prepare the user's kubeconfig
|
||||
// prepareKubeConfig prepare the user's kube config
|
||||
func (c *cloudShellServiceImpl) prepareKubeConfig(ctx context.Context) error {
|
||||
var userName string
|
||||
if user := ctx.Value(&apisv1.CtxKeyUser); user != nil {
|
||||
@@ -212,10 +239,13 @@ func (c *cloudShellServiceImpl) prepareKubeConfig(ctx context.Context) error {
|
||||
readOnly = checkReadOnly(p.Name, permissions)
|
||||
}
|
||||
if readOnly {
|
||||
// TODO:(@barnettZQG) there needs a method to revoke the privileges
|
||||
if err := c.managePrivilegesForUser(ctx, p.Name, true, userName, false); err != nil {
|
||||
groupName, err := c.managePrivilegesForProjectRead(ctx, p.Name, true)
|
||||
if err != nil {
|
||||
log.Logger.Errorf("failed to privileges the user %s", err.Error())
|
||||
}
|
||||
if groupName != "" {
|
||||
groups = append(groups, groupName)
|
||||
}
|
||||
} else {
|
||||
groups = append(groups, utils.KubeVelaProjectGroupPrefix+p.Name)
|
||||
}
|
||||
@@ -345,8 +375,8 @@ func checkReadOnly(projectName string, permissions []*model.Permission) bool {
|
||||
return !ra.Match(permissions)
|
||||
}
|
||||
|
||||
// managePrivilegesForUser grant or revoke privileges for a user
|
||||
func (c *cloudShellServiceImpl) managePrivilegesForUser(ctx context.Context, projectName string, readOnly bool, userName string, revoke bool) error {
|
||||
// managePrivilegesForProjectRead grant the read privileges for a project
|
||||
func (c *cloudShellServiceImpl) managePrivilegesForProjectRead(ctx context.Context, projectName string, readOnly bool) (string, error) {
|
||||
targets, err := c.TargetService.ListTargets(ctx, 0, 0, projectName)
|
||||
if err != nil {
|
||||
log.Logger.Infof("failed to list the targets by the project name %s :%s", projectName, err.Error())
|
||||
@@ -362,16 +392,12 @@ func (c *cloudShellServiceImpl) managePrivilegesForUser(ctx context.Context, pro
|
||||
for _, e := range envs.Envs {
|
||||
authPDs = append(authPDs, &auth.ApplicationPrivilege{Cluster: kubevelatypes.ClusterLocalName, Namespace: e.Namespace, ReadOnly: readOnly})
|
||||
}
|
||||
|
||||
identity := &auth.Identity{User: userName}
|
||||
groupName := utils.KubeVelaProjectReadGroupPrefix + projectName
|
||||
identity := &auth.Identity{Groups: []string{groupName}}
|
||||
writer := &bytes.Buffer{}
|
||||
f, msg := auth.GrantPrivileges, "GrantPrivileges"
|
||||
if revoke {
|
||||
f, msg = auth.RevokePrivileges, "RevokePrivileges"
|
||||
if err := auth.GrantPrivileges(ctx, c.KubeClient, authPDs, identity, writer, auth.WithReplace); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err := f(ctx, c.KubeClient, authPDs, identity, writer); err != nil {
|
||||
return err
|
||||
}
|
||||
log.Logger.Debugf("%s: %s", msg, writer.String())
|
||||
return nil
|
||||
log.Logger.Debugf("GrantPrivileges: %s", writer.String())
|
||||
return groupName, nil
|
||||
}
|
||||
|
||||
@@ -154,10 +154,13 @@ var _ = Describe("Test cloudshell service function", func() {
|
||||
err = k8sClient.Get(context.Background(), types.NamespacedName{Name: "kubevela:reader:application:binding", Namespace: "default"}, &rb)
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(len(rb.Subjects)).Should(Equal(1))
|
||||
Expect(rb.Subjects[0].Name).Should(Equal("test-viewer"))
|
||||
Expect(rb.Subjects[0].Kind).Should(Equal("User"))
|
||||
Expect(rb.Subjects[0].Name).Should(Equal(utils.KubeVelaProjectReadGroupPrefix + "default"))
|
||||
Expect(rb.Subjects[0].Kind).Should(Equal("Group"))
|
||||
err = k8sClient.Get(context.Background(), types.NamespacedName{Name: "kubevela:reader:binding", Namespace: "default"}, &rb)
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(len(rb.Subjects)).Should(Equal(1))
|
||||
Expect(rb.Subjects[0].Name).Should(Equal(utils.KubeVelaProjectReadGroupPrefix + "default"))
|
||||
Expect(rb.Subjects[0].Kind).Should(Equal("Group"))
|
||||
|
||||
By("test the administrator users")
|
||||
|
||||
@@ -178,7 +181,7 @@ var _ = Describe("Test cloudshell service function", func() {
|
||||
})
|
||||
|
||||
It("test prepare", func() {
|
||||
By("With not CRD")
|
||||
By("Test with not CRD")
|
||||
_, err = userService.CreateUser(context.TODO(), apisv1.CreateUserRequest{Name: "test", Password: "test"})
|
||||
Expect(err).Should(BeNil())
|
||||
ctx := context.WithValue(context.TODO(), &apisv1.CtxKeyUser, "test")
|
||||
@@ -186,6 +189,7 @@ var _ = Describe("Test cloudshell service function", func() {
|
||||
Expect(err).ShouldNot(BeNil())
|
||||
Expect(err.Error()).Should(Equal(bcode.ErrCloudShellAddonNotEnabled.Error()))
|
||||
|
||||
By("Test with CRD")
|
||||
cloudshellCRDBytes, err := ioutil.ReadFile("./testdata/cloudshell-crd.yaml")
|
||||
Expect(err).Should(BeNil())
|
||||
|
||||
@@ -210,8 +214,12 @@ var _ = Describe("Test cloudshell service function", func() {
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(re.Status).Should(Equal(StatusCompleted))
|
||||
|
||||
By("Test get the cloud shell endpoint")
|
||||
endpoint, err := cloudShellService.GetCloudShellEndpoint(ctx)
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(endpoint).Should(Equal("10.10.1.1:8765"))
|
||||
|
||||
By("Test destroy cloud shell")
|
||||
Expect(cloudShellService.Destroy(ctx)).Should(BeNil())
|
||||
})
|
||||
})
|
||||
|
||||
@@ -89,8 +89,13 @@ func (u *configServiceImpl) ListConfigTypes(ctx context.Context, query string) (
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, defsLegacy.Items...)
|
||||
|
||||
// filter repeated config,due to new labels that exist at the same time
|
||||
for _, legacy := range defsLegacy.Items {
|
||||
if legacy.Labels[configCatalog] == types.VelaCoreConfig {
|
||||
continue
|
||||
}
|
||||
items = append(items, legacy)
|
||||
}
|
||||
var tfDefs []v1beta1.ComponentDefinition
|
||||
var configTypes []*apis.ConfigType
|
||||
|
||||
|
||||
@@ -484,7 +484,7 @@ func (p *rbacServiceImpl) GetUserPermissions(ctx context.Context, user *model.Us
|
||||
perms = append(perms, &model.Permission{
|
||||
Name: "cloudshell",
|
||||
Resources: []string{"cloudshell"},
|
||||
Actions: []string{"create"},
|
||||
Actions: []string{"*"},
|
||||
Effect: "Allow",
|
||||
})
|
||||
return perms, nil
|
||||
|
||||
@@ -113,8 +113,9 @@ func (u systemInfoServiceImpl) UpdateSystemInfo(ctx context.Context, sysInfo v1.
|
||||
CreateTime: info.CreateTime,
|
||||
UpdateTime: time.Now(),
|
||||
},
|
||||
StatisticInfo: info.StatisticInfo,
|
||||
DexUserDefaultProjects: sysInfo.DexUserDefaultProjects,
|
||||
StatisticInfo: info.StatisticInfo,
|
||||
DexUserDefaultProjects: sysInfo.DexUserDefaultProjects,
|
||||
DexUserDefaultPlatformRoles: info.DexUserDefaultPlatformRoles,
|
||||
}
|
||||
|
||||
if sysInfo.LoginType == model.LoginTypeDex {
|
||||
@@ -167,10 +168,11 @@ func (u systemInfoServiceImpl) Init(ctx context.Context) error {
|
||||
|
||||
func convertInfoToBase(info *model.SystemInfo) v1.SystemInfo {
|
||||
return v1.SystemInfo{
|
||||
PlatformID: info.InstallID,
|
||||
EnableCollection: info.EnableCollection,
|
||||
LoginType: info.LoginType,
|
||||
InstallTime: info.CreateTime,
|
||||
DexUserDefaultProjects: info.DexUserDefaultProjects,
|
||||
PlatformID: info.InstallID,
|
||||
EnableCollection: info.EnableCollection,
|
||||
LoginType: info.LoginType,
|
||||
InstallTime: info.CreateTime,
|
||||
DexUserDefaultProjects: info.DexUserDefaultProjects,
|
||||
DexUserDefaultPlatformRoles: info.DexUserDefaultPlatformRoles,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,6 +104,7 @@ func authCheckFilter(req *restful.Request, res *restful.Response, chain *restful
|
||||
}
|
||||
if tokenValue == "" {
|
||||
bcode.ReturnError(req, res, bcode.ErrNotAuthorized)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,6 +61,14 @@ func (c *CloudShellAPIInterface) GetWebServiceRoute() *restful.WebService {
|
||||
Returns(400, "Bad Request", bcode.Bcode{}).
|
||||
Writes(apis.CloudShellPrepareResponse{}).Do(returns200, returns500))
|
||||
|
||||
ws.Route(ws.DELETE("/").To(c.destroyCloudShell).
|
||||
Doc("destroy the user's cloud shell environment").
|
||||
Metadata(restfulspec.KeyOpenAPITags, tags).
|
||||
Filter(c.RbacService.CheckPerm("cloudshell", "delete")).
|
||||
Returns(200, "OK", apis.EmptyResponse{}).
|
||||
Returns(400, "Bad Request", bcode.Bcode{}).
|
||||
Writes(apis.EmptyResponse{}).Do(returns200, returns500))
|
||||
|
||||
ws.Filter(authCheckFilter)
|
||||
return ws
|
||||
}
|
||||
@@ -82,6 +90,19 @@ func (c *CloudShellAPIInterface) prepareCloudShell(req *restful.Request, res *re
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CloudShellAPIInterface) destroyCloudShell(req *restful.Request, res *restful.Response) {
|
||||
err := c.CloudShellService.Destroy(req.Request.Context())
|
||||
// Write back response data
|
||||
if err != nil {
|
||||
bcode.ReturnError(req, res, err)
|
||||
return
|
||||
}
|
||||
if err := res.WriteEntity(apis.EmptyResponse{}); err != nil {
|
||||
bcode.ReturnError(req, res, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// CloudShellView provide the view handler
|
||||
type CloudShellView struct {
|
||||
RbacService service.RBACService `inject:""`
|
||||
|
||||
@@ -1194,11 +1194,12 @@ type SystemInfoResponse struct {
|
||||
|
||||
// SystemInfo system info
|
||||
type SystemInfo struct {
|
||||
PlatformID string `json:"platformID"`
|
||||
EnableCollection bool `json:"enableCollection"`
|
||||
LoginType string `json:"loginType" validate:"oneof=dex local"`
|
||||
InstallTime time.Time `json:"installTime,omitempty"`
|
||||
DexUserDefaultProjects []model.ProjectRef `json:"dexUserDefaultProjects,omitempty"`
|
||||
PlatformID string `json:"platformID"`
|
||||
EnableCollection bool `json:"enableCollection"`
|
||||
LoginType string `json:"loginType" validate:"oneof=dex local"`
|
||||
InstallTime time.Time `json:"installTime,omitempty"`
|
||||
DexUserDefaultProjects []model.ProjectRef `json:"dexUserDefaultProjects,omitempty"`
|
||||
DexUserDefaultPlatformRoles []string `json:"dexUserDefaultPlatformRoles,omitempty"`
|
||||
}
|
||||
|
||||
// StatisticInfo generated by cronJob running in backend
|
||||
|
||||
@@ -32,6 +32,9 @@ import (
|
||||
// KubeVelaProjectGroupPrefix the prefix kubevela project
|
||||
const KubeVelaProjectGroupPrefix = "kubevela:project:"
|
||||
|
||||
// KubeVelaProjectReadGroupPrefix the prefix kubevela project group that only has the read permissions
|
||||
const KubeVelaProjectReadGroupPrefix = "kubevela:project-ro:"
|
||||
|
||||
// KubeVelaAdminGroupPrefix the prefix kubevela admin
|
||||
const KubeVelaAdminGroupPrefix = "kubevela:admin:"
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ func (wl *Workload) EvalStatus(ctx process.Context, cli client.Client, accessor
|
||||
// EvalHealth eval workload health check
|
||||
func (wl *Workload) EvalHealth(ctx process.Context, client client.Client, accessor util.NamespaceAccessor) (bool, error) {
|
||||
// if health of template is not set or standard workload is managed by trait always return true
|
||||
if wl.FullTemplate.Health == "" || wl.SkipApplyWorkload {
|
||||
if wl.SkipApplyWorkload {
|
||||
return true, nil
|
||||
}
|
||||
return wl.engine.HealthCheck(ctx, client, accessor, wl.FullTemplate.Health)
|
||||
@@ -152,9 +152,6 @@ func (trait *Trait) EvalStatus(ctx process.Context, cli client.Client, accessor
|
||||
|
||||
// EvalHealth eval trait health check
|
||||
func (trait *Trait) EvalHealth(ctx process.Context, client client.Client, accessor util.NamespaceAccessor) (bool, error) {
|
||||
if trait.FullTemplate.Health == "" {
|
||||
return true, nil
|
||||
}
|
||||
return trait.engine.HealthCheck(ctx, client, accessor, trait.HealthCheckPolicy)
|
||||
}
|
||||
|
||||
|
||||
@@ -403,8 +403,21 @@ func removeSubjects(src []rbacv1.Subject, toRemove []rbacv1.Subject) []rbacv1.Su
|
||||
return subs
|
||||
}
|
||||
|
||||
type opts struct {
|
||||
replace bool
|
||||
}
|
||||
|
||||
// WithReplace means to replace all subjects, this is only useful in Grant Privileges
|
||||
func WithReplace(o *opts) {
|
||||
o.replace = true
|
||||
}
|
||||
|
||||
// GrantPrivileges grant privileges to identity
|
||||
func GrantPrivileges(ctx context.Context, cli client.Client, privileges []PrivilegeDescription, identity *Identity, writer io.Writer) error {
|
||||
func GrantPrivileges(ctx context.Context, cli client.Client, privileges []PrivilegeDescription, identity *Identity, writer io.Writer, optionFuncs ...func(*opts)) error {
|
||||
var options = &opts{}
|
||||
for _, fc := range optionFuncs {
|
||||
fc(options)
|
||||
}
|
||||
subs := identity.Subjects()
|
||||
if len(subs) == 0 {
|
||||
return fmt.Errorf("failed to find RBAC subjects in identity")
|
||||
@@ -434,12 +447,20 @@ func GrantPrivileges(ctx context.Context, cli client.Client, privileges []Privil
|
||||
case *rbacv1.RoleBinding:
|
||||
obj := &rbacv1.RoleBinding{}
|
||||
if err := cli.Get(_ctx, client.ObjectKeyFromObject(bindingObj), obj); err == nil {
|
||||
bindingObj.Subjects = mergeSubjects(bindingObj.Subjects, obj.Subjects)
|
||||
if options.replace {
|
||||
bindingObj.Subjects = obj.Subjects
|
||||
} else {
|
||||
bindingObj.Subjects = mergeSubjects(bindingObj.Subjects, obj.Subjects)
|
||||
}
|
||||
}
|
||||
case *rbacv1.ClusterRoleBinding:
|
||||
obj := &rbacv1.ClusterRoleBinding{}
|
||||
if err := cli.Get(_ctx, client.ObjectKeyFromObject(bindingObj), obj); err == nil {
|
||||
bindingObj.Subjects = mergeSubjects(bindingObj.Subjects, obj.Subjects)
|
||||
if options.replace {
|
||||
bindingObj.Subjects = obj.Subjects
|
||||
} else {
|
||||
bindingObj.Subjects = mergeSubjects(bindingObj.Subjects, obj.Subjects)
|
||||
}
|
||||
}
|
||||
}
|
||||
res, err := utils.CreateOrUpdate(_ctx, cli, binding)
|
||||
@@ -454,7 +475,11 @@ func GrantPrivileges(ctx context.Context, cli client.Client, privileges []Privil
|
||||
// RevokePrivileges revoke privileges (notice that the revoking process only deletes bond subject in the
|
||||
// RoleBinding/ClusterRoleBinding, it does not ensure the identity's other related privileges are removed to
|
||||
// prevent identity from accessing)
|
||||
func RevokePrivileges(ctx context.Context, cli client.Client, privileges []PrivilegeDescription, identity *Identity, writer io.Writer) error {
|
||||
func RevokePrivileges(ctx context.Context, cli client.Client, privileges []PrivilegeDescription, identity *Identity, writer io.Writer, optionFuncs ...func(*opts)) error {
|
||||
var options = &opts{}
|
||||
for _, fc := range optionFuncs {
|
||||
fc(options)
|
||||
}
|
||||
subs := identity.Subjects()
|
||||
if len(subs) == 0 {
|
||||
return fmt.Errorf("failed to find RBAC subjects in identity")
|
||||
|
||||
@@ -128,9 +128,10 @@ func (c *HTTPCmd) Run(meta *registry.Meta) (res interface{}, err error) {
|
||||
b, err := io.ReadAll(resp.Body)
|
||||
// parse response body and headers
|
||||
return map[string]interface{}{
|
||||
"body": string(b),
|
||||
"header": resp.Header,
|
||||
"trailer": resp.Trailer,
|
||||
"body": string(b),
|
||||
"header": resp.Header,
|
||||
"trailer": resp.Trailer,
|
||||
"statusCode": resp.StatusCode,
|
||||
}, err
|
||||
}
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
|
||||
if annotations := app.GetAnnotations(); annotations == nil || annotations[oam.AnnotationKubeVelaVersion] == "" {
|
||||
metav1.SetMetaDataAnnotation(&app.ObjectMeta, oam.AnnotationKubeVelaVersion, version.VelaVersion)
|
||||
}
|
||||
logCtx.AddTag("publish_version", app.GetAnnotations()[oam.AnnotationKubeVelaVersion])
|
||||
logCtx.AddTag("publish_version", app.GetAnnotations()[oam.AnnotationPublishVersion])
|
||||
|
||||
appParser := appfile.NewApplicationParser(r.Client, r.dm, r.pd)
|
||||
handler, err := NewAppHandler(logCtx, r, app, appParser)
|
||||
|
||||
@@ -186,7 +186,7 @@ func (wd *workloadDef) getTemplateContext(ctx process.Context, cli client.Reader
|
||||
return nil, err
|
||||
}
|
||||
// AuxiliaryWorkload will have a unique label("trait.oam.dev/resource"="name of outputs") in per component/app level
|
||||
object, err := getResourceFromObj(ctx.GetCtx(), traitRef, cli, accessor.For(componentWorkload), util.MergeMapOverrideWithDst(map[string]string{
|
||||
object, err := getResourceFromObj(ctx.GetCtx(), traitRef, cli, accessor.For(traitRef), util.MergeMapOverrideWithDst(map[string]string{
|
||||
oam.TraitTypeLabel: AuxiliaryWorkload,
|
||||
}, commonLabels), assist.Name)
|
||||
if err != nil {
|
||||
@@ -202,9 +202,6 @@ func (wd *workloadDef) getTemplateContext(ctx process.Context, cli client.Reader
|
||||
|
||||
// HealthCheck address health check for workload
|
||||
func (wd *workloadDef) HealthCheck(ctx process.Context, cli client.Client, accessor util.NamespaceAccessor, healthPolicyTemplate string) (bool, error) {
|
||||
if healthPolicyTemplate == "" {
|
||||
return true, nil
|
||||
}
|
||||
templateContext, err := wd.getTemplateContext(ctx, cli, accessor)
|
||||
if err != nil {
|
||||
return false, errors.WithMessage(err, "get template context")
|
||||
@@ -213,6 +210,9 @@ func (wd *workloadDef) HealthCheck(ctx process.Context, cli client.Client, acces
|
||||
}
|
||||
|
||||
func checkHealth(templateContext map[string]interface{}, healthPolicyTemplate string) (bool, error) {
|
||||
if healthPolicyTemplate == "" {
|
||||
return true, nil
|
||||
}
|
||||
bt, err := json.Marshal(templateContext)
|
||||
if err != nil {
|
||||
return false, errors.WithMessage(err, "json marshal template context")
|
||||
@@ -233,9 +233,6 @@ func checkHealth(templateContext map[string]interface{}, healthPolicyTemplate st
|
||||
|
||||
// Status get workload status by customStatusTemplate
|
||||
func (wd *workloadDef) Status(ctx process.Context, cli client.Client, accessor util.NamespaceAccessor, customStatusTemplate string, parameter interface{}) (string, error) {
|
||||
if customStatusTemplate == "" {
|
||||
return "", nil
|
||||
}
|
||||
templateContext, err := wd.getTemplateContext(ctx, cli, accessor)
|
||||
if err != nil {
|
||||
return "", errors.WithMessage(err, "get template context")
|
||||
@@ -244,6 +241,9 @@ func (wd *workloadDef) Status(ctx process.Context, cli client.Client, accessor u
|
||||
}
|
||||
|
||||
func getStatusMessage(pd *packages.PackageDiscover, templateContext map[string]interface{}, customStatusTemplate string, parameter interface{}) (string, error) {
|
||||
if customStatusTemplate == "" {
|
||||
return "", nil
|
||||
}
|
||||
bi := build.NewContext().NewInstance("", nil)
|
||||
var ctxBuff string
|
||||
var paramBuff = "parameter: {}\n"
|
||||
@@ -455,9 +455,6 @@ func (td *traitDef) getTemplateContext(ctx process.Context, cli client.Reader, a
|
||||
|
||||
// Status get trait status by customStatusTemplate
|
||||
func (td *traitDef) Status(ctx process.Context, cli client.Client, accessor util.NamespaceAccessor, customStatusTemplate string, parameter interface{}) (string, error) {
|
||||
if customStatusTemplate == "" {
|
||||
return "", nil
|
||||
}
|
||||
templateContext, err := td.getTemplateContext(ctx, cli, accessor)
|
||||
if err != nil {
|
||||
return "", errors.WithMessage(err, "get template context")
|
||||
@@ -467,9 +464,6 @@ func (td *traitDef) Status(ctx process.Context, cli client.Client, accessor util
|
||||
|
||||
// HealthCheck address health check for trait
|
||||
func (td *traitDef) HealthCheck(ctx process.Context, cli client.Client, accessor util.NamespaceAccessor, healthPolicyTemplate string) (bool, error) {
|
||||
if healthPolicyTemplate == "" {
|
||||
return true, nil
|
||||
}
|
||||
templateContext, err := td.getTemplateContext(ctx, cli, accessor)
|
||||
if err != nil {
|
||||
return false, errors.WithMessage(err, "get template context")
|
||||
|
||||
@@ -115,6 +115,9 @@ func listMergeProcess(field *ast.Field, key string, baseList, patchList *ast.Lis
|
||||
kmaps[fmt.Sprintf(key, blit.Value)] = patchList.Elts[i]
|
||||
}
|
||||
if !foundPatch {
|
||||
if len(patchList.Elts) == 0 {
|
||||
continue
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user