mirror of
https://github.com/kubevela/kubevela.git
synced 2026-08-18 20:17:04 +00:00
Chore: remove useless envbinding env (#6122)
* Chore: remove useless envbinding env Signed-off-by: Somefive <yd219913@alibaba-inc.com> * fix go proxy Signed-off-by: Somefive <yd219913@alibaba-inc.com> --------- Signed-off-by: Somefive <yd219913@alibaba-inc.com>
This commit is contained in:
+1
-1
@@ -9,7 +9,7 @@ COPY go.sum go.sum
|
||||
|
||||
# It's a proxy for CN developer, please unblock it if you have network issue
|
||||
ARG GOPROXY
|
||||
ENV GOPROXY=${GOPROXY:-https://goproxy.cn}
|
||||
ENV GOPROXY=${GOPROXY:-https://proxy.golang.org}
|
||||
|
||||
# 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
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ ARG BASE_IMAGE
|
||||
# Build the cli binary
|
||||
FROM --platform=${BUILDPLATFORM:-linux/amd64} golang:1.19-alpine@sha256:2381c1e5f8350a901597d633b2e517775eeac7a6682be39225a93b22cfd0f8bb as builder
|
||||
ARG GOPROXY
|
||||
ENV GOPROXY=${GOPROXY:-https://goproxy.cn}
|
||||
ENV GOPROXY=${GOPROXY:-https://proxy.golang.org}
|
||||
WORKDIR /workspace
|
||||
# Copy the Go Modules manifests
|
||||
COPY go.mod go.mod
|
||||
|
||||
@@ -334,12 +334,11 @@ const (
|
||||
type OAMObjectReference struct {
|
||||
Component string `json:"component,omitempty"`
|
||||
Trait string `json:"trait,omitempty"`
|
||||
Env string `json:"env,omitempty"`
|
||||
}
|
||||
|
||||
// Equal check if two references are equal
|
||||
func (in OAMObjectReference) Equal(r OAMObjectReference) bool {
|
||||
return in.Component == r.Component && in.Trait == r.Trait && in.Env == r.Env
|
||||
return in.Component == r.Component && in.Trait == r.Trait
|
||||
}
|
||||
|
||||
// AddLabelsToObject add labels to object if properties are not empty
|
||||
@@ -354,9 +353,6 @@ func (in OAMObjectReference) AddLabelsToObject(obj client.Object) {
|
||||
if in.Trait != "" {
|
||||
labels[oam.TraitTypeLabel] = in.Trait
|
||||
}
|
||||
if in.Env != "" {
|
||||
labels[oam.LabelAppEnv] = in.Env
|
||||
}
|
||||
obj.SetLabels(labels)
|
||||
}
|
||||
|
||||
@@ -366,7 +362,6 @@ func NewOAMObjectReferenceFromObject(obj client.Object) OAMObjectReference {
|
||||
return OAMObjectReference{
|
||||
Component: labels[oam.LabelAppComponent],
|
||||
Trait: labels[oam.TraitTypeLabel],
|
||||
Env: labels[oam.LabelAppEnv],
|
||||
}
|
||||
}
|
||||
return OAMObjectReference{}
|
||||
|
||||
@@ -29,13 +29,12 @@ func TestOAMObjectReference(t *testing.T) {
|
||||
o1 := OAMObjectReference{
|
||||
Component: "component",
|
||||
Trait: "trait",
|
||||
Env: "env",
|
||||
}
|
||||
obj := &unstructured.Unstructured{}
|
||||
o2 := NewOAMObjectReferenceFromObject(obj)
|
||||
r.False(o2.Equal(o1))
|
||||
o1.AddLabelsToObject(obj)
|
||||
r.Equal(3, len(obj.GetLabels()))
|
||||
r.Equal(2, len(obj.GetLabels()))
|
||||
o3 := NewOAMObjectReferenceFromObject(obj)
|
||||
r.True(o1.Equal(o3))
|
||||
o3.Component = "comp"
|
||||
|
||||
@@ -185,7 +185,7 @@ func (in *ManagedResource) ResourceKey() string {
|
||||
|
||||
// ComponentKey computes the key for the component which managed resource belongs to
|
||||
func (in *ManagedResource) ComponentKey() string {
|
||||
return strings.Join([]string{in.Env, in.Component}, "/")
|
||||
return strings.Join([]string{in.Cluster, in.Component}, "/")
|
||||
}
|
||||
|
||||
// UnmarshalTo unmarshal ManagedResource into target object
|
||||
|
||||
@@ -124,14 +124,13 @@ func TestManagedResourceKeys(t *testing.T) {
|
||||
},
|
||||
},
|
||||
OAMObjectReference: common.OAMObjectReference{
|
||||
Env: "env",
|
||||
Component: "component",
|
||||
Trait: "trait",
|
||||
},
|
||||
}
|
||||
r.Equal("namespace/name", input.NamespacedName().String())
|
||||
r.Equal("apps/Deployment/cluster/namespace/name", input.ResourceKey())
|
||||
r.Equal("env/component", input.ComponentKey())
|
||||
r.Equal("cluster/component", input.ComponentKey())
|
||||
r.Equal("Deployment name (Cluster: cluster, Namespace: namespace)", input.DisplayName())
|
||||
var deploy1, deploy2 appsv1.Deployment
|
||||
deploy1.Spec.Replicas = pointer.Int32(5)
|
||||
|
||||
@@ -82,8 +82,6 @@ spec:
|
||||
deleted:
|
||||
description: Deleted marks the resource to be deleted
|
||||
type: boolean
|
||||
env:
|
||||
type: string
|
||||
fieldPath:
|
||||
description: 'If referring to a piece of an object instead of
|
||||
an entire object, this string should contain a valid JSON/Go
|
||||
|
||||
@@ -22,7 +22,6 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/crossplane/crossplane-runtime/pkg/meta"
|
||||
"github.com/pkg/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
@@ -313,19 +312,19 @@ func checkDependsOnValidComponent(dependsOnComponentNames, allComponentNames []s
|
||||
}
|
||||
|
||||
func (h *AppHandler) renderComponentFunc(appParser *appfile.Parser, appRev *v1beta1.ApplicationRevision, af *appfile.Appfile) oamProvider.ComponentRender {
|
||||
return func(baseCtx context.Context, comp common.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string, env string) (*unstructured.Unstructured, []*unstructured.Unstructured, error) {
|
||||
return func(baseCtx context.Context, comp common.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string) (*unstructured.Unstructured, []*unstructured.Unstructured, error) {
|
||||
ctx := multicluster.ContextWithClusterName(baseCtx, clusterName)
|
||||
|
||||
_, manifest, err := h.prepareWorkloadAndManifests(ctx, appParser, comp, appRev, patcher, af)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return renderComponentsAndTraits(h.r.Client, manifest, appRev, clusterName, overrideNamespace, env)
|
||||
return renderComponentsAndTraits(h.r.Client, manifest, appRev, clusterName, overrideNamespace)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *AppHandler) checkComponentHealth(appParser *appfile.Parser, appRev *v1beta1.ApplicationRevision, af *appfile.Appfile) oamProvider.ComponentHealthCheck {
|
||||
return func(baseCtx context.Context, comp common.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string, env string) (bool, *unstructured.Unstructured, []*unstructured.Unstructured, error) {
|
||||
return func(baseCtx context.Context, comp common.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string) (bool, *unstructured.Unstructured, []*unstructured.Unstructured, error) {
|
||||
ctx := multicluster.ContextWithClusterName(baseCtx, clusterName)
|
||||
ctx = contextWithComponentNamespace(ctx, overrideNamespace)
|
||||
ctx = contextWithReplicaKey(ctx, comp.ReplicaKey)
|
||||
@@ -336,7 +335,7 @@ func (h *AppHandler) checkComponentHealth(appParser *appfile.Parser, appRev *v1b
|
||||
}
|
||||
wl.Ctx.SetCtx(auth.ContextWithUserInfo(ctx, h.app))
|
||||
|
||||
readyWorkload, readyTraits, err := renderComponentsAndTraits(h.r.Client, manifest, appRev, clusterName, overrideNamespace, env)
|
||||
readyWorkload, readyTraits, err := renderComponentsAndTraits(h.r.Client, manifest, appRev, clusterName, overrideNamespace)
|
||||
if err != nil {
|
||||
return false, nil, nil, err
|
||||
}
|
||||
@@ -360,7 +359,7 @@ func (h *AppHandler) checkComponentHealth(appParser *appfile.Parser, appRev *v1b
|
||||
}
|
||||
|
||||
func (h *AppHandler) applyComponentFunc(appParser *appfile.Parser, appRev *v1beta1.ApplicationRevision, af *appfile.Appfile) oamProvider.ComponentApply {
|
||||
return func(baseCtx context.Context, comp common.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string, env string) (*unstructured.Unstructured, []*unstructured.Unstructured, bool, error) {
|
||||
return func(baseCtx context.Context, comp common.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string) (*unstructured.Unstructured, []*unstructured.Unstructured, bool, error) {
|
||||
t := time.Now()
|
||||
defer func() { metrics.ApplyComponentTimeHistogram.WithLabelValues("-").Observe(time.Since(t).Seconds()) }()
|
||||
|
||||
@@ -379,7 +378,7 @@ func (h *AppHandler) applyComponentFunc(appParser *appfile.Parser, appRev *v1bet
|
||||
}
|
||||
wl.Ctx.SetCtx(auth.ContextWithUserInfo(ctx, h.app))
|
||||
|
||||
readyWorkload, readyTraits, err := renderComponentsAndTraits(h.r.Client, manifest, appRev, clusterName, overrideNamespace, env)
|
||||
readyWorkload, readyTraits, err := renderComponentsAndTraits(h.r.Client, manifest, appRev, clusterName, overrideNamespace)
|
||||
if err != nil {
|
||||
return nil, nil, false, err
|
||||
}
|
||||
@@ -470,7 +469,7 @@ func (h *AppHandler) prepareWorkloadAndManifests(ctx context.Context,
|
||||
return wl, manifest, nil
|
||||
}
|
||||
|
||||
func renderComponentsAndTraits(client client.Client, manifest *types.ComponentManifest, appRev *v1beta1.ApplicationRevision, clusterName string, overrideNamespace string, env string) (*unstructured.Unstructured, []*unstructured.Unstructured, error) {
|
||||
func renderComponentsAndTraits(client client.Client, manifest *types.ComponentManifest, appRev *v1beta1.ApplicationRevision, clusterName string, overrideNamespace string) (*unstructured.Unstructured, []*unstructured.Unstructured, error) {
|
||||
readyWorkload, readyTraits, err := assemble.PrepareBeforeApply(manifest, appRev, []assemble.WorkloadOption{assemble.DiscoveryHelmBasedWorkload(context.TODO(), client)})
|
||||
if err != nil {
|
||||
return nil, nil, errors.WithMessage(err, "assemble resources before apply fail")
|
||||
@@ -488,12 +487,6 @@ func renderComponentsAndTraits(client client.Client, manifest *types.ComponentMa
|
||||
}
|
||||
}
|
||||
readyTraits = overrideTraits(appRev, readyTraits)
|
||||
if env != "" {
|
||||
meta.AddLabels(readyWorkload, map[string]string{oam.LabelAppEnv: env})
|
||||
for _, readyTrait := range readyTraits {
|
||||
meta.AddLabels(readyTrait, map[string]string{oam.LabelAppEnv: env})
|
||||
}
|
||||
}
|
||||
return readyWorkload, readyTraits, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -80,9 +80,6 @@ const (
|
||||
// LabelAddonRegistry indicates the name of addon-registry
|
||||
LabelAddonRegistry = "addons.oam.dev/registry"
|
||||
|
||||
// LabelAppEnv records the name of Env
|
||||
LabelAppEnv = "envbinding.oam.dev/env"
|
||||
|
||||
// LabelNamespaceOfEnvName records the env name of namespace
|
||||
LabelNamespaceOfEnvName = "namespace.oam.dev/env"
|
||||
|
||||
|
||||
@@ -345,7 +345,7 @@ HealthCheck:
|
||||
break HealthCheck
|
||||
}
|
||||
checkResults := slices.ParMap[*applyTask, *applyTaskResult](checkTasks, func(task *applyTask) *applyTaskResult {
|
||||
healthy, output, outputs, err := healthCheck(ctx, task.component, nil, task.placement.Cluster, task.placement.Namespace, "")
|
||||
healthy, output, outputs, err := healthCheck(ctx, task.component, nil, task.placement.Cluster, task.placement.Namespace)
|
||||
task.healthy = pointer.Bool(healthy)
|
||||
if healthy {
|
||||
err = task.generateOutput(output, outputs, cache, makeValue)
|
||||
@@ -381,7 +381,7 @@ HealthCheck:
|
||||
if err != nil {
|
||||
return &applyTaskResult{healthy: false, err: err, task: task}
|
||||
}
|
||||
_, _, healthy, err := apply(ctx, task.component, nil, task.placement.Cluster, task.placement.Namespace, "")
|
||||
_, _, healthy, err := apply(ctx, task.component, nil, task.placement.Cluster, task.placement.Namespace)
|
||||
if err != nil {
|
||||
return &applyTaskResult{healthy: healthy, err: err, task: task}
|
||||
}
|
||||
|
||||
@@ -114,12 +114,12 @@ func TestApplyComponentsDepends(t *testing.T) {
|
||||
}
|
||||
|
||||
applyMap := &sync.Map{}
|
||||
apply := func(_ context.Context, comp apicommon.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string, env string) (*unstructured.Unstructured, []*unstructured.Unstructured, bool, error) {
|
||||
apply := func(_ context.Context, comp apicommon.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string) (*unstructured.Unstructured, []*unstructured.Unstructured, bool, error) {
|
||||
time.Sleep(time.Duration(rand.Intn(200)+25) * time.Millisecond)
|
||||
applyMap.Store(fmt.Sprintf("%s/%s", clusterName, comp.Name), true)
|
||||
return nil, nil, true, nil
|
||||
}
|
||||
healthCheck := func(_ context.Context, comp apicommon.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string, env string) (bool, *unstructured.Unstructured, []*unstructured.Unstructured, error) {
|
||||
healthCheck := func(_ context.Context, comp apicommon.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string) (bool, *unstructured.Unstructured, []*unstructured.Unstructured, error) {
|
||||
_, found := applyMap.Load(fmt.Sprintf("%s/%s", clusterName, comp.Name))
|
||||
return found, nil, nil, nil
|
||||
}
|
||||
@@ -158,12 +158,12 @@ func TestApplyComponentsIO(t *testing.T) {
|
||||
applyMap = new(sync.Map)
|
||||
ctx = context.Background()
|
||||
)
|
||||
apply := func(_ context.Context, comp apicommon.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string, env string) (*unstructured.Unstructured, []*unstructured.Unstructured, bool, error) {
|
||||
apply := func(_ context.Context, comp apicommon.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string) (*unstructured.Unstructured, []*unstructured.Unstructured, bool, error) {
|
||||
time.Sleep(time.Duration(rand.Intn(200)+25) * time.Millisecond)
|
||||
applyMap.Store(fmt.Sprintf("%s/%s", clusterName, comp.Name), true)
|
||||
return nil, nil, true, nil
|
||||
}
|
||||
healthCheck := func(_ context.Context, comp apicommon.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string, env string) (bool, *unstructured.Unstructured, []*unstructured.Unstructured, error) {
|
||||
healthCheck := func(_ context.Context, comp apicommon.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string) (bool, *unstructured.Unstructured, []*unstructured.Unstructured, error) {
|
||||
_, found := applyMap.Load(fmt.Sprintf("%s/%s", clusterName, comp.Name))
|
||||
return found, &unstructured.Unstructured{Object: map[string]interface{}{
|
||||
"spec": map[string]interface{}{
|
||||
@@ -293,7 +293,7 @@ func TestApplyComponentsIO(t *testing.T) {
|
||||
output *unstructured.Unstructured
|
||||
outputs []*unstructured.Unstructured
|
||||
}
|
||||
apply := func(_ context.Context, comp apicommon.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string, env string) (*unstructured.Unstructured, []*unstructured.Unstructured, bool, error) {
|
||||
apply := func(_ context.Context, comp apicommon.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string) (*unstructured.Unstructured, []*unstructured.Unstructured, bool, error) {
|
||||
time.Sleep(time.Duration(rand.Intn(200)+25) * time.Millisecond)
|
||||
key := storeKey(clusterName, comp)
|
||||
result := applyResult{
|
||||
@@ -320,7 +320,7 @@ func TestApplyComponentsIO(t *testing.T) {
|
||||
applyMap.Store(storeKey(clusterName, comp), result)
|
||||
return nil, nil, true, nil
|
||||
}
|
||||
healthCheck := func(_ context.Context, comp apicommon.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string, env string) (bool, *unstructured.Unstructured, []*unstructured.Unstructured, error) {
|
||||
healthCheck := func(_ context.Context, comp apicommon.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string) (bool, *unstructured.Unstructured, []*unstructured.Unstructured, error) {
|
||||
key := storeKey(clusterName, comp)
|
||||
r, found := applyMap.Load(key)
|
||||
result, _ := r.(applyResult)
|
||||
|
||||
@@ -44,13 +44,13 @@ const (
|
||||
)
|
||||
|
||||
// ComponentApply apply oam component.
|
||||
type ComponentApply func(ctx context.Context, comp common.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string, env string) (*unstructured.Unstructured, []*unstructured.Unstructured, bool, error)
|
||||
type ComponentApply func(ctx context.Context, comp common.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string) (*unstructured.Unstructured, []*unstructured.Unstructured, bool, error)
|
||||
|
||||
// ComponentRender render oam component.
|
||||
type ComponentRender func(ctx context.Context, comp common.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string, env string) (*unstructured.Unstructured, []*unstructured.Unstructured, error)
|
||||
type ComponentRender func(ctx context.Context, comp common.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string) (*unstructured.Unstructured, []*unstructured.Unstructured, error)
|
||||
|
||||
// ComponentHealthCheck health check oam component.
|
||||
type ComponentHealthCheck func(ctx context.Context, comp common.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string, env string) (bool, *unstructured.Unstructured, []*unstructured.Unstructured, error)
|
||||
type ComponentHealthCheck func(ctx context.Context, comp common.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string) (bool, *unstructured.Unstructured, []*unstructured.Unstructured, error)
|
||||
|
||||
// WorkloadRenderer renderer to render application component into workload
|
||||
type WorkloadRenderer func(ctx context.Context, comp common.ApplicationComponent) (*appfile.Workload, error)
|
||||
@@ -65,11 +65,11 @@ type provider struct {
|
||||
|
||||
// RenderComponent render component
|
||||
func (p *provider) RenderComponent(ctx monitorContext.Context, wfCtx wfContext.Context, v *value.Value, act wfTypes.Action) error {
|
||||
comp, patcher, clusterName, overrideNamespace, env, err := lookUpCompInfo(v)
|
||||
comp, patcher, clusterName, overrideNamespace, err := lookUpCompInfo(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
workload, traits, err := p.render(ctx, *comp, patcher, clusterName, overrideNamespace, env)
|
||||
workload, traits, err := p.render(ctx, *comp, patcher, clusterName, overrideNamespace)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -94,11 +94,11 @@ func (p *provider) RenderComponent(ctx monitorContext.Context, wfCtx wfContext.C
|
||||
|
||||
// ApplyComponent apply component.
|
||||
func (p *provider) ApplyComponent(ctx monitorContext.Context, wfCtx wfContext.Context, v *value.Value, act wfTypes.Action) error {
|
||||
comp, patcher, clusterName, overrideNamespace, env, err := lookUpCompInfo(v)
|
||||
comp, patcher, clusterName, overrideNamespace, err := lookUpCompInfo(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
workload, traits, healthy, err := p.apply(ctx, *comp, patcher, clusterName, overrideNamespace, env)
|
||||
workload, traits, healthy, err := p.apply(ctx, *comp, patcher, clusterName, overrideNamespace)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -129,15 +129,15 @@ func (p *provider) ApplyComponent(ctx monitorContext.Context, wfCtx wfContext.Co
|
||||
return nil
|
||||
}
|
||||
|
||||
func lookUpCompInfo(v *value.Value) (*common.ApplicationComponent, *value.Value, string, string, string, error) {
|
||||
func lookUpCompInfo(v *value.Value) (*common.ApplicationComponent, *value.Value, string, string, error) {
|
||||
compSettings, err := v.LookupValue("value")
|
||||
if err != nil {
|
||||
return nil, nil, "", "", "", err
|
||||
return nil, nil, "", "", err
|
||||
}
|
||||
comp := &common.ApplicationComponent{}
|
||||
|
||||
if err := compSettings.UnmarshalTo(comp); err != nil {
|
||||
return nil, nil, "", "", "", err
|
||||
return nil, nil, "", "", err
|
||||
}
|
||||
patcher, err := v.LookupValue("patch")
|
||||
if err != nil {
|
||||
@@ -151,11 +151,7 @@ func lookUpCompInfo(v *value.Value) (*common.ApplicationComponent, *value.Value,
|
||||
if err != nil {
|
||||
overrideNamespace = ""
|
||||
}
|
||||
env, err := v.GetString("env")
|
||||
if err != nil {
|
||||
env = ""
|
||||
}
|
||||
return comp, patcher, clusterName, overrideNamespace, env, nil
|
||||
return comp, patcher, clusterName, overrideNamespace, nil
|
||||
}
|
||||
|
||||
// LoadComponent load component describe info in application.
|
||||
|
||||
@@ -185,7 +185,7 @@ func TestLoadComponentInOrder(t *testing.T) {
|
||||
|
||||
var testHealthy bool
|
||||
|
||||
func simpleComponentApplyForTest(_ context.Context, comp common.ApplicationComponent, _ *value.Value, _, _, _ string) (*unstructured.Unstructured, []*unstructured.Unstructured, bool, error) {
|
||||
func simpleComponentApplyForTest(_ context.Context, comp common.ApplicationComponent, _ *value.Value, _, _ string) (*unstructured.Unstructured, []*unstructured.Unstructured, bool, error) {
|
||||
workload := new(unstructured.Unstructured)
|
||||
workload.UnmarshalJSON([]byte(`{
|
||||
"apiVersion": "v1",
|
||||
|
||||
Reference in New Issue
Block a user