Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for ReplicaSet k8s kind #152

Merged
2 changes: 1 addition & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ linters-settings:
Statements: 50
goconst:
min-len: 2
min-occurrences: 2
min-occurrences: 5
depguard:
list-type: blacklist
include-go-root: false
Expand Down
26 changes: 25 additions & 1 deletion internal/k8s/selfregister.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,35 @@ func (a *AdmissionWebhookRegisterClient) Register(ctx context.Context, c *config
{
Operations: []admissionv1.OperationType{admissionv1.Create, admissionv1.Update},
Rule: admissionv1.Rule{
APIGroups: []string{"extensions"},
APIGroups: []string{"apps"},
APIVersions: []string{"v1"},
Resources: []string{"deployments"},
},
},
{
Operations: []admissionv1.OperationType{admissionv1.Create, admissionv1.Update},
Rule: admissionv1.Rule{
APIGroups: []string{"apps"},
APIVersions: []string{"v1"},
Resources: []string{"statefulsets"},
},
},
{
Operations: []admissionv1.OperationType{admissionv1.Create, admissionv1.Update},
Rule: admissionv1.Rule{
APIGroups: []string{"apps"},
APIVersions: []string{"v1"},
Resources: []string{"daemonsets"},
},
},
{
Operations: []admissionv1.OperationType{admissionv1.Create, admissionv1.Update},
Rule: admissionv1.Rule{
APIGroups: []string{"apps"},
APIVersions: []string{"v1"},
Resources: []string{"replicasets"},
},
},
},
SideEffects: &sideEffects,
AdmissionReviewVersions: []string{"v1"},
Expand Down
68 changes: 49 additions & 19 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,19 +69,25 @@ func (s *admissionWebhookServer) Review(in *admissionv1.AdmissionRequest) *admis
return resp
}

p, metaPtr, spec := s.unmarshal(in)
podMetaPtr, spec := s.unmarshal(in)
p := ""
if in.Kind.Kind != "Pod" {
p = "/spec/template"
}
p = path.Join("/", p)

if spec == nil {
resp.Allowed = true
return resp
}
annotation := metaPtr.Annotations[s.config.Annotation]
annotation := podMetaPtr.Annotations[s.config.Annotation]

if annotation != "" {
bytes, err := json.Marshal([]jsonpatch.JsonPatchOperation{
s.createInitContainerPatch(p, annotation, spec.InitContainers),
s.createContainerPatch(p, annotation, spec.Containers),
s.createVolumesPatch(p, spec.Volumes),
s.createLabelPatch(p, metaPtr.Labels),
s.createLabelPatch(p, podMetaPtr.Labels),
})
if err != nil {
resp.Result = &v1.Status{
Expand All @@ -98,45 +104,69 @@ func (s *admissionWebhookServer) Review(in *admissionv1.AdmissionRequest) *admis
return resp
}

func (s *admissionWebhookServer) unmarshal(in *admissionv1.AdmissionRequest) (p string, meta *v1.ObjectMeta, spec *corev1.PodSpec) {
var podSpec *corev1.PodSpec
var metaPtr *v1.ObjectMeta
func (s *admissionWebhookServer) unmarshal(in *admissionv1.AdmissionRequest) (podMetaPtr *v1.ObjectMeta, podSpec *corev1.PodSpec) {
var target interface{}
p = "/spec/template"
var metaPtr *v1.ObjectMeta
switch in.Kind.Kind {
case "Deployment":
var deployment appsv1.Deployment
metaPtr = &deployment.Spec.Template.ObjectMeta
metaPtr = &deployment.ObjectMeta
podMetaPtr = &deployment.Spec.Template.ObjectMeta
podSpec = &deployment.Spec.Template.Spec
target = &deployment
case "Pod":
var pod corev1.Pod
p = ""
metaPtr = &pod.ObjectMeta
podMetaPtr = &pod.ObjectMeta
podSpec = &pod.Spec
target = &pod
case "DaemonSet":
var daemonSet appsv1.DaemonSet
metaPtr = &daemonSet.Spec.Template.ObjectMeta
metaPtr = &daemonSet.ObjectMeta
podMetaPtr = &daemonSet.Spec.Template.ObjectMeta
podSpec = &daemonSet.Spec.Template.Spec
target = &daemonSet
case "StatefulSet":
var statefulSet appsv1.StatefulSet
metaPtr = &statefulSet.Spec.Template.ObjectMeta
metaPtr = &statefulSet.ObjectMeta
podMetaPtr = &statefulSet.Spec.Template.ObjectMeta
podSpec = &statefulSet.Spec.Template.Spec
target = &statefulSet
case "ReplicaSet":
var replicaSet appsv1.ReplicaSet
metaPtr = &replicaSet.ObjectMeta
podMetaPtr = &replicaSet.Spec.Template.ObjectMeta
podSpec = &replicaSet.Spec.Template.Spec
target = &replicaSet
default:
return "", nil, nil
return nil, nil
}

if err := json.Unmarshal(in.Object.Raw, target); err != nil {
return "", nil, nil
return nil, nil
}
p = path.Join("/", p)
if metaPtr.Labels == nil {
metaPtr.Labels = make(map[string]string)
podMetaPtr = s.postProcessPodMeta(podMetaPtr, metaPtr, in.Kind.Kind)
return podMetaPtr, podSpec
}

func (s *admissionWebhookServer) postProcessPodMeta(podMetaPtr, metaPtr *v1.ObjectMeta, kind string) *v1.ObjectMeta {
if podMetaPtr.Labels == nil {
podMetaPtr.Labels = make(map[string]string)
}
// Annotations shouldn't be applied second time.
if kind != "Pod" {
if podMetaPtr.Annotations == nil {
podMetaPtr.Annotations = metaPtr.Annotations
} else {
s.logger.Errorf("Malformed specification. Annotations can't be provided in several places.")
}
}
if kind == "ReplicaSet" {
for _, o := range metaPtr.OwnerReferences {
if o.Kind == "Deployment" {
return nil
}
}
}
return p, metaPtr, podSpec
return podMetaPtr
}

func (s *admissionWebhookServer) createVolumesPatch(p string, volumes []corev1.Volume) jsonpatch.JsonPatchOperation {
Expand Down