2020-01-07 17:06:17 -08:00
package mutate
2019-05-21 18:27:56 +03:00
import (
2019-05-22 18:28:38 +01:00
"encoding/json"
2019-06-05 13:43:07 +03:00
"reflect"
2019-05-21 18:27:56 +03:00
"testing"
2019-05-22 22:34:25 +01:00
jsonpatch "github.com/evanphx/json-patch"
2020-01-07 17:06:17 -08:00
"github.com/nirmata/kyverno/pkg/engine/utils"
2019-05-21 18:27:56 +03:00
"gotest.tools/assert"
2020-03-17 16:25:34 -07:00
"sigs.k8s.io/controller-runtime/pkg/log"
2019-05-21 18:27:56 +03:00
)
2019-07-23 03:08:00 -04:00
func compareJSONAsMap ( t * testing . T , expected , actual [ ] byte ) {
2019-06-05 13:43:07 +03:00
var expectedMap , actualMap map [ string ] interface { }
assert . NilError ( t , json . Unmarshal ( expected , & expectedMap ) )
assert . NilError ( t , json . Unmarshal ( actual , & actualMap ) )
assert . Assert ( t , reflect . DeepEqual ( expectedMap , actualMap ) )
}
2019-07-26 17:52:26 -07:00
func TestProcessOverlayPatches_NestedListWithAnchor ( t * testing . T ) {
2019-05-23 17:31:34 +03:00
resourceRaw := [ ] byte ( `
{
"apiVersion" : "v1" ,
"kind" : "Endpoints" ,
"metadata" : {
"name" : "test-endpoint" ,
"labels" : {
"label" : "test"
}
} ,
"subsets" : [
{
"addresses" : [
{
"ip" : "192.168.10.171"
}
] ,
"ports" : [
{
"name" : "secure-connection" ,
"port" : 443 ,
"protocol" : "TCP"
}
]
}
]
} ` )
overlayRaw := [ ] byte ( `
{
"subsets" : [
{
"ports" : [
{
"(name)" : "secure-connection" ,
"port" : 444 ,
"protocol" : "UDP"
}
]
}
]
} ` )
2019-05-22 18:28:38 +01:00
2019-05-22 22:34:25 +01:00
var resource , overlay interface { }
2019-05-22 18:28:38 +01:00
2020-03-24 00:35:05 +05:30
err := json . Unmarshal ( resourceRaw , & resource )
assert . NilError ( t , err )
err = json . Unmarshal ( overlayRaw , & overlay )
assert . NilError ( t , err )
2019-05-22 18:28:38 +01:00
2020-03-17 16:25:34 -07:00
patches , overlayerr := processOverlayPatches ( log . Log , resource , overlay )
2019-11-06 16:16:38 -08:00
assert . Assert ( t , reflect . DeepEqual ( overlayerr , overlayError { } ) )
2019-05-22 22:34:25 +01:00
assert . Assert ( t , patches != nil )
2019-05-22 18:28:38 +01:00
2020-01-07 17:06:17 -08:00
patch := utils . JoinPatches ( patches )
2019-05-22 22:34:25 +01:00
decoded , err := jsonpatch . DecodePatch ( patch )
assert . NilError ( t , err )
assert . Assert ( t , decoded != nil )
patched , err := decoded . Apply ( resourceRaw )
assert . NilError ( t , err )
assert . Assert ( t , patched != nil )
2019-06-12 12:21:52 +03:00
expectedResult := [ ] byte ( `
{
"apiVersion" : "v1" ,
"kind" : "Endpoints" ,
"metadata" : {
"name" : "test-endpoint" ,
"labels" : {
"label" : "test"
}
} ,
"subsets" : [
{
"addresses" : [
{
"ip" : "192.168.10.171"
}
] ,
"ports" : [
{
"name" : "secure-connection" ,
"port" : 444.000000 ,
"protocol" : "UDP"
}
]
}
]
} ` )
2019-07-23 03:08:00 -04:00
compareJSONAsMap ( t , expectedResult , patched )
2019-05-22 22:34:25 +01:00
}
2019-07-26 17:52:26 -07:00
func TestProcessOverlayPatches_InsertIntoArray ( t * testing . T ) {
2019-05-23 17:31:34 +03:00
resourceRaw := [ ] byte ( `
{
"apiVersion" : "v1" ,
"kind" : "Endpoints" ,
"metadata" : {
"name" : "test-endpoint" ,
"labels" : {
"label" : "test"
}
} ,
"subsets" : [
{
"addresses" : [
{
"ip" : "192.168.10.171"
}
] ,
"ports" : [
{
"name" : "secure-connection" ,
"port" : 443 ,
"protocol" : "TCP"
}
]
}
]
} ` )
overlayRaw := [ ] byte ( `
{
"subsets" : [
{
"addresses" : [
{
"ip" : "192.168.10.172"
} ,
{
"ip" : "192.168.10.173"
}
] ,
"ports" : [
{
"name" : "insecure-connection" ,
"port" : 80 ,
"protocol" : "UDP"
}
]
}
]
} ` )
2019-05-22 22:34:25 +01:00
var resource , overlay interface { }
2020-03-24 00:35:05 +05:30
err := json . Unmarshal ( resourceRaw , & resource )
assert . NilError ( t , err )
err = json . Unmarshal ( overlayRaw , & overlay )
assert . NilError ( t , err )
2019-05-22 22:34:25 +01:00
2020-03-17 16:25:34 -07:00
patches , overlayerr := processOverlayPatches ( log . Log , resource , overlay )
2019-11-06 16:16:38 -08:00
assert . Assert ( t , reflect . DeepEqual ( overlayerr , overlayError { } ) )
2019-05-22 22:34:25 +01:00
assert . Assert ( t , patches != nil )
2020-01-07 17:06:17 -08:00
patch := utils . JoinPatches ( patches )
2019-05-22 22:34:25 +01:00
decoded , err := jsonpatch . DecodePatch ( patch )
assert . NilError ( t , err )
assert . Assert ( t , decoded != nil )
patched , err := decoded . Apply ( resourceRaw )
assert . NilError ( t , err )
assert . Assert ( t , patched != nil )
2019-06-12 12:21:52 +03:00
expectedResult := [ ] byte ( ` {
"apiVersion" : "v1" ,
"kind" : "Endpoints" ,
"metadata" : {
"name" : "test-endpoint" ,
"labels" : {
"label" : "test"
}
} ,
"subsets" : [
{
"addresses" : [
{
"ip" : "192.168.10.171"
}
] ,
"ports" : [
{
"name" : "secure-connection" ,
"port" : 443 ,
"protocol" : "TCP"
}
]
} ,
{
"addresses" : [
{
"ip" : "192.168.10.172"
} ,
{
"ip" : "192.168.10.173"
}
] ,
"ports" : [
{
"name" : "insecure-connection" ,
"port" : 80 ,
"protocol" : "UDP"
}
]
}
]
} ` )
2019-07-23 03:08:00 -04:00
compareJSONAsMap ( t , expectedResult , patched )
2019-05-21 18:27:56 +03:00
}
2019-05-23 16:31:00 +03:00
2019-07-26 17:52:26 -07:00
func TestProcessOverlayPatches_TestInsertToArray ( t * testing . T ) {
2019-05-23 17:31:34 +03:00
overlayRaw := [ ] byte ( `
{
"spec" : {
"template" : {
"spec" : {
"containers" : [
{
"name" : "pi1" ,
"image" : "vasylev.perl"
}
]
}
}
}
} ` )
resourceRaw := [ ] byte ( ` {
"apiVersion" : "batch/v1" ,
"kind" : "Job" ,
"metadata" : {
"name" : "pi"
} ,
"spec" : {
"template" : {
"spec" : {
"containers" : [
{
"name" : "piv0" ,
"image" : "perl" ,
"command" : [
"perl"
]
} ,
{
"name" : "pi" ,
"image" : "perl" ,
"command" : [
"perl"
]
} ,
{
"name" : "piv1" ,
"image" : "perl" ,
"command" : [
"perl"
]
}
] ,
"restartPolicy" : "Never"
}
} ,
"backoffLimit" : 4
}
} ` )
2019-05-23 16:31:00 +03:00
var resource , overlay interface { }
2020-03-24 00:35:05 +05:30
err := json . Unmarshal ( resourceRaw , & resource )
assert . NilError ( t , err )
err = json . Unmarshal ( overlayRaw , & overlay )
assert . NilError ( t , err )
2019-05-23 16:31:00 +03:00
2020-03-17 16:25:34 -07:00
patches , overlayerr := processOverlayPatches ( log . Log , resource , overlay )
2019-11-06 16:16:38 -08:00
assert . Assert ( t , reflect . DeepEqual ( overlayerr , overlayError { } ) )
2019-05-23 16:31:00 +03:00
assert . Assert ( t , patches != nil )
2020-01-07 17:06:17 -08:00
patch := utils . JoinPatches ( patches )
2019-05-23 16:31:00 +03:00
decoded , err := jsonpatch . DecodePatch ( patch )
assert . NilError ( t , err )
assert . Assert ( t , decoded != nil )
patched , err := decoded . Apply ( resourceRaw )
assert . NilError ( t , err )
assert . Assert ( t , patched != nil )
}
2019-06-05 15:02:58 +03:00
2019-07-26 17:52:26 -07:00
func TestProcessOverlayPatches_ImagePullPolicy ( t * testing . T ) {
2019-06-05 15:02:58 +03:00
overlayRaw := [ ] byte ( ` {
"spec" : {
"template" : {
"spec" : {
"containers" : [
{
"(image)" : "*:latest" ,
"imagePullPolicy" : "IfNotPresent" ,
"ports" : [
{
"containerPort" : 8080
}
]
}
]
}
}
}
} ` )
resourceRaw := [ ] byte ( ` {
"apiVersion" : "apps/v1" ,
"kind" : "Deployment" ,
"metadata" : {
"name" : "nginx-deployment" ,
"labels" : {
"app" : "nginx"
}
} ,
"spec" : {
"replicas" : 1 ,
"selector" : {
"matchLabels" : {
"app" : "nginx"
}
} ,
"template" : {
"metadata" : {
"labels" : {
"app" : "nginx"
}
} ,
"spec" : {
"containers" : [
{
"name" : "nginx" ,
"image" : "nginx:latest" ,
"ports" : [
{
"containerPort" : 80
}
]
} ,
{
"name" : "ghost" ,
"image" : "ghost:latest"
}
]
}
}
}
} ` )
var resource , overlay interface { }
2020-03-24 00:35:05 +05:30
err := json . Unmarshal ( resourceRaw , & resource )
assert . NilError ( t , err )
err = json . Unmarshal ( overlayRaw , & overlay )
assert . NilError ( t , err )
2019-06-05 15:02:58 +03:00
2020-03-17 16:25:34 -07:00
patches , overlayerr := processOverlayPatches ( log . Log , resource , overlay )
2019-11-06 16:16:38 -08:00
assert . Assert ( t , reflect . DeepEqual ( overlayerr , overlayError { } ) )
2019-06-05 15:02:58 +03:00
assert . Assert ( t , len ( patches ) != 0 )
2020-01-07 17:06:17 -08:00
doc , err := utils . ApplyPatches ( resourceRaw , patches )
2019-06-05 15:02:58 +03:00
assert . NilError ( t , err )
2019-06-12 12:21:52 +03:00
expectedResult := [ ] byte ( ` {
"apiVersion" : "apps/v1" ,
"kind" : "Deployment" ,
"metadata" : {
"name" : "nginx-deployment" ,
"labels" : {
"app" : "nginx"
}
} ,
"spec" : {
"replicas" : 1 ,
"selector" : {
"matchLabels" : {
"app" : "nginx"
}
} ,
"template" : {
"metadata" : {
"labels" : {
"app" : "nginx"
}
} ,
"spec" : {
"containers" : [
{
"image" : "nginx:latest" ,
"imagePullPolicy" : "IfNotPresent" ,
"name" : "nginx" ,
"ports" : [
{
"containerPort" : 80
} ,
{
"containerPort" : 8080
}
]
} ,
{
"image" : "ghost:latest" ,
"imagePullPolicy" : "IfNotPresent" ,
"name" : "ghost" ,
"ports" : [
{
"containerPort" : 8080
}
]
}
]
}
}
}
} ` )
2019-07-23 03:08:00 -04:00
compareJSONAsMap ( t , expectedResult , doc )
2019-07-26 17:52:26 -07:00
overlayRaw = [ ] byte ( ` {
"spec" : {
"template" : {
"metadata" : {
"labels" : {
"(app)" : "nginx"
}
} ,
"spec" : {
"containers" : [
{
"(image)" : "*:latest" ,
"imagePullPolicy" : "IfNotPresent" ,
"ports" : [
{
"containerPort" : 8080
}
]
}
]
}
}
}
} ` )
2020-03-24 00:35:05 +05:30
err = json . Unmarshal ( overlayRaw , & overlay )
assert . NilError ( t , err )
2019-07-26 17:52:26 -07:00
2020-03-17 16:25:34 -07:00
patches , err = processOverlayPatches ( log . Log , resource , overlay )
2019-11-06 16:16:38 -08:00
assert . Assert ( t , reflect . DeepEqual ( err , overlayError { } ) )
2019-07-26 17:52:26 -07:00
assert . Assert ( t , len ( patches ) != 0 )
2020-01-07 17:06:17 -08:00
doc , err = utils . ApplyPatches ( resourceRaw , patches )
2019-07-26 17:52:26 -07:00
assert . NilError ( t , err )
compareJSONAsMap ( t , expectedResult , doc )
overlayRaw = [ ] byte ( ` {
"spec" : {
"template" : {
"metadata" : {
"labels" : {
"(app)" : "nginx1"
}
} ,
"spec" : {
"containers" : [
{
"(image)" : "*:latest" ,
"imagePullPolicy" : "IfNotPresent" ,
"ports" : [
{
"containerPort" : 8080
}
]
}
]
}
}
}
} ` )
2020-03-24 00:35:05 +05:30
err = json . Unmarshal ( overlayRaw , & overlay )
assert . NilError ( t , err )
2019-07-26 17:52:26 -07:00
2020-03-17 16:25:34 -07:00
patches , err = processOverlayPatches ( log . Log , resource , overlay )
2019-12-10 09:15:50 -08:00
assert . Error ( t , err , "[overlayError:0] Policy not applied, conditions are not met at /spec/template/metadata/labels/app/, [overlayError:0] Failed validating value nginx with overlay nginx1" )
2019-07-26 17:52:26 -07:00
assert . Assert ( t , len ( patches ) == 0 )
2019-06-05 15:02:58 +03:00
}
2019-06-14 17:19:32 +03:00
2019-07-26 17:52:26 -07:00
func TestProcessOverlayPatches_AddingAnchor ( t * testing . T ) {
2019-06-14 17:19:32 +03:00
overlayRaw := [ ] byte ( ` {
"metadata" : {
"name" : "nginx-deployment" ,
"labels" : {
"+(app)" : "should-not-be-here" ,
"+(key1)" : "value1"
}
}
} ` )
resourceRaw := [ ] byte ( ` {
"metadata" : {
"name" : "nginx-deployment" ,
"labels" : {
"app" : "nginx"
}
}
} ` )
var resource , overlay interface { }
2020-03-24 00:35:05 +05:30
err := json . Unmarshal ( resourceRaw , & resource )
assert . NilError ( t , err )
err = json . Unmarshal ( overlayRaw , & overlay )
assert . NilError ( t , err )
2019-06-14 17:19:32 +03:00
2020-03-17 16:25:34 -07:00
patches , overlayerr := processOverlayPatches ( log . Log , resource , overlay )
2019-11-06 16:16:38 -08:00
assert . Assert ( t , reflect . DeepEqual ( overlayerr , overlayError { } ) )
2019-06-14 17:19:32 +03:00
assert . Assert ( t , len ( patches ) != 0 )
2020-01-07 17:06:17 -08:00
doc , err := utils . ApplyPatches ( resourceRaw , patches )
2019-06-14 17:19:32 +03:00
assert . NilError ( t , err )
expectedResult := [ ] byte ( ` {
"metadata" : {
"labels" : {
"app" : "nginx" ,
"key1" : "value1"
} ,
"name" : "nginx-deployment"
}
} ` )
2019-07-23 03:08:00 -04:00
compareJSONAsMap ( t , expectedResult , doc )
2019-06-14 17:19:32 +03:00
}
2019-06-18 13:51:36 +03:00
2019-07-26 17:52:26 -07:00
func TestProcessOverlayPatches_AddingAnchorInsideListElement ( t * testing . T ) {
2019-06-18 13:51:36 +03:00
overlayRaw := [ ] byte ( `
{
2019-06-18 15:02:41 +03:00
"spec" : {
"template" : {
"spec" : {
"containers" : [
{
"(image)" : "*:latest" ,
"+(imagePullPolicy)" : "IfNotPresent"
}
]
}
2019-06-18 13:51:36 +03:00
}
2019-06-18 15:02:41 +03:00
}
2019-06-18 13:51:36 +03:00
} ` )
resourceRaw := [ ] byte ( `
2019-06-18 15:02:41 +03:00
{
"apiVersion" : "apps/v1" ,
"kind" : "Deployment" ,
"metadata" : {
"name" : "nginx-deployment" ,
"labels" : {
"app" : "nginx"
}
} ,
"spec" : {
"replicas" : 1 ,
"selector" : {
"matchLabels" : {
"app" : "nginx"
}
2019-06-18 13:51:36 +03:00
} ,
2019-06-18 15:02:41 +03:00
"template" : {
"metadata" : {
"labels" : {
"app" : "nginx"
}
} ,
"spec" : {
"containers" : [
{
"image" : "nginx:latest"
} ,
{
"image" : "ghost:latest" ,
"imagePullPolicy" : "Always"
} ,
{
2019-10-31 20:38:24 -07:00
"image" : "debian:latest"
2019-06-18 15:02:41 +03:00
} ,
{
2019-10-31 20:38:24 -07:00
"image" : "ubuntu:latest" ,
2019-06-18 15:02:41 +03:00
"imagePullPolicy" : "Always"
}
]
}
2019-06-18 13:51:36 +03:00
}
2019-06-18 15:02:41 +03:00
}
2019-06-18 13:51:36 +03:00
} ` )
var resource , overlay interface { }
2020-03-24 00:35:05 +05:30
err := json . Unmarshal ( resourceRaw , & resource )
assert . NilError ( t , err )
err = json . Unmarshal ( overlayRaw , & overlay )
assert . NilError ( t , err )
2019-06-18 13:51:36 +03:00
2020-03-17 16:25:34 -07:00
patches , overlayerr := processOverlayPatches ( log . Log , resource , overlay )
2019-11-06 16:16:38 -08:00
assert . Assert ( t , reflect . DeepEqual ( overlayerr , overlayError { } ) )
2019-06-18 13:51:36 +03:00
assert . Assert ( t , len ( patches ) != 0 )
2020-01-07 17:06:17 -08:00
doc , err := utils . ApplyPatches ( resourceRaw , patches )
2019-06-18 13:51:36 +03:00
assert . NilError ( t , err )
expectedResult := [ ] byte ( `
2019-06-18 15:02:41 +03:00
{
"apiVersion" : "apps/v1" ,
"kind" : "Deployment" ,
"metadata" : {
"name" : "nginx-deployment" ,
"labels" : {
"app" : "nginx"
}
} ,
"spec" : {
"replicas" : 1 ,
"selector" : {
"matchLabels" : {
"app" : "nginx"
}
} ,
"template" : {
"metadata" : {
"labels" : {
"app" : "nginx"
}
} ,
"spec" : {
"containers" : [
{
"image" : "nginx:latest" ,
"imagePullPolicy" : "IfNotPresent"
} ,
{
"image" : "ghost:latest" ,
"imagePullPolicy" : "Always"
} ,
{
2019-10-31 20:38:24 -07:00
"image" : "debian:latest" ,
"imagePullPolicy" : "IfNotPresent"
2019-06-18 15:02:41 +03:00
} ,
{
2019-10-31 20:38:24 -07:00
"image" : "ubuntu:latest" ,
2019-06-18 15:02:41 +03:00
"imagePullPolicy" : "Always"
}
]
}
}
}
} ` )
2019-07-23 03:08:00 -04:00
compareJSONAsMap ( t , expectedResult , doc )
2019-07-26 17:52:26 -07:00
// multiple anchors
overlayRaw = [ ] byte ( `
{
"spec" : {
"template" : {
"metadata" : {
"labels" : {
"(app)" : "nginx"
}
} ,
"spec" : {
"containers" : [
{
"(image)" : "*:latest" ,
"+(imagePullPolicy)" : "IfNotPresent"
}
]
}
}
}
} ` )
2020-03-24 00:35:05 +05:30
err = json . Unmarshal ( overlayRaw , & overlay )
assert . NilError ( t , err )
2019-07-26 17:52:26 -07:00
2020-03-17 16:25:34 -07:00
patches , err = processOverlayPatches ( log . Log , resource , overlay )
2019-11-06 16:16:38 -08:00
assert . Assert ( t , reflect . DeepEqual ( err , overlayError { } ) )
2019-07-26 17:52:26 -07:00
assert . Assert ( t , len ( patches ) != 0 )
2020-01-07 17:06:17 -08:00
doc , err = utils . ApplyPatches ( resourceRaw , patches )
2019-07-26 17:52:26 -07:00
assert . NilError ( t , err )
compareJSONAsMap ( t , expectedResult , doc )
}
func TestProcessOverlayPatches_anchorOnPeer ( t * testing . T ) {
resourceRaw := [ ] byte ( `
{
"apiVersion" : "v1" ,
"kind" : "Endpoints" ,
"metadata" : {
"name" : "test-endpoint" ,
"labels" : {
"label" : "test"
}
} ,
"subsets" : [
{
"addresses" : [
{
"ip" : "192.168.10.171"
}
] ,
"ports" : [
{
"name" : "secure-connection" ,
"port" : 443 ,
"protocol" : "TCP"
}
]
}
]
} ` )
overlayRaw := [ ] byte ( `
{
"subsets" : [
{
"addresses" : [
{
"(ip)" : "192.168.10.171"
}
] ,
"ports" : [
{
"(name)" : "secure-connection" ,
"port" : 444 ,
"protocol" : "UDP"
}
]
}
]
} ` )
var resource , overlay interface { }
2020-03-24 00:35:05 +05:30
err := json . Unmarshal ( resourceRaw , & resource )
assert . NilError ( t , err )
err = json . Unmarshal ( overlayRaw , & overlay )
assert . NilError ( t , err )
2019-07-26 17:52:26 -07:00
2020-03-17 16:25:34 -07:00
patches , overlayerr := processOverlayPatches ( log . Log , resource , overlay )
2019-11-06 16:16:38 -08:00
assert . Assert ( t , reflect . DeepEqual ( overlayerr , overlayError { } ) )
2019-07-26 17:52:26 -07:00
assert . Assert ( t , len ( patches ) != 0 )
2020-01-07 17:06:17 -08:00
doc , err := utils . ApplyPatches ( resourceRaw , patches )
2019-07-26 17:52:26 -07:00
assert . NilError ( t , err )
expectedResult := [ ] byte ( ` {
"apiVersion" : "v1" ,
"kind" : "Endpoints" ,
"metadata" : {
"name" : "test-endpoint" ,
"labels" : {
"label" : "test"
}
} ,
"subsets" : [
{
"addresses" : [
{
"ip" : "192.168.10.171"
}
] ,
"ports" : [
{
"name" : "secure-connection" ,
"port" : 444 ,
"protocol" : "UDP"
}
]
}
]
} ` )
compareJSONAsMap ( t , expectedResult , doc )
overlayRaw = [ ] byte ( `
{
"subsets" : [
{
"addresses" : [
{
"ip" : "192.168.10.171"
}
] ,
"ports" : [
{
"(name)" : "secure-connection" ,
"(port)" : 444 ,
"protocol" : "UDP"
}
]
}
]
} ` )
2020-03-24 00:35:05 +05:30
err = json . Unmarshal ( overlayRaw , & overlay )
assert . NilError ( t , err )
2019-07-26 17:52:26 -07:00
2020-03-17 16:25:34 -07:00
patches , err = processOverlayPatches ( log . Log , resource , overlay )
2019-12-10 09:15:50 -08:00
assert . Error ( t , err , "[overlayError:0] Policy not applied, conditions are not met at /subsets/0/ports/0/port/, [overlayError:0] Failed validating value 443 with overlay 444" )
2019-07-26 17:52:26 -07:00
assert . Assert ( t , len ( patches ) == 0 )
2019-06-18 13:51:36 +03:00
}
2019-07-26 18:27:59 -07:00
func TestProcessOverlayPatches_insertWithCondition ( t * testing . T ) {
resourceRaw := [ ] byte ( ` {
"apiVersion" : "apps/v1" ,
"kind" : "Deployment" ,
"metadata" : {
"name" : "psp-demo-unprivileged" ,
"labels" : {
"app.type" : "prod"
}
} ,
"spec" : {
"replicas" : 1 ,
"selector" : {
"matchLabels" : {
"app" : "psp"
}
} ,
"template" : {
"metadata" : {
"labels" : {
"app" : "psp"
}
} ,
"spec" : {
"securityContext" : {
"runAsNonRoot" : true
} ,
"containers" : [
{
"name" : "sec-ctx-unprivileged" ,
"image" : "nginxinc/nginx-unprivileged" ,
"securityContext" : {
"runAsNonRoot" : true ,
"allowPrivilegeEscalation" : false
} ,
"env" : [
{
"name" : "ENV_KEY" ,
"value" : "ENV_VALUE"
}
]
}
]
}
}
}
} ` )
overlayRaw := [ ] byte ( ` {
"spec" : {
"template" : {
"spec" : {
"containers" : [
{
"(image)" : "*/nginx-unprivileged" ,
"securityContext" : {
"(runAsNonRoot)" : true ,
"allowPrivilegeEscalation" : true
} ,
"env" : [
{
"name" : "ENV_NEW_KEY" ,
"value" : "ENV_NEW_VALUE"
}
]
}
]
}
}
}
} ` )
var resource , overlay interface { }
2020-03-24 00:35:05 +05:30
err := json . Unmarshal ( resourceRaw , & resource )
assert . NilError ( t , err )
err = json . Unmarshal ( overlayRaw , & overlay )
assert . NilError ( t , err )
2019-07-26 18:27:59 -07:00
2020-03-17 16:25:34 -07:00
patches , overlayerr := processOverlayPatches ( log . Log , resource , overlay )
2019-11-06 16:16:38 -08:00
assert . Assert ( t , reflect . DeepEqual ( overlayerr , overlayError { } ) )
2019-07-26 18:27:59 -07:00
assert . Assert ( t , len ( patches ) != 0 )
2020-01-07 17:06:17 -08:00
doc , err := utils . ApplyPatches ( resourceRaw , patches )
2019-07-26 18:27:59 -07:00
assert . NilError ( t , err )
expectedResult := [ ] byte ( ` {
"apiVersion" : "apps/v1" ,
"kind" : "Deployment" ,
"metadata" : {
"name" : "psp-demo-unprivileged" ,
"labels" : {
"app.type" : "prod"
}
} ,
"spec" : {
"replicas" : 1 ,
"selector" : {
"matchLabels" : {
"app" : "psp"
}
} ,
"template" : {
"metadata" : {
"labels" : {
"app" : "psp"
}
} ,
"spec" : {
"securityContext" : {
"runAsNonRoot" : true
} ,
"containers" : [
{
"name" : "sec-ctx-unprivileged" ,
"image" : "nginxinc/nginx-unprivileged" ,
"securityContext" : {
"runAsNonRoot" : true ,
"allowPrivilegeEscalation" : true
} ,
"env" : [
{
"name" : "ENV_KEY" ,
"value" : "ENV_VALUE"
} ,
{
"name" : "ENV_NEW_KEY" ,
"value" : "ENV_NEW_VALUE"
}
]
}
]
}
}
}
} ` )
compareJSONAsMap ( t , expectedResult , doc )
}
2019-11-05 10:16:07 -08:00
func TestProcessOverlayPatches_InsertIfNotPresentWithConditions ( t * testing . T ) {
overlayRaw := [ ] byte ( `
{
"metadata" : {
"annotations" : {
"+(cluster-autoscaler.kubernetes.io/safe-to-evict)" : true
}
} ,
"spec" : {
"volumes" : [
{
"(emptyDir)" : { }
}
]
}
} ` )
resourceRaw := [ ] byte ( `
{
"apiVersion" : "v1" ,
"kind" : "Pod" ,
"metadata" : {
"name" : "pod-with-emptydir"
} ,
"spec" : {
"containers" : [
{
"image" : "k8s.gcr.io/test-webserver" ,
"name" : "test-container" ,
"volumeMounts" : [
{
"mountPath" : "/cache" ,
"name" : "cache-volume"
}
]
}
] ,
"volumes" : [
{
"name" : "cache-volume" ,
"emptyDir" : { }
}
]
}
} ` )
var resource , overlay interface { }
2020-03-24 00:35:05 +05:30
err := json . Unmarshal ( resourceRaw , & resource )
assert . NilError ( t , err )
err = json . Unmarshal ( overlayRaw , & overlay )
assert . NilError ( t , err )
2019-11-05 10:16:07 -08:00
2020-03-17 16:25:34 -07:00
patches , overlayerr := processOverlayPatches ( log . Log , resource , overlay )
2019-11-06 16:16:38 -08:00
assert . Assert ( t , reflect . DeepEqual ( overlayerr , overlayError { } ) )
2019-11-05 10:16:07 -08:00
assert . Assert ( t , len ( patches ) != 0 )
2020-01-07 17:06:17 -08:00
doc , err := utils . ApplyPatches ( resourceRaw , patches )
2019-11-05 10:16:07 -08:00
assert . NilError ( t , err )
expectedResult := [ ] byte ( `
{
"apiVersion" : "v1" ,
"kind" : "Pod" ,
"metadata" : {
"name" : "pod-with-emptydir" ,
"annotations" : {
2019-12-13 18:04:19 -08:00
"cluster-autoscaler.kubernetes.io/safe-to-evict" : "true"
2019-11-05 10:16:07 -08:00
}
} ,
"spec" : {
"containers" : [
{
"image" : "k8s.gcr.io/test-webserver" ,
"name" : "test-container" ,
"volumeMounts" : [
{
"mountPath" : "/cache" ,
"name" : "cache-volume"
}
]
}
] ,
"volumes" : [
{
"name" : "cache-volume" ,
"emptyDir" : { }
}
]
}
} ` )
2019-12-27 12:57:06 -08:00
t . Log ( string ( doc ) )
2019-11-05 10:16:07 -08:00
compareJSONAsMap ( t , expectedResult , doc )
}
2019-12-27 12:57:06 -08:00
func Test_wrapBoolean ( t * testing . T ) {
tests := [ ] struct {
test string
expected string
} {
{
test : ` { "op": "add", "path": "/metadata/annotations", "value": { "cluster-autoscaler.kubernetes.io/safe-to-evict":true} } ` ,
expected : ` { "op": "add", "path": "/metadata/annotations", "value": { "cluster-autoscaler.kubernetes.io/safe-to-evict":"true"} } ` ,
} ,
{
test : ` { "op": "add", "path": "/metadata/annotations", "value": { "cluster-autoscaler.kubernetes.io/safe-to-evict": true} } ` ,
expected : ` { "op": "add", "path": "/metadata/annotations", "value": { "cluster-autoscaler.kubernetes.io/safe-to-evict":"true"} } ` ,
} ,
{
test : ` { "op": "add", "path": "/metadata/annotations", "value": { "cluster-autoscaler.kubernetes.io/safe-to-evict": false } } ` ,
expected : ` { "op": "add", "path": "/metadata/annotations", "value": { "cluster-autoscaler.kubernetes.io/safe-to-evict":"false"} } ` ,
} ,
{
test : ` { "op": "add", "path": "/metadata/annotations/cluster-autoscaler.kubernetes.io~1safe-to-evict", "value": false } ` ,
expected : ` { "op": "add", "path": "/metadata/annotations/cluster-autoscaler.kubernetes.io~1safe-to-evict", "value":"false"} ` ,
} ,
}
for _ , testcase := range tests {
out := wrapBoolean ( testcase . test )
t . Log ( out )
assert . Assert ( t , testcase . expected == out )
}
}
2019-12-27 13:04:07 -08:00
2019-12-16 18:26:38 -08:00
func TestApplyOverlay_ConditionOnArray ( t * testing . T ) {
resourceRaw := [ ] byte ( `
{
"apiVersion" : "v1" ,
"kind" : "Pod" ,
"metadata" : {
"name" : "myapp-pod" ,
"labels" : {
"app" : "myapp" ,
"dedicated" : "spark"
}
} ,
"spec" : {
"containers" : [
{
"name" : "myapp-container" ,
"image" : "busybox" ,
"command" : [
"sh" ,
"-c" ,
"echo Hello Kubernetes! && sleep 3600"
]
}
] ,
"affinity" : {
"nodeAffinity" : {
"a" : {
"b" : [
{
"matchExpressions" : [
{
"key" : "dedicated" ,
"operator" : "NotIn" ,
"values" : [
"spark"
]
}
]
}
]
}
}
}
}
}
` )
overlayRaw := [ ] byte ( `
{
"spec" : {
"affinity" : {
"nodeAffinity" : {
"a" : {
"b" : [
{
"matchExpressions" : [
{
"(key)" : "dedicated" ,
"operator" : "In" ,
"(values)" : [
"spark"
]
}
]
}
]
}
}
}
}
}
` )
var resource , overlay interface { }
assert . NilError ( t , json . Unmarshal ( resourceRaw , & resource ) )
assert . NilError ( t , json . Unmarshal ( overlayRaw , & overlay ) )
expectedPatches := [ ] byte ( ` [
2019-12-27 13:04:07 -08:00
{ "op" : "replace" , "path" : "/spec/affinity/nodeAffinity/a/b/0/matchExpressions/0/operator" , "value" : "In" }
2019-12-16 18:26:38 -08:00
] ` )
p , err := applyOverlay ( resource , overlay , "/" )
assert . NilError ( t , err )
2020-01-07 17:06:17 -08:00
assert . Assert ( t , string ( utils . JoinPatches ( p ) ) == string ( expectedPatches ) )
2019-12-16 18:26:38 -08:00
}