-
Notifications
You must be signed in to change notification settings - Fork 35
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
Feature: pod security admission #165
Changes from 11 commits
614deae
ffdff05
e68438e
800b0c1
d93f82c
63502cd
e342737
faef587
2eeebfe
497d2a0
d797fca
91e86b5
5985a28
2239fa9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -34,6 +34,7 @@ import ( | |||||||||
networkingv1 "k8s.io/api/networking/v1" | ||||||||||
"k8s.io/apimachinery/pkg/api/resource" | ||||||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||||||||
psaapi "k8s.io/pod-security-admission/api" | ||||||||||
) | ||||||||||
|
||||||||||
const ( | ||||||||||
|
@@ -74,6 +75,8 @@ func GetObjectMeta(name, namespace string, labels, annotations map[string]string | |||||||||
} | ||||||||||
|
||||||||||
// GetContainers iterates through all container components, filters out init containers and returns corresponding containers | ||||||||||
// | ||||||||||
// Deprecated in favor of GetPodTemplateSpec | ||||||||||
feloy marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
func GetContainers(devfileObj parser.DevfileObj, options common.DevfileOptions) ([]corev1.Container, error) { | ||||||||||
allContainers, err := getAllContainers(devfileObj, options) | ||||||||||
if err != nil { | ||||||||||
|
@@ -120,6 +123,8 @@ func GetContainers(devfileObj parser.DevfileObj, options common.DevfileOptions) | |||||||||
} | ||||||||||
|
||||||||||
// GetInitContainers gets the init container for every preStart devfile event | ||||||||||
// | ||||||||||
// Deprecated in favor of GetPodTemplateSpec | ||||||||||
func GetInitContainers(devfileObj parser.DevfileObj) ([]corev1.Container, error) { | ||||||||||
containers, err := getAllContainers(devfileObj, common.DevfileOptions{}) | ||||||||||
if err != nil { | ||||||||||
|
@@ -170,23 +175,92 @@ func GetInitContainers(devfileObj parser.DevfileObj) ([]corev1.Container, error) | |||||||||
|
||||||||||
// DeploymentParams is a struct that contains the required data to create a deployment object | ||||||||||
type DeploymentParams struct { | ||||||||||
TypeMeta metav1.TypeMeta | ||||||||||
ObjectMeta metav1.ObjectMeta | ||||||||||
InitContainers []corev1.Container | ||||||||||
Containers []corev1.Container | ||||||||||
TypeMeta metav1.TypeMeta | ||||||||||
ObjectMeta metav1.ObjectMeta | ||||||||||
// Deprecated. InitContainers, Containers and Volumes are deprecated and are replaced by PodTemplateSpec. | ||||||||||
// A PodTemplateSpec value can be obtained calling GetPodTemplateSpec function, instead of calling GetContainers and GetInitContainers | ||||||||||
InitContainers []corev1.Container | ||||||||||
// Deprecated, see InitContainers | ||||||||||
Containers []corev1.Container | ||||||||||
// Deprecated, see InitContainers | ||||||||||
Volumes []corev1.Volume | ||||||||||
PodTemplateSpec *corev1.PodTemplateSpec | ||||||||||
PodSelectorLabels map[string]string | ||||||||||
Replicas *int32 | ||||||||||
} | ||||||||||
|
||||||||||
// GetDeployment gets a deployment object | ||||||||||
func GetDeployment(devfileObj parser.DevfileObj, deployParams DeploymentParams) (*appsv1.Deployment, error) { | ||||||||||
|
||||||||||
var deploySpecParams deploymentSpecParams | ||||||||||
feloy marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
if deployParams.PodTemplateSpec == nil { | ||||||||||
// Deprecated | ||||||||||
podTemplateSpecParams := podTemplateSpecParams{ | ||||||||||
ObjectMeta: deployParams.ObjectMeta, | ||||||||||
InitContainers: deployParams.InitContainers, | ||||||||||
Containers: deployParams.Containers, | ||||||||||
Volumes: deployParams.Volumes, | ||||||||||
} | ||||||||||
podTemplateSpec, err := getPodTemplateSpec(podTemplateSpecParams) | ||||||||||
if err != nil { | ||||||||||
return nil, err | ||||||||||
} | ||||||||||
deploySpecParams = deploymentSpecParams{ | ||||||||||
PodTemplateSpec: *podTemplateSpec, | ||||||||||
PodSelectorLabels: deployParams.PodSelectorLabels, | ||||||||||
Replicas: deployParams.Replicas, | ||||||||||
} | ||||||||||
} else { | ||||||||||
deploySpecParams = deploymentSpecParams{ | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. dup with library/pkg/devfile/generator/generators.go Lines 209 to 212 in 5985a28
|
||||||||||
PodTemplateSpec: *deployParams.PodTemplateSpec, | ||||||||||
PodSelectorLabels: deployParams.PodSelectorLabels, | ||||||||||
Replicas: deployParams.Replicas, | ||||||||||
} | ||||||||||
} | ||||||||||
|
||||||||||
containerAnnotations, err := getContainerAnnotations(devfileObj, common.DevfileOptions{}) | ||||||||||
if err != nil { | ||||||||||
return nil, err | ||||||||||
} | ||||||||||
deployParams.ObjectMeta.Annotations = mergeMaps(deployParams.ObjectMeta.Annotations, containerAnnotations.Deployment) | ||||||||||
|
||||||||||
deployment := &appsv1.Deployment{ | ||||||||||
TypeMeta: deployParams.TypeMeta, | ||||||||||
ObjectMeta: deployParams.ObjectMeta, | ||||||||||
Spec: *getDeploymentSpec(deploySpecParams), | ||||||||||
} | ||||||||||
|
||||||||||
return deployment, nil | ||||||||||
} | ||||||||||
|
||||||||||
// PodTemplateParams is a struct that contains the required data to create a podtemplatespec object | ||||||||||
type PodTemplateParams struct { | ||||||||||
ObjectMeta metav1.ObjectMeta | ||||||||||
// PodSecurityAdmissionPolicy is the policy to be respected by the created pod | ||||||||||
// The pod will be patched, if necessary, to respect the policies | ||||||||||
PodSecurityAdmissionPolicy psaapi.Policy | ||||||||||
} | ||||||||||
|
||||||||||
// GetPodTemplateSpec returns a pod template | ||||||||||
// The function: | ||||||||||
// - iterates through all container components, filters out init containers and gets corresponding containers | ||||||||||
// - gets the init container for every preStart devfile event | ||||||||||
// - patches the pod template and containers to satisfy PodSecurityAdmissionPolicy | ||||||||||
// - patches the pod template and containers to apply pod and container overrides | ||||||||||
func GetPodTemplateSpec(devfileObj parser.DevfileObj, podTemplateParams PodTemplateParams) (*corev1.PodTemplateSpec, error) { | ||||||||||
containers, err := GetContainers(devfileObj, common.DevfileOptions{}) | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMO, the GetContainers/GetInitContainers could be removed later from the library interface, by renaming them as getContainers/getInitContainers |
||||||||||
if err != nil { | ||||||||||
return nil, err | ||||||||||
} | ||||||||||
initContainers, err := GetInitContainers(devfileObj) | ||||||||||
if err != nil { | ||||||||||
return nil, err | ||||||||||
} | ||||||||||
|
||||||||||
podTemplateSpecParams := podTemplateSpecParams{ | ||||||||||
ObjectMeta: deployParams.ObjectMeta, | ||||||||||
InitContainers: deployParams.InitContainers, | ||||||||||
Containers: deployParams.Containers, | ||||||||||
Volumes: deployParams.Volumes, | ||||||||||
ObjectMeta: podTemplateParams.ObjectMeta, | ||||||||||
InitContainers: initContainers, | ||||||||||
Containers: containers, | ||||||||||
feloy marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
} | ||||||||||
var globalAttributes attributes.Attributes | ||||||||||
// attributes is not supported in versions less than 2.1.0, so we skip it | ||||||||||
|
@@ -199,29 +273,74 @@ func GetDeployment(devfileObj parser.DevfileObj, deployParams DeploymentParams) | |||||||||
if err != nil { | ||||||||||
return nil, err | ||||||||||
} | ||||||||||
podTemplateSpec, err := getPodTemplateSpec(globalAttributes, components, podTemplateSpecParams) | ||||||||||
|
||||||||||
podTemplateSpec, err := getPodTemplateSpec(podTemplateSpecParams) | ||||||||||
if err != nil { | ||||||||||
return nil, err | ||||||||||
} | ||||||||||
deploySpecParams := deploymentSpecParams{ | ||||||||||
PodTemplateSpec: *podTemplateSpec, | ||||||||||
PodSelectorLabels: deployParams.PodSelectorLabels, | ||||||||||
Replicas: deployParams.Replicas, | ||||||||||
|
||||||||||
podTemplateSpec, err = patchForPolicy(podTemplateSpec, podTemplateParams.PodSecurityAdmissionPolicy) | ||||||||||
if err != nil { | ||||||||||
return nil, err | ||||||||||
} | ||||||||||
|
||||||||||
containerAnnotations, err := getContainerAnnotations(devfileObj, common.DevfileOptions{}) | ||||||||||
if needsPodOverrides(globalAttributes, components) { | ||||||||||
patchedPodTemplateSpec, err := applyPodOverrides(globalAttributes, components, podTemplateSpec) | ||||||||||
if err != nil { | ||||||||||
return nil, err | ||||||||||
} | ||||||||||
patchedPodTemplateSpec.ObjectMeta = podTemplateSpecParams.ObjectMeta | ||||||||||
podTemplateSpec = patchedPodTemplateSpec | ||||||||||
} | ||||||||||
|
||||||||||
podTemplateSpec.Spec.Containers, err = applyContainerOverrides(devfileObj, podTemplateSpec.Spec.Containers) | ||||||||||
if err != nil { | ||||||||||
return nil, err | ||||||||||
} | ||||||||||
podTemplateSpec.Spec.InitContainers, err = applyContainerOverrides(devfileObj, podTemplateSpec.Spec.InitContainers) | ||||||||||
if err != nil { | ||||||||||
return nil, err | ||||||||||
} | ||||||||||
deployParams.ObjectMeta.Annotations = mergeMaps(deployParams.ObjectMeta.Annotations, containerAnnotations.Deployment) | ||||||||||
|
||||||||||
deployment := &appsv1.Deployment{ | ||||||||||
TypeMeta: deployParams.TypeMeta, | ||||||||||
ObjectMeta: deployParams.ObjectMeta, | ||||||||||
Spec: *getDeploymentSpec(deploySpecParams), | ||||||||||
return podTemplateSpec, nil | ||||||||||
} | ||||||||||
|
||||||||||
func applyContainerOverrides(devfileObj parser.DevfileObj, containers []corev1.Container) ([]corev1.Container, error) { | ||||||||||
containerComponents, err := devfileObj.Data.GetComponents(common.DevfileOptions{ | ||||||||||
ComponentOptions: common.ComponentOptions{ | ||||||||||
ComponentType: v1.ContainerComponentType, | ||||||||||
}, | ||||||||||
}) | ||||||||||
if err != nil { | ||||||||||
return nil, err | ||||||||||
} | ||||||||||
|
||||||||||
return deployment, nil | ||||||||||
getContainerByName := func(name string) (*corev1.Container, bool) { | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you do not need to introduce a new function for this purpose.
DevfileOptions.FilterByName = <the containerName>
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you sure? |
||||||||||
for _, container := range containers { | ||||||||||
if container.Name == name { | ||||||||||
return &container, true | ||||||||||
} | ||||||||||
} | ||||||||||
return nil, false | ||||||||||
} | ||||||||||
|
||||||||||
result := make([]corev1.Container, 0, len(containers)) | ||||||||||
for _, comp := range containerComponents { | ||||||||||
container, found := getContainerByName(comp.Name) | ||||||||||
if !found { | ||||||||||
continue | ||||||||||
} | ||||||||||
if comp.Attributes.Exists(ContainerOverridesAttribute) { | ||||||||||
patched, err := containerOverridesHandler(comp, container) | ||||||||||
if err != nil { | ||||||||||
return nil, err | ||||||||||
} | ||||||||||
result = append(result, *patched) | ||||||||||
} else { | ||||||||||
result = append(result, *container) | ||||||||||
} | ||||||||||
} | ||||||||||
return result, nil | ||||||||||
} | ||||||||||
|
||||||||||
// PVCParams is a struct to create PVC | ||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess we also need to update the Go version in
codecov.yml
? I can see that this workflow is not triggered on PRs, but only upon a push onmain
, which makes me think that this may no longer pass onmain
once this PR is merged.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, wondering if we should not update the version in
go.mod
to reflect this? This way, all calls to thesetup-go
action could simply use the version declared ingo.mod
(see https://github.com/actions/setup-go#getting-go-version-from-the-gomod-file). But I am not sure about the implications on consumers of the library if the Go version ingo.mod
is updated. This might be a different issue, that said..