update storageclass-accessor webhook (#5927)
Signed-off-by: stoneshi-yunify <stoneshi@kubesphere.io>
This commit is contained in:
6
vendor/github.com/kubesphere/storageclass-accessor/webhook/certwatcher.go
generated
vendored
6
vendor/github.com/kubesphere/storageclass-accessor/webhook/certwatcher.go
generated
vendored
@@ -92,7 +92,7 @@ func (cw *CertWatcher) Watch() {
|
||||
return
|
||||
}
|
||||
|
||||
klog.Error(err, "certificate watch error")
|
||||
klog.ErrorS(err, "certificate watch failed")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -126,12 +126,12 @@ func (cw *CertWatcher) handleEvent(event fsnotify.Event) {
|
||||
// If the file was removed, re-add the watch.
|
||||
if isRemove(event) {
|
||||
if err := cw.watcher.Add(event.Name); err != nil {
|
||||
klog.Error(err, "error re-watching file")
|
||||
klog.ErrorS(err, "failed to re-watching file")
|
||||
}
|
||||
}
|
||||
|
||||
if err := cw.ReadCertificate(); err != nil {
|
||||
klog.Error(err, "error re-reading certificate")
|
||||
klog.ErrorS(err, "failed to re-reading certificate")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
69
vendor/github.com/kubesphere/storageclass-accessor/webhook/pvc.go
generated
vendored
69
vendor/github.com/kubesphere/storageclass-accessor/webhook/pvc.go
generated
vendored
@@ -1,10 +1,16 @@
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
admissionv1 "k8s.io/api/admission/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/klog/v2"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client/config"
|
||||
)
|
||||
|
||||
type ReqInfo struct {
|
||||
@@ -20,28 +26,55 @@ var reviewResponse = &admissionv1.AdmissionResponse{
|
||||
Result: &metav1.Status{},
|
||||
}
|
||||
|
||||
func AdmitPVC(ar admissionv1.AdmissionReview) *admissionv1.AdmissionResponse {
|
||||
klog.Info("admitting pvc")
|
||||
type Admitter struct {
|
||||
client client.Client
|
||||
}
|
||||
|
||||
func NewAdmitter() (*Admitter, error) {
|
||||
cfg, err := config.GetConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cli, err := client.New(cfg, client.Options{
|
||||
Scheme: scheme,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
a := &Admitter{
|
||||
client: cli,
|
||||
}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
func NewAdmitterWithClient(client client.Client) *Admitter {
|
||||
return &Admitter{
|
||||
client: client,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Admitter) serverPVCRequest(w http.ResponseWriter, r *http.Request) {
|
||||
server(w, r, newDelegateToV1AdmitHandler(a.AdmitPVC))
|
||||
}
|
||||
|
||||
func (a *Admitter) AdmitPVC(ar admissionv1.AdmissionReview) *admissionv1.AdmissionResponse {
|
||||
if ar.Request.Operation != admissionv1.Create {
|
||||
return reviewResponse
|
||||
}
|
||||
|
||||
raw := ar.Request.Object.Raw
|
||||
|
||||
var newPVC *corev1.PersistentVolumeClaim
|
||||
|
||||
deserializer := codecs.UniversalDeserializer()
|
||||
pvc := &corev1.PersistentVolumeClaim{}
|
||||
obj, _, err := deserializer.Decode(raw, nil, pvc)
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
klog.ErrorS(err, "failed to decode raw object")
|
||||
return toV1AdmissionResponse(err)
|
||||
}
|
||||
var ok bool
|
||||
newPVC, ok = obj.(*corev1.PersistentVolumeClaim)
|
||||
|
||||
newPVC, ok := obj.(*corev1.PersistentVolumeClaim)
|
||||
if !ok {
|
||||
klog.Error("obj can't exchange to pvc object")
|
||||
err = fmt.Errorf("obj can't exchange to pvc object")
|
||||
klog.ErrorS(err, "failed to exchange to pvc object")
|
||||
return toV1AdmissionResponse(err)
|
||||
}
|
||||
|
||||
@@ -52,26 +85,28 @@ func AdmitPVC(ar admissionv1.AdmissionReview) *admissionv1.AdmissionResponse {
|
||||
operator: string(ar.Request.Operation),
|
||||
storageClassName: *newPVC.Spec.StorageClassName,
|
||||
}
|
||||
return DecidePVCV1(reqPVC)
|
||||
|
||||
klog.Infof("request pvc: %v", reqPVC)
|
||||
return a.decidePVCV1(context.Background(), reqPVC)
|
||||
}
|
||||
|
||||
func DecidePVCV1(pvc ReqInfo) *admissionv1.AdmissionResponse {
|
||||
|
||||
accessors, err := getAccessors(pvc.storageClassName)
|
||||
func (a *Admitter) decidePVCV1(ctx context.Context, pvc ReqInfo) *admissionv1.AdmissionResponse {
|
||||
accessors, err := a.getAccessors(ctx, pvc.storageClassName)
|
||||
|
||||
if err != nil {
|
||||
klog.Error("get accessor failed, err:", err)
|
||||
klog.ErrorS(err, "get accessor failed")
|
||||
return toV1AdmissionResponse(err)
|
||||
} else if len(accessors) == 0 {
|
||||
klog.Info("Not Found accessor for the storageClass:", pvc.storageClassName)
|
||||
klog.Infof("Not Found accessor for the storageClass: %s", pvc.storageClassName)
|
||||
return reviewResponse
|
||||
}
|
||||
|
||||
for _, accessor := range accessors {
|
||||
if err = validateNameSpace(pvc, accessor); err != nil {
|
||||
klog.Infof("starting validating accessor: %s", accessor.Name)
|
||||
if err = a.validateNameSpace(ctx, pvc, &accessor); err != nil {
|
||||
return toV1AdmissionResponse(err)
|
||||
}
|
||||
if err = validateWorkSpace(pvc, accessor); err != nil {
|
||||
if err = a.validateWorkSpace(ctx, pvc, &accessor); err != nil {
|
||||
return toV1AdmissionResponse(err)
|
||||
}
|
||||
}
|
||||
|
||||
4
vendor/github.com/kubesphere/storageclass-accessor/webhook/scheme.go
generated
vendored
4
vendor/github.com/kubesphere/storageclass-accessor/webhook/scheme.go
generated
vendored
@@ -1,6 +1,7 @@
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"github.com/kubesphere/storageclass-accessor/client/apis/accessor/v1alpha1"
|
||||
admissionv1 "k8s.io/api/admission/v1"
|
||||
admissionv1beta1 "k8s.io/api/admission/v1beta1"
|
||||
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||
@@ -9,6 +10,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
workspacev1alpha1 "kubesphere.io/api/tenant/v1alpha1"
|
||||
)
|
||||
|
||||
var scheme = runtime.NewScheme()
|
||||
@@ -24,4 +26,6 @@ func addToScheme(scheme *runtime.Scheme) {
|
||||
utilruntime.Must(admissionregistrationv1beta1.AddToScheme(scheme))
|
||||
utilruntime.Must(admissionv1.AddToScheme(scheme))
|
||||
utilruntime.Must(admissionregistrationv1.AddToScheme(scheme))
|
||||
utilruntime.Must(v1alpha1.AddToScheme(scheme))
|
||||
utilruntime.Must(workspacev1alpha1.AddToScheme(scheme))
|
||||
}
|
||||
|
||||
66
vendor/github.com/kubesphere/storageclass-accessor/webhook/selector.go
generated
vendored
66
vendor/github.com/kubesphere/storageclass-accessor/webhook/selector.go
generated
vendored
@@ -1,9 +1,11 @@
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"github.com/kubesphere/storageclass-accessor/client/apis/accessor/v1alpha1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/utils/strings/slices"
|
||||
workspacev1alpha1 "kubesphere.io/api/tenant/v1alpha1"
|
||||
|
||||
"github.com/kubesphere/storageclass-accessor/client/apis/accessor/v1alpha1"
|
||||
)
|
||||
|
||||
func matchLabel(info map[string]string, expressions []v1alpha1.MatchExpressions) bool {
|
||||
@@ -14,11 +16,26 @@ func matchLabel(info map[string]string, expressions []v1alpha1.MatchExpressions)
|
||||
for _, rule := range expressions {
|
||||
rulePass := true
|
||||
for _, item := range rule.MatchExpressions {
|
||||
if len(item.Values) == 0 {
|
||||
continue
|
||||
}
|
||||
var labelKeyExist bool
|
||||
_, ok := info[item.Key]
|
||||
if ok {
|
||||
labelKeyExist = true
|
||||
}
|
||||
switch item.Operator {
|
||||
case v1alpha1.In:
|
||||
rulePass = rulePass && inList(info[item.Key], item.Values)
|
||||
rulePass = rulePass && labelKeyExist && (slices.Contains(item.Values, "*") || slices.Contains(item.Values, info[item.Key]))
|
||||
case v1alpha1.NotIn:
|
||||
rulePass = rulePass && !inList(info[item.Key], item.Values)
|
||||
if labelKeyExist {
|
||||
rulePass = rulePass && !slices.Contains(item.Values, "*") && !slices.Contains(item.Values, info[item.Key])
|
||||
}
|
||||
default:
|
||||
continue
|
||||
}
|
||||
if !rulePass {
|
||||
break
|
||||
}
|
||||
}
|
||||
if rulePass {
|
||||
@@ -28,7 +45,7 @@ func matchLabel(info map[string]string, expressions []v1alpha1.MatchExpressions)
|
||||
return false
|
||||
}
|
||||
|
||||
func matchField(ns *corev1.Namespace, expressions []v1alpha1.FieldExpressions) bool {
|
||||
func nsMatchField(ns *corev1.Namespace, expressions []v1alpha1.FieldExpressions) bool {
|
||||
//If not set limit, default pass
|
||||
if len(expressions) == 0 {
|
||||
return true
|
||||
@@ -37,18 +54,28 @@ func matchField(ns *corev1.Namespace, expressions []v1alpha1.FieldExpressions) b
|
||||
for _, rule := range expressions {
|
||||
rulePass := true
|
||||
for _, item := range rule.FieldExpressions {
|
||||
if len(item.Values) == 0 {
|
||||
continue
|
||||
}
|
||||
var val string
|
||||
switch item.Field {
|
||||
case v1alpha1.Name:
|
||||
val = ns.Name
|
||||
case v1alpha1.Status:
|
||||
val = string(ns.Status.Phase)
|
||||
default:
|
||||
continue
|
||||
}
|
||||
switch item.Operator {
|
||||
case v1alpha1.In:
|
||||
rulePass = rulePass && inList(val, item.Values)
|
||||
rulePass = rulePass && (slices.Contains(item.Values, "*") || slices.Contains(item.Values, val))
|
||||
case v1alpha1.NotIn:
|
||||
rulePass = rulePass && !inList(val, item.Values)
|
||||
rulePass = rulePass && !slices.Contains(item.Values, "*") && !slices.Contains(item.Values, val)
|
||||
default:
|
||||
continue
|
||||
}
|
||||
if !rulePass {
|
||||
break
|
||||
}
|
||||
}
|
||||
if rulePass {
|
||||
@@ -66,15 +93,29 @@ func wsMatchField(ws *workspacev1alpha1.Workspace, expressions []v1alpha1.FieldE
|
||||
for _, rule := range expressions {
|
||||
pass := true
|
||||
for _, item := range rule.FieldExpressions {
|
||||
if len(item.Values) == 0 {
|
||||
continue
|
||||
}
|
||||
var val string
|
||||
switch item.Field {
|
||||
case v1alpha1.Name:
|
||||
val = ws.Name
|
||||
case v1alpha1.Status:
|
||||
// TODO(stone): check status
|
||||
continue
|
||||
default:
|
||||
continue
|
||||
}
|
||||
switch item.Operator {
|
||||
case v1alpha1.In:
|
||||
pass = pass && inList(ws.Name, item.Values)
|
||||
pass = pass && (slices.Contains(item.Values, "*") || slices.Contains(item.Values, val))
|
||||
case v1alpha1.NotIn:
|
||||
pass = pass && !inList(ws.Name, item.Values)
|
||||
pass = pass && !slices.Contains(item.Values, "*") && !slices.Contains(item.Values, val)
|
||||
default:
|
||||
continue
|
||||
}
|
||||
if !pass {
|
||||
break
|
||||
}
|
||||
}
|
||||
if pass {
|
||||
@@ -83,12 +124,3 @@ func wsMatchField(ws *workspacev1alpha1.Workspace, expressions []v1alpha1.FieldE
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func inList(val string, list []string) bool {
|
||||
for _, elements := range list {
|
||||
if val == elements {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
108
vendor/github.com/kubesphere/storageclass-accessor/webhook/validation.go
generated
vendored
108
vendor/github.com/kubesphere/storageclass-accessor/webhook/validation.go
generated
vendored
@@ -3,127 +3,87 @@ package webhook
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/kubesphere/storageclass-accessor/client/apis/accessor/v1alpha1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/klog/v2"
|
||||
workspacev1alpha1 "kubesphere.io/api/tenant/v1alpha1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client/config"
|
||||
)
|
||||
|
||||
func validateNameSpace(reqResource ReqInfo, accessor *v1alpha1.Accessor) error {
|
||||
klog.Info("start validate namespace")
|
||||
//accessor, err := getAccessor()
|
||||
ns, err := getNameSpace(reqResource.namespace)
|
||||
func (a *Admitter) validateNameSpace(ctx context.Context, reqResource ReqInfo, accessor *v1alpha1.Accessor) error {
|
||||
klog.Infof("start validating namespace: %s", reqResource.namespace)
|
||||
ns, err := a.getNameSpace(ctx, reqResource.namespace)
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
klog.ErrorS(err, "get namespace failed", "namespace", reqResource.namespace)
|
||||
return err
|
||||
}
|
||||
var fieldPass, labelPass bool
|
||||
fieldPass = matchField(ns, accessor.Spec.NameSpaceSelector.FieldSelector)
|
||||
labelPass = matchLabel(ns.Labels, accessor.Spec.NameSpaceSelector.LabelSelector)
|
||||
fieldPass := nsMatchField(ns, accessor.Spec.NameSpaceSelector.FieldSelector)
|
||||
labelPass := matchLabel(ns.Labels, accessor.Spec.NameSpaceSelector.LabelSelector)
|
||||
if fieldPass && labelPass {
|
||||
return nil
|
||||
}
|
||||
|
||||
klog.Error(fmt.Sprintf("%s %s does not allowed %s in the namespace: %s", reqResource.resource, reqResource.name, reqResource.operator, reqResource.namespace))
|
||||
return fmt.Errorf("The storageClass: %s does not allowed %s %s %s in the namespace: %s ", reqResource.storageClassName, reqResource.operator, reqResource.resource, reqResource.name, reqResource.namespace)
|
||||
err = fmt.Errorf("%s %s is not allowed %s in the namespace: %s", reqResource.resource, reqResource.name, reqResource.operator, reqResource.namespace)
|
||||
klog.ErrorS(err, "validate namespace failed")
|
||||
return err
|
||||
}
|
||||
|
||||
func validateWorkSpace(reqResource ReqInfo, accessor *v1alpha1.Accessor) error {
|
||||
klog.Info("start validate workspace")
|
||||
func (a *Admitter) validateWorkSpace(ctx context.Context, reqResource ReqInfo, accessor *v1alpha1.Accessor) error {
|
||||
klog.Infof("start validating workspace for namespace: %s", reqResource.namespace)
|
||||
|
||||
ns, err := getNameSpace(reqResource.namespace)
|
||||
ns, err := a.getNameSpace(ctx, reqResource.namespace)
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
klog.ErrorS(err, "get namespace failed", "namespace", reqResource.namespace)
|
||||
return err
|
||||
}
|
||||
if wsName, ok := ns.Labels["kubesphere.io/workspace"]; ok {
|
||||
klog.Infof("namespace %s is in workspace %s", reqResource.namespace, wsName)
|
||||
var ws *workspacev1alpha1.Workspace
|
||||
ws, err = getWorkSpace(wsName)
|
||||
ws, err = a.getWorkSpace(ctx, wsName)
|
||||
if err != nil {
|
||||
klog.Error("Cannot get the workspace")
|
||||
klog.ErrorS(err, "failed to get the workspace", "workspace", wsName)
|
||||
return err
|
||||
}
|
||||
var fieldPass, labelPass bool
|
||||
fieldPass = wsMatchField(ws, accessor.Spec.WorkSpaceSelector.FieldSelector)
|
||||
labelPass = matchLabel(ns.Labels, accessor.Spec.WorkSpaceSelector.LabelSelector)
|
||||
fieldPass := wsMatchField(ws, accessor.Spec.WorkSpaceSelector.FieldSelector)
|
||||
labelPass := matchLabel(ws.Labels, accessor.Spec.WorkSpaceSelector.LabelSelector)
|
||||
if fieldPass && labelPass {
|
||||
return nil
|
||||
}
|
||||
|
||||
klog.Error(fmt.Sprintf("%s %s does not allowed %s in the workspace: %s", reqResource.resource, reqResource.name, reqResource.operator, wsName))
|
||||
return fmt.Errorf("The storageClass: %s does not allowed %s %s %s in the workspace: %s ", reqResource.storageClassName, reqResource.operator, reqResource.resource, reqResource.name, wsName)
|
||||
err = fmt.Errorf("%s %s is not allowed %s in the workspace: %s", reqResource.resource, reqResource.name, reqResource.operator, wsName)
|
||||
klog.ErrorS(err, "validate workspace failed", "workspace", wsName)
|
||||
return err
|
||||
}
|
||||
klog.Info("Unable to get workspace information, skipped.")
|
||||
klog.Infof("namespace %s has no workspace information, skipped", reqResource.namespace)
|
||||
return nil
|
||||
}
|
||||
|
||||
func getNameSpace(nameSpaceName string) (*corev1.Namespace, error) {
|
||||
nsClient, err := client.New(config.GetConfigOrDie(), client.Options{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
func (a *Admitter) getNameSpace(ctx context.Context, nameSpaceName string) (*corev1.Namespace, error) {
|
||||
ns := &corev1.Namespace{}
|
||||
err = nsClient.Get(context.Background(), types.NamespacedName{Namespace: "", Name: nameSpaceName}, ns)
|
||||
if err != nil {
|
||||
klog.Error("client get namespace failed, err:", err)
|
||||
return nil, err
|
||||
}
|
||||
return ns, nil
|
||||
err := a.client.Get(ctx, types.NamespacedName{Name: nameSpaceName}, ns)
|
||||
return ns, err
|
||||
}
|
||||
|
||||
func getAccessors(storageClassName string) ([]*v1alpha1.Accessor, error) {
|
||||
// get config
|
||||
cfg, err := config.GetConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var cli client.Client
|
||||
opts := client.Options{}
|
||||
scheme := runtime.NewScheme()
|
||||
_ = v1alpha1.AddToScheme(scheme)
|
||||
opts.Scheme = scheme
|
||||
cli, err = client.New(cfg, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
func (a *Admitter) getAccessors(ctx context.Context, storageClassName string) ([]v1alpha1.Accessor, error) {
|
||||
accessorList := &v1alpha1.AccessorList{}
|
||||
|
||||
var listOpt []client.ListOption
|
||||
err = cli.List(context.Background(), accessorList, listOpt...)
|
||||
err := a.client.List(ctx, accessorList)
|
||||
if err != nil {
|
||||
klog.ErrorS(err, "failed to list accessors for storage class", "storageClassName", storageClassName)
|
||||
// TODO If not found , pass or not?
|
||||
return nil, err
|
||||
}
|
||||
list := make([]*v1alpha1.Accessor, 0)
|
||||
list := make([]v1alpha1.Accessor, 0)
|
||||
for _, accessor := range accessorList.Items {
|
||||
if accessor.Spec.StorageClassName == storageClassName {
|
||||
list = append(list, &accessor)
|
||||
list = append(list, accessor)
|
||||
}
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func getWorkSpace(workspaceName string) (*workspacev1alpha1.Workspace, error) {
|
||||
cfg, err := config.GetConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var cli client.Client
|
||||
opts := client.Options{}
|
||||
scheme := runtime.NewScheme()
|
||||
_ = workspacev1alpha1.AddToScheme(scheme)
|
||||
opts.Scheme = scheme
|
||||
cli, err = client.New(cfg, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
func (a *Admitter) getWorkSpace(ctx context.Context, workspaceName string) (*workspacev1alpha1.Workspace, error) {
|
||||
workspace := &workspacev1alpha1.Workspace{}
|
||||
err = cli.Get(context.Background(), types.NamespacedName{Namespace: "", Name: workspaceName}, workspace)
|
||||
if err != nil {
|
||||
klog.Error("can't get the workspace by name, err:", err)
|
||||
}
|
||||
err := a.client.Get(ctx, types.NamespacedName{Name: workspaceName}, workspace)
|
||||
return workspace, err
|
||||
}
|
||||
|
||||
105
vendor/github.com/kubesphere/storageclass-accessor/webhook/weebhook.go
generated
vendored
105
vendor/github.com/kubesphere/storageclass-accessor/webhook/weebhook.go
generated
vendored
@@ -5,12 +5,14 @@ import (
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"io/ioutil"
|
||||
v1 "k8s.io/api/admission/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/klog/v2"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -50,38 +52,39 @@ func newDelegateToV1AdmitHandler(f admitV1Func) admitHandler {
|
||||
}
|
||||
|
||||
func server(w http.ResponseWriter, r *http.Request, admit admitHandler) {
|
||||
var body []byte
|
||||
var err error
|
||||
if r.Body == nil {
|
||||
msg := "Expected request body to be non-empty"
|
||||
klog.Error(msg)
|
||||
http.Error(w, msg, http.StatusBadRequest)
|
||||
err = fmt.Errorf("request body is nil")
|
||||
klog.ErrorS(err, "request body is nil")
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadAll(r.Body)
|
||||
var body []byte
|
||||
body, err = io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("Request could not be decoded: %v", err)
|
||||
klog.Error(msg)
|
||||
http.Error(w, msg, http.StatusBadRequest)
|
||||
klog.ErrorS(err, "read request body failed")
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
body = data
|
||||
|
||||
// verify the content type is accurate
|
||||
contentType := r.Header.Get("Content-Type")
|
||||
if contentType != "application/json" {
|
||||
msg := fmt.Sprintf("contentType=%s, expect application/json", contentType)
|
||||
klog.Errorf(msg)
|
||||
http.Error(w, msg, http.StatusBadRequest)
|
||||
err = fmt.Errorf("contentType=%s, expect application/json", contentType)
|
||||
klog.ErrorS(err, "contentType is not application/json")
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
klog.V(2).Info(fmt.Sprintf("handling request: %s", body))
|
||||
klog.Infof("handling request: %s", body)
|
||||
|
||||
deserializer := codecs.UniversalDeserializer()
|
||||
obj, gvk, err := deserializer.Decode(body, nil, nil)
|
||||
var obj runtime.Object
|
||||
var gvk *schema.GroupVersionKind
|
||||
obj, gvk, err = codecs.UniversalDeserializer().Decode(body, nil, nil)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("Request could not be decoded: %v", err)
|
||||
klog.Error(msg)
|
||||
http.Error(w, msg, http.StatusBadRequest)
|
||||
klog.ErrorS(err, "request body could not be decoded")
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -91,9 +94,9 @@ func server(w http.ResponseWriter, r *http.Request, admit admitHandler) {
|
||||
case v1.SchemeGroupVersion.WithKind("AdmissionReview"):
|
||||
requestedAdmissionReview, ok := obj.(*v1.AdmissionReview)
|
||||
if !ok {
|
||||
msg := fmt.Sprintf("Expected v1.AdmissionReview but got: %T", obj)
|
||||
klog.Errorf(msg)
|
||||
http.Error(w, msg, http.StatusBadRequest)
|
||||
err = fmt.Errorf("expected v1.AdmissionReview but got: %T", obj)
|
||||
klog.ErrorS(err, "wrong object type")
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
responseAdmissionReview := &v1.AdmissionReview{}
|
||||
@@ -101,41 +104,40 @@ func server(w http.ResponseWriter, r *http.Request, admit admitHandler) {
|
||||
responseAdmissionReview.Response = admit.v1(*requestedAdmissionReview)
|
||||
responseAdmissionReview.Response.UID = requestedAdmissionReview.Request.UID
|
||||
responseObj = responseAdmissionReview
|
||||
|
||||
klog.Infof("start writing response: %v", responseObj)
|
||||
|
||||
var respBytes []byte
|
||||
respBytes, err = json.Marshal(responseObj)
|
||||
if err != nil {
|
||||
klog.ErrorS(err, "failed to marshal response object")
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, err = w.Write(respBytes)
|
||||
if err != nil {
|
||||
klog.ErrorS(err, "failed to write response")
|
||||
}
|
||||
default:
|
||||
msg := fmt.Sprintf("Unsupported group version kind: %v", gvk)
|
||||
klog.Error(msg)
|
||||
http.Error(w, msg, http.StatusBadRequest)
|
||||
err = fmt.Errorf("unsupported group version kind: %v", gvk)
|
||||
klog.ErrorS(err, "unsupported group version kind")
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
klog.V(2).Info(fmt.Sprintf("sending response: %v", responseObj))
|
||||
|
||||
respBytes, err := json.Marshal(responseObj)
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if _, err := w.Write(respBytes); err != nil {
|
||||
klog.Error(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func serverPVCRequest(w http.ResponseWriter, r *http.Request) {
|
||||
server(w, r, newDelegateToV1AdmitHandler(AdmitPVC))
|
||||
}
|
||||
|
||||
func startServer(ctx context.Context, tlsConfig *tls.Config, cw *CertWatcher) error {
|
||||
func startServer(ctx context.Context, tlsConfig *tls.Config, cw *CertWatcher, admitter *Admitter) error {
|
||||
go func() {
|
||||
klog.Info("Starting certificate watcher")
|
||||
if err := cw.Start(ctx); err != nil {
|
||||
klog.Errorf("certificate watcher error: %v", err)
|
||||
klog.ErrorS(err, "failed to start certificate watcher")
|
||||
}
|
||||
}()
|
||||
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/persistentvolumeclaims", serverPVCRequest)
|
||||
mux.HandleFunc("/persistentvolumeclaims", admitter.serverPVCRequest)
|
||||
srv := &http.Server{
|
||||
Handler: mux,
|
||||
TLSConfig: tlsConfig,
|
||||
@@ -148,6 +150,7 @@ func startServer(ctx context.Context, tlsConfig *tls.Config, cw *CertWatcher) er
|
||||
}
|
||||
return srv.Serve(listener)
|
||||
}
|
||||
|
||||
func main(cmd *cobra.Command, args []string) {
|
||||
// Create new cert watcher
|
||||
ctx, cancel := context.WithCancel(cmd.Context())
|
||||
@@ -160,7 +163,13 @@ func main(cmd *cobra.Command, args []string) {
|
||||
GetCertificate: cw.GetCertificate,
|
||||
}
|
||||
|
||||
if err := startServer(ctx, tslConfig, cw); err != nil {
|
||||
klog.Fatalf("server stopped: %v", err)
|
||||
admitter, err := NewAdmitter()
|
||||
if err != nil {
|
||||
klog.Fatalf("failed to initialize new admitter: %v", err)
|
||||
}
|
||||
|
||||
err = startServer(ctx, tslConfig, cw, admitter)
|
||||
if err != nil {
|
||||
klog.Fatalf("failed to start server: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
3
vendor/modules.txt
vendored
3
vendor/modules.txt
vendored
@@ -615,7 +615,7 @@ github.com/kubesphere/pvc-autoresizer/runners
|
||||
# github.com/kubesphere/sonargo v0.0.2 => github.com/kubesphere/sonargo v0.0.2
|
||||
## explicit
|
||||
github.com/kubesphere/sonargo/sonar
|
||||
# github.com/kubesphere/storageclass-accessor v0.2.2
|
||||
# github.com/kubesphere/storageclass-accessor v0.2.4-0.20230919084454-2f39c69db301 => github.com/kubesphere/storageclass-accessor v0.2.4-0.20230919084454-2f39c69db301
|
||||
## explicit; go 1.16
|
||||
github.com/kubesphere/storageclass-accessor/client/apis/accessor/v1alpha1
|
||||
github.com/kubesphere/storageclass-accessor/webhook
|
||||
@@ -2711,6 +2711,7 @@ sigs.k8s.io/yaml
|
||||
# github.com/kubernetes-csi/external-snapshotter/client/v4 => github.com/kubernetes-csi/external-snapshotter/client/v4 v4.2.0
|
||||
# github.com/kubesphere/pvc-autoresizer => github.com/kubesphere/pvc-autoresizer v0.3.0
|
||||
# github.com/kubesphere/sonargo => github.com/kubesphere/sonargo v0.0.2
|
||||
# github.com/kubesphere/storageclass-accessor => github.com/kubesphere/storageclass-accessor v0.2.4-0.20230919084454-2f39c69db301
|
||||
# github.com/lann/builder => github.com/lann/builder v0.0.0-20180802200727-47ae307949d0
|
||||
# github.com/lann/ps => github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0
|
||||
# github.com/lib/pq => github.com/lib/pq v1.10.7
|
||||
|
||||
Reference in New Issue
Block a user