@@ -17,7 +17,10 @@ limitations under the License.
1717package kustomize_test
1818
1919import (
20+ "context"
2021 "fmt"
22+ "net/http"
23+ "net/http/httptest"
2124 "os"
2225 "path/filepath"
2326 "strings"
@@ -26,6 +29,7 @@ import (
2629 . "github.com/onsi/gomega"
2730 "github.com/otiai10/copy"
2831 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
32+ "sigs.k8s.io/controller-runtime/pkg/client"
2933 "sigs.k8s.io/kustomize/api/resmap"
3034 kustypes "sigs.k8s.io/kustomize/api/types"
3135 "sigs.k8s.io/kustomize/kyaml/filesys"
@@ -741,3 +745,143 @@ func TestOpenAPIPollution(t *testing.T) {
741745 g .Expect (string (yaml2 )).To (ContainSubstring ("memory: 64Mi" ))
742746 })
743747}
748+
749+ func TestOpenAPIPathMergesBuiltins (t * testing.T ) {
750+ g := NewWithT (t )
751+
752+ tmpDir , err := testTempDir (t )
753+ g .Expect (err ).ToNot (HaveOccurred ())
754+ writeOpenAPIPathDaemonSetFixture (g , tmpDir , "custom-openapi.json" )
755+
756+ res , err := kustomize .SecureBuild (tmpDir , tmpDir , false )
757+ g .Expect (err ).ToNot (HaveOccurred ())
758+ g .Expect (res .Resources ()).To (HaveLen (1 ))
759+
760+ expectOpenAPIPathDaemonSet (g , res )
761+ }
762+
763+ func TestOpenAPIPathHTTPURLMergesBuiltins (t * testing.T ) {
764+ g := NewWithT (t )
765+
766+ server := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
767+ g .Expect (r .URL .Path ).To (Equal ("/custom-openapi.json" ))
768+ w .Header ().Set ("Content-Type" , "application/json" )
769+ _ , err := w .Write ([]byte (customOpenAPISchema ))
770+ g .Expect (err ).ToNot (HaveOccurred ())
771+ }))
772+ defer server .Close ()
773+
774+ tmpDir , err := testTempDir (t )
775+ g .Expect (err ).ToNot (HaveOccurred ())
776+ writeOpenAPIPathDaemonSetFixture (g , tmpDir , server .URL + "/custom-openapi.json" )
777+
778+ res , err := kustomize .SecureBuild (tmpDir , tmpDir , false )
779+ g .Expect (err ).ToNot (HaveOccurred ())
780+ g .Expect (res .Resources ()).To (HaveLen (1 ))
781+
782+ expectOpenAPIPathDaemonSet (g , res )
783+ }
784+
785+ func expectOpenAPIPathDaemonSet (g Gomega , res resmap.ResMap ) {
786+ out , err := res .AsYaml ()
787+ g .Expect (err ).ToNot (HaveOccurred ())
788+ obj := daemonSetObject (g , out )
789+ container := daemonSetContainer (g , obj .Object )
790+ image , found , err := unstructured .NestedString (container , "image" )
791+ g .Expect (err ).ToNot (HaveOccurred ())
792+ g .Expect (found ).To (BeTrue ())
793+ g .Expect (image ).To (Equal ("quay.io/prometheus/node-exporter:v1.10.2" ))
794+
795+ volumeMounts , foundVolumeMounts , err := unstructured .NestedSlice (container , "volumeMounts" )
796+ g .Expect (err ).ToNot (HaveOccurred ())
797+ g .Expect (foundVolumeMounts ).To (BeTrue ())
798+ g .Expect (volumeMounts ).To (BeEmpty ())
799+
800+ g .Expect (kubeClient .Create (context .Background (), obj , client .DryRunAll )).To (Succeed ())
801+ }
802+
803+ func daemonSetObject (g Gomega , data []byte ) * unstructured.Unstructured {
804+ var obj map [string ]interface {}
805+ g .Expect (yaml .Unmarshal (data , & obj )).To (Succeed ())
806+ u := & unstructured.Unstructured {Object : obj }
807+ u .SetNamespace ("default" )
808+ return u
809+ }
810+
811+ func daemonSetContainer (g Gomega , obj map [string ]interface {}) map [string ]interface {} {
812+ containers , found , err := unstructured .NestedSlice (obj , "spec" , "template" , "spec" , "containers" )
813+ g .Expect (err ).ToNot (HaveOccurred ())
814+ g .Expect (found ).To (BeTrue ())
815+ g .Expect (containers ).To (HaveLen (1 ))
816+ container , ok := containers [0 ].(map [string ]interface {})
817+ g .Expect (ok ).To (BeTrue ())
818+ return container
819+ }
820+
821+ func writeOpenAPIPathDaemonSetFixture (g Gomega , dir , openAPIPath string ) {
822+ files := map [string ]string {
823+ "kustomization.yaml" : fmt .Sprintf (`resources:
824+ - daemonset.yaml
825+ openapi:
826+ path: %s
827+ patches:
828+ - patch: |-
829+ apiVersion: apps/v1
830+ kind: DaemonSet
831+ metadata:
832+ name: monitoring-prometheus-node-exporter
833+ spec:
834+ template:
835+ spec:
836+ containers:
837+ - name: node-exporter
838+ volumeMounts:
839+ - name: root
840+ mountPropagation: None
841+ target:
842+ group: apps
843+ kind: DaemonSet
844+ name: monitoring-prometheus-node-exporter
845+ ` , openAPIPath ),
846+ "custom-openapi.json" : customOpenAPISchema ,
847+ "daemonset.yaml" : `apiVersion: apps/v1
848+ kind: DaemonSet
849+ metadata:
850+ name: monitoring-prometheus-node-exporter
851+ spec:
852+ selector:
853+ matchLabels:
854+ app: node-exporter
855+ template:
856+ metadata:
857+ labels:
858+ app: node-exporter
859+ spec:
860+ containers:
861+ - name: node-exporter
862+ image: quay.io/prometheus/node-exporter:v1.10.2
863+ volumeMounts:
864+ - name: root
865+ mountPath: /host/root
866+ volumes:
867+ - name: root
868+ hostPath:
869+ path: /
870+ ` ,
871+ }
872+
873+ for name , content := range files {
874+ g .Expect (os .WriteFile (filepath .Join (dir , name ), []byte (content ), 0o644 )).To (Succeed ())
875+ }
876+ }
877+
878+ const customOpenAPISchema = `{
879+ "swagger": "2.0",
880+ "info": {
881+ "title": "Custom schema",
882+ "version": "v1"
883+ },
884+ "paths": {},
885+ "definitions": {}
886+ }
887+ `
0 commit comments