...
1
16
17 package autoprovision
18
19 import (
20 "context"
21 "fmt"
22 "io"
23
24 corev1 "k8s.io/api/core/v1"
25 "k8s.io/apimachinery/pkg/api/errors"
26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27 "k8s.io/apiserver/pkg/admission"
28 genericadmissioninitializer "k8s.io/apiserver/pkg/admission/initializer"
29 "k8s.io/client-go/informers"
30 "k8s.io/client-go/kubernetes"
31 corev1listers "k8s.io/client-go/listers/core/v1"
32 api "k8s.io/kubernetes/pkg/apis/core"
33 )
34
35
36 const PluginName = "NamespaceAutoProvision"
37
38
39 func Register(plugins *admission.Plugins) {
40 plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
41 return NewProvision(), nil
42 })
43 }
44
45
46
47
48 type Provision struct {
49 *admission.Handler
50 client kubernetes.Interface
51 namespaceLister corev1listers.NamespaceLister
52 }
53
54 var _ admission.MutationInterface = &Provision{}
55 var _ = genericadmissioninitializer.WantsExternalKubeInformerFactory(&Provision{})
56 var _ = genericadmissioninitializer.WantsExternalKubeClientSet(&Provision{})
57
58
59 func (p *Provision) Admit(ctx context.Context, a admission.Attributes, o admission.ObjectInterfaces) error {
60
61 if a.IsDryRun() {
62 return nil
63 }
64
65
66
67
68 if len(a.GetNamespace()) == 0 || a.GetKind().GroupKind() == api.Kind("Namespace") {
69 return nil
70 }
71
72 if !p.WaitForReady() {
73 return admission.NewForbidden(a, fmt.Errorf("not yet ready to handle request"))
74 }
75
76 _, err := p.namespaceLister.Get(a.GetNamespace())
77 if err == nil {
78 return nil
79 }
80
81 if !errors.IsNotFound(err) {
82 return admission.NewForbidden(a, err)
83 }
84
85 namespace := &corev1.Namespace{
86 ObjectMeta: metav1.ObjectMeta{
87 Name: a.GetNamespace(),
88 Namespace: "",
89 },
90 Status: corev1.NamespaceStatus{},
91 }
92
93 _, err = p.client.CoreV1().Namespaces().Create(context.TODO(), namespace, metav1.CreateOptions{})
94 if err != nil && !errors.IsAlreadyExists(err) {
95 return admission.NewForbidden(a, err)
96 }
97
98 return nil
99 }
100
101
102 func NewProvision() *Provision {
103 return &Provision{
104 Handler: admission.NewHandler(admission.Create),
105 }
106 }
107
108
109 func (p *Provision) SetExternalKubeClientSet(client kubernetes.Interface) {
110 p.client = client
111 }
112
113
114 func (p *Provision) SetExternalKubeInformerFactory(f informers.SharedInformerFactory) {
115 namespaceInformer := f.Core().V1().Namespaces()
116 p.namespaceLister = namespaceInformer.Lister()
117 p.SetReadyFunc(namespaceInformer.Informer().HasSynced)
118 }
119
120
121 func (p *Provision) ValidateInitialization() error {
122 if p.namespaceLister == nil {
123 return fmt.Errorf("missing namespaceLister")
124 }
125 if p.client == nil {
126 return fmt.Errorf("missing client")
127 }
128 return nil
129 }
130
View as plain text