11package main
22
33import (
4- "encoding/json "
4+ "bytes "
55 "fmt"
6+ "github.com/pkg/errors"
7+ "io"
8+ "io/ioutil"
69 "os"
710
8- "github.com/go-yaml/yaml"
9- kingpin "gopkg.in/alecthomas/kingpin.v2"
11+ "gopkg.in/alecthomas/kingpin.v2"
1012 "k8s.io/api/apps/v1beta1"
11- v1 "k8s.io/api/core/v1"
13+ "k8s.io/api/core/v1"
1214 "k8s.io/apimachinery/pkg/api/resource"
1315 k8sjson "k8s.io/apimachinery/pkg/runtime/serializer/json"
1416 k8syaml "k8s.io/apimachinery/pkg/util/yaml"
@@ -29,68 +31,41 @@ var (
2931
3032func main () {
3133 kingpin .Parse ()
34+ runInjector ()
35+ }
3236
33- var cloudSQLProxyContainer v1.Container
34- {
35- requestResources , limitResources := setResources (* cpuRequest , * memoryRequest , * cpuLimit , * memoryLimit )
36-
37- var runAsUser int64 = 2
38- var allowPrivilegeEscalation = false
39-
40- securityContext := v1.SecurityContext {
41- RunAsUser : & runAsUser ,
42- AllowPrivilegeEscalation : & allowPrivilegeEscalation ,
43- }
44-
45- volumeMount := v1.VolumeMount {
46- Name : "cloudsql-proxy-credentials" ,
47- MountPath : "/secrets/cloudsql" ,
48- ReadOnly : true ,
49- }
50-
51- cloudSQLProxyContainer = v1.Container {}
52- cloudSQLProxyContainer .Name = "cloudsql-proxy"
53- cloudSQLProxyContainer .Image = fmt .Sprintf ("gcr.io/cloudsql-docker/gce-proxy:%s" , * proxyVersion )
54- cloudSQLProxyContainer .Command = []string {"/cloud_sql_proxy" , fmt .Sprintf ("-instances=%s:%s:%s" , * project , * region , * instance ), "-log_debug_stdout=true" , fmt .Sprintf ("-verbose=%s" , * verbose ), "-credential_file=/secrets/cloudsql/credentials.json" }
55- cloudSQLProxyContainer .Resources = v1.ResourceRequirements {Requests : requestResources , Limits : limitResources }
56- cloudSQLProxyContainer .SecurityContext = & securityContext
57- cloudSQLProxyContainer .VolumeMounts = []v1.VolumeMount {volumeMount }
58- }
59-
60- b , err := yaml .Marshal (& cloudSQLProxyContainer )
61- if err != nil {
62- panic (err )
63- }
64- f , err := os .Open (* path )
65- if err != nil {
66- panic (err )
67- }
68- defer f .Close ()
37+ func runInjector () {
38+ cloudSQLProxyContainer := getCloudContainer ()
6939
70- b , err = json .Marshal (& cloudSQLProxyContainer )
71- if err != nil {
72- panic (err )
73- }
40+ // split the file bytes by resources
41+ // a file may contains multiple resources, separated by "---"
42+ allK8SResources := getAllResourcesBytes (* path )
43+ // separate deployment from others resources
44+ deploymentBytes , otherResources := extractDeploymentBytes (allK8SResources )
7445
75- deploy := & v1beta1.Deployment {}
76- err = json . Unmarshal ( b , & deploy )
46+ deploy := v1beta1.Deployment {}
47+ err := k8syaml . NewYAMLOrJSONDecoder ( bytes . NewReader ( deploymentBytes ), 4096 ). Decode ( & deploy )
7748 if err != nil {
7849 panic (err )
7950 }
80- k8syaml .NewYAMLOrJSONDecoder (f , 4096 ).Decode (& deploy )
8151
82- deploy .Spec .Template .Spec .Volumes = []v1. Volume { v1.Volume {
52+ deploy .Spec .Template .Spec .Volumes = append ( deploy . Spec . Template . Spec . Volumes , v1.Volume {
8353 Name : "cloudsql-proxy-credentials" ,
8454 VolumeSource : v1.VolumeSource {
8555 Secret : & v1.SecretVolumeSource {
8656 SecretName : "cloudsql-proxy-credentials" ,
8757 },
8858 },
89- }}
59+ })
9060 deploy .Spec .Template .Spec .Containers = append (deploy .Spec .Template .Spec .Containers , cloudSQLProxyContainer )
9161
9262 serializer := k8sjson .NewYAMLSerializer (k8sjson .DefaultMetaFactory , nil , nil )
93- serializer .Encode (deploy , os .Stdout )
63+
64+ outputBytes := bytes .NewBuffer (nil )
65+ serializer .Encode (& deploy , outputBytes )
66+ putItBack (otherResources , outputBytes )
67+
68+ os .Stdout .Write (outputBytes .Bytes ())
9469}
9570
9671func setResources (cpuRequest , memoryRequest , cpuLimit , memoryLimit string ) (request v1.ResourceList , limit v1.ResourceList ) {
@@ -123,3 +98,86 @@ func setResources(cpuRequest, memoryRequest, cpuLimit, memoryLimit string) (requ
12398
12499 return request , limit
125100}
101+
102+ func getAllResourcesBytes (filepath string ) [][]byte {
103+ f , err := os .Open (filepath )
104+ if err != nil {
105+ panic (err )
106+ }
107+ defer f .Close ()
108+
109+ fileBytes , err := ioutil .ReadAll (f )
110+ if err != nil {
111+ panic (err )
112+ }
113+
114+ return bytes .Split (fileBytes , []byte ("\n ---" ))
115+ }
116+
117+ func extractDeploymentBytes (allK8SResources [][]byte ) (deploymentBytes []byte , otherResources [][]byte ) {
118+ // find the deployment in the list of resources
119+ for _ , resourceBytes := range allK8SResources {
120+ // Because interpreter read only JSON...
121+ resourceJSON , err := k8syaml .ToJSON (resourceBytes )
122+ if err != nil {
123+ panic (err )
124+ }
125+ schema , err := k8sjson .DefaultMetaFactory .Interpret (resourceJSON )
126+ if err != nil {
127+ panic (err )
128+ }
129+
130+ // Is this a deployment or something else
131+ if schema .Kind == "Deployment" {
132+ deploymentBytes = resourceBytes
133+ } else {
134+ otherResources = append (otherResources , resourceBytes )
135+ }
136+ }
137+
138+ if len (deploymentBytes ) <= 0 {
139+ panic (errors .New ("could not find deployment resource in given file" ))
140+ }
141+
142+ return deploymentBytes , otherResources
143+ }
144+
145+ func getCloudContainer () v1.Container {
146+ var cloudSQLProxyContainer v1.Container
147+ {
148+ requestResources , limitResources := setResources (* cpuRequest , * memoryRequest , * cpuLimit , * memoryLimit )
149+
150+ var runAsUser int64 = 2
151+ var allowPrivilegeEscalation = false
152+
153+ securityContext := v1.SecurityContext {
154+ RunAsUser : & runAsUser ,
155+ AllowPrivilegeEscalation : & allowPrivilegeEscalation ,
156+ }
157+
158+ volumeMount := v1.VolumeMount {
159+ Name : "cloudsql-proxy-credentials" ,
160+ MountPath : "/secrets/cloudsql" ,
161+ ReadOnly : true ,
162+ }
163+
164+ cloudSQLProxyContainer = v1.Container {}
165+ cloudSQLProxyContainer .Name = "cloudsql-proxy"
166+ cloudSQLProxyContainer .Image = fmt .Sprintf ("gcr.io/cloudsql-docker/gce-proxy:%s" , * proxyVersion )
167+ cloudSQLProxyContainer .Command = []string {"/cloud_sql_proxy" , fmt .Sprintf ("-instances=%s:%s:%s" , * project , * region , * instance ), "-log_debug_stdout=true" , fmt .Sprintf ("-verbose=%s" , * verbose ), "-credential_file=/secrets/cloudsql/credentials.json" }
168+ cloudSQLProxyContainer .Resources = v1.ResourceRequirements {Requests : requestResources , Limits : limitResources }
169+ cloudSQLProxyContainer .SecurityContext = & securityContext
170+ cloudSQLProxyContainer .VolumeMounts = append (cloudSQLProxyContainer .VolumeMounts , volumeMount )
171+ }
172+
173+
174+ return cloudSQLProxyContainer
175+ }
176+
177+ // Put the remaining bytes that are not the deployment, back in the output
178+ func putItBack (otherResources [][]byte , w io.Writer ) {
179+ for _ , resourceBytes := range otherResources {
180+ w .Write ([]byte ("\n ---\n " ))
181+ w .Write (resourceBytes )
182+ }
183+ }
0 commit comments