@@ -1702,39 +1702,186 @@ function generateSingleDeploymentManifest({
17021702 const nodeSelector = enableFullYaml ? deploy . deployable ?. nodeSelector : deploy . service ?. nodeSelector ;
17031703
17041704 const envToUse = deploy . env || { } ;
1705- const containers = [ ] ;
1706- const volumes : VOLUME [ ] = [ ] ;
1707- const volumeMounts = [ ] ;
1705+ const containers : Array < Record < string , any > > = [ ] ;
1706+ const initContainers : Array < Record < string , any > > = [ ] ;
1707+
1708+ const volumes : VOLUME [ ] = [
1709+ {
1710+ emptyDir : { } ,
1711+ name : 'config-volume' ,
1712+ } ,
1713+ ] ;
1714+ const volumeMounts : Array < { name : string ; mountPath : string } > = [ ] ;
1715+
1716+ const datadogLabels = {
1717+ 'tags.datadoghq.com/env' : `lifecycle-${ build . uuid } ` ,
1718+ 'tags.datadoghq.com/service' : serviceName || name ,
1719+ 'tags.datadoghq.com/version' : build . uuid ,
1720+ } ;
17081721
17091722 // Handle init container if present
17101723 if ( deploy . initDockerImage ) {
1711- const initEnvObj = flattenObject ( build . commentInitEnv ) ;
1712- const initEnvArray = Object . entries ( initEnvObj ) . map ( ( [ key , value ] ) => ( {
1713- name : key ,
1714- value : String ( value ) ,
1715- } ) ) ;
1724+ const initEnvObj = _ . merge (
1725+ { __NAMESPACE__ : 'lifecycle' } ,
1726+ deploy . initEnv || { } ,
1727+ flattenObject ( build . commentInitEnv )
1728+ ) ;
1729+
1730+ const initEnvArray : Array < Record < string , any > > = Object . entries ( initEnvObj )
1731+ . filter ( ( [ , value ] ) => ! _ . isObject ( value ) )
1732+ . map ( ( [ key , value ] ) => ( {
1733+ name : key ,
1734+ value : String ( value ) ,
1735+ } ) ) ;
1736+
1737+ initEnvArray . push (
1738+ {
1739+ name : 'POD_IP' ,
1740+ valueFrom : {
1741+ fieldRef : {
1742+ fieldPath : 'status.podIP' ,
1743+ } ,
1744+ } ,
1745+ } ,
1746+ {
1747+ name : 'DD_AGENT_HOST' ,
1748+ valueFrom : {
1749+ fieldRef : {
1750+ fieldPath : 'status.hostIP' ,
1751+ } ,
1752+ } ,
1753+ }
1754+ ) ;
17161755
1717- const initContainer = {
1756+ const initContainer : Record < string , any > = {
17181757 name : `init-${ serviceName || 'container' } ` ,
17191758 image : deploy . initDockerImage ,
1720- imagePullPolicy : 'Always ' ,
1759+ imagePullPolicy : 'IfNotPresent ' ,
17211760 env : initEnvArray ,
1761+ volumeMounts : [
1762+ {
1763+ mountPath : '/config' ,
1764+ name : 'config-volume' ,
1765+ } ,
1766+ ] ,
17221767 } ;
1723- containers . push ( initContainer ) ;
1768+
1769+ if ( serviceCPU || serviceMemory ) {
1770+ initContainer . resources = {
1771+ limits : { } ,
1772+ requests : { } ,
1773+ } ;
1774+ if ( serviceCPU ) {
1775+ initContainer . resources . limits . cpu = serviceCPU ;
1776+ initContainer . resources . requests . cpu = serviceCPU ;
1777+ }
1778+ if ( serviceMemory ) {
1779+ initContainer . resources . limits . memory = serviceMemory ;
1780+ initContainer . resources . requests . memory = serviceMemory ;
1781+ }
1782+ }
1783+
1784+ if ( servicePort ) {
1785+ initContainer . ports = [ ] ;
1786+ for ( const port of servicePort . split ( ',' ) ) {
1787+ initContainer . ports . push ( {
1788+ name : `port-${ port } ` ,
1789+ containerPort : Number ( port ) ,
1790+ } ) ;
1791+ }
1792+ }
1793+
1794+ if ( enableFullYaml ) {
1795+ if ( deploy . deployable ?. initCommand ) {
1796+ initContainer . command = [ deploy . deployable . initCommand ] ;
1797+ }
1798+ if ( deploy . deployable ?. initArguments ) {
1799+ initContainer . args = deploy . deployable . initArguments . split ( '%%SPLIT%%' ) ;
1800+ }
1801+ }
1802+
1803+ initContainers . push ( initContainer ) ;
17241804 }
17251805
17261806 // Handle main container
1727- const mainEnvObj = flattenObject ( { ...build . commentRuntimeEnv , ...envToUse } ) ;
1728- const mainEnvArray = Object . entries ( mainEnvObj ) . map ( ( [ key , value ] ) => ( {
1729- name : key ,
1730- value : String ( value ) ,
1731- } ) ) ;
1807+ const mainEnvObj = _ . merge ( { __NAMESPACE__ : 'lifecycle' } , envToUse , flattenObject ( build . commentRuntimeEnv ) ) ;
1808+ const mainEnvArray : Array < Record < string , any > > = Object . entries ( mainEnvObj )
1809+ . filter ( ( [ , value ] ) => ! _ . isObject ( value ) )
1810+ . map ( ( [ key , value ] ) => ( {
1811+ name : key ,
1812+ value : String ( value ) ,
1813+ } ) ) ;
1814+
1815+ // Add Kubernetes field references for pod metadata
1816+ mainEnvArray . push (
1817+ {
1818+ name : 'POD_IP' ,
1819+ valueFrom : {
1820+ fieldRef : {
1821+ fieldPath : 'status.podIP' ,
1822+ } ,
1823+ } ,
1824+ } ,
1825+ {
1826+ name : 'DD_AGENT_HOST' ,
1827+ valueFrom : {
1828+ fieldRef : {
1829+ fieldPath : 'status.hostIP' ,
1830+ } ,
1831+ } ,
1832+ }
1833+ ) ;
1834+
1835+ // Add Datadog env vars from labels (only if not already set)
1836+ const existingEnvKeys = new Set ( mainEnvArray . map ( ( e ) => e . name ) ) ;
1837+ if ( ! existingEnvKeys . has ( 'DD_ENV' ) ) {
1838+ mainEnvArray . push ( {
1839+ name : 'DD_ENV' ,
1840+ valueFrom : {
1841+ fieldRef : {
1842+ fieldPath : "metadata.labels['tags.datadoghq.com/env']" ,
1843+ } ,
1844+ } ,
1845+ } ) ;
1846+ }
1847+ if ( ! existingEnvKeys . has ( 'DD_SERVICE' ) ) {
1848+ mainEnvArray . push ( {
1849+ name : 'DD_SERVICE' ,
1850+ valueFrom : {
1851+ fieldRef : {
1852+ fieldPath : "metadata.labels['tags.datadoghq.com/service']" ,
1853+ } ,
1854+ } ,
1855+ } ) ;
1856+ }
1857+ if ( ! existingEnvKeys . has ( 'DD_VERSION' ) ) {
1858+ mainEnvArray . push ( {
1859+ name : 'DD_VERSION' ,
1860+ valueFrom : {
1861+ fieldRef : {
1862+ fieldPath : "metadata.labels['tags.datadoghq.com/version']" ,
1863+ } ,
1864+ } ,
1865+ } ) ;
1866+ }
1867+ if ( ! existingEnvKeys . has ( 'LC_UUID' ) ) {
1868+ mainEnvArray . push ( {
1869+ name : 'LC_UUID' ,
1870+ value : build . uuid ,
1871+ } ) ;
1872+ }
17321873
17331874 const mainContainer : any = {
17341875 name : serviceName || 'main' ,
17351876 image : deploy . dockerImage ,
1736- imagePullPolicy : 'Always ' ,
1877+ imagePullPolicy : 'IfNotPresent ' ,
17371878 env : mainEnvArray ,
1879+ volumeMounts : [
1880+ {
1881+ mountPath : '/config' ,
1882+ name : 'config-volume' ,
1883+ } ,
1884+ ] ,
17381885 } ;
17391886
17401887 // Only add resources if they are defined
@@ -1760,12 +1907,15 @@ function generateSingleDeploymentManifest({
17601907 mainContainer . ports = [ ] ;
17611908 for ( const port of servicePort . split ( ',' ) ) {
17621909 mainContainer . ports . push ( {
1910+ name : `port-${ port } ` ,
17631911 containerPort : Number ( port ) ,
17641912 } ) ;
17651913 }
17661914 }
17671915
1768- // Handle volumes
1916+ // Handle additional volumes (service disks)
1917+ let hasPersistentVolumeClaims = false ;
1918+
17691919 if ( enableFullYaml && deploy . deployable ?. serviceDisksYaml ) {
17701920 const serviceDisks : ServiceDiskConfig [ ] = JSON . parse ( deploy . deployable . serviceDisksYaml ) ;
17711921 serviceDisks . forEach ( ( disk ) => {
@@ -1775,6 +1925,8 @@ function generateSingleDeploymentManifest({
17751925 emptyDir : { } ,
17761926 } ) ;
17771927 } else {
1928+ // EBS or other persistent disk - requires Recreate strategy
1929+ hasPersistentVolumeClaims = true ;
17781930 volumes . push ( {
17791931 name : disk . name ,
17801932 persistentVolumeClaim : {
@@ -1795,6 +1947,8 @@ function generateSingleDeploymentManifest({
17951947 emptyDir : { } ,
17961948 } ) ;
17971949 } else {
1950+ // EBS or other persistent disk - requires Recreate strategy
1951+ hasPersistentVolumeClaims = true ;
17981952 volumes . push ( {
17991953 name : disk . name ,
18001954 persistentVolumeClaim : {
@@ -1809,8 +1963,9 @@ function generateSingleDeploymentManifest({
18091963 } ) ;
18101964 }
18111965
1966+ // Add additional volume mounts to main container
18121967 if ( volumeMounts . length > 0 ) {
1813- mainContainer . volumeMounts = volumeMounts ;
1968+ mainContainer . volumeMounts = [ ... mainContainer . volumeMounts , ... volumeMounts ] ;
18141969 }
18151970
18161971 // Add probes
@@ -1830,6 +1985,16 @@ function generateSingleDeploymentManifest({
18301985 }
18311986 }
18321987
1988+ // Add command/args if specified
1989+ if ( enableFullYaml ) {
1990+ if ( deploy . deployable ?. command ) {
1991+ mainContainer . command = [ deploy . deployable . command ] ;
1992+ }
1993+ if ( deploy . deployable ?. arguments ) {
1994+ mainContainer . args = deploy . deployable . arguments . split ( '%%SPLIT%%' ) ;
1995+ }
1996+ }
1997+
18331998 containers . push ( mainContainer ) ;
18341999
18352000 const deploymentSpec : any = {
@@ -1838,44 +2003,60 @@ function generateSingleDeploymentManifest({
18382003 metadata : {
18392004 namespace,
18402005 name,
2006+ annotations : {
2007+ 'cluster-autoscaler.kubernetes.io/safe-to-evict' : 'true' ,
2008+ } ,
18412009 labels : {
18422010 name,
18432011 lc_uuid : build . uuid ,
18442012 deploy_uuid : deploy . uuid ,
2013+ dd_name : `lifecycle-${ build . uuid } ` ,
2014+ ...datadogLabels ,
18452015 } ,
18462016 } ,
18472017 spec : {
18482018 replicas : replicaCount ,
2019+ revisionHistoryLimit : 5 ,
18492020 selector : {
18502021 matchLabels : {
18512022 name,
18522023 } ,
18532024 } ,
2025+ // Use Recreate strategy for deployments with PVCs (EBS volumes can only attach to one pod)
2026+ // Use RollingUpdate for all other deployments
2027+ strategy : hasPersistentVolumeClaims ? { type : 'Recreate' } : { rollingUpdate : { maxUnavailable : '0%' } } ,
18542028 template : {
18552029 metadata : {
2030+ annotations : {
2031+ 'cluster-autoscaler.kubernetes.io/safe-to-evict' : 'true' ,
2032+ } ,
18562033 labels : {
18572034 name,
18582035 lc_uuid : build . uuid ,
18592036 deploy_uuid : deploy . uuid ,
2037+ dd_name : `lifecycle-${ build . uuid } ` ,
2038+ ...datadogLabels ,
18602039 } ,
18612040 } ,
18622041 spec : {
18632042 serviceAccountName,
18642043 affinity,
18652044 ...( nodeSelector && { nodeSelector } ) ,
2045+ securityContext : {
2046+ fsGroup : 2000 ,
2047+ } ,
2048+ ...( initContainers . length > 0 && { initContainers } ) ,
18662049 containers,
2050+ volumes,
18672051 ...( build ?. isStatic && {
18682052 tolerations : staticEnvTolerations ,
18692053 } ) ,
2054+ enableServiceLinks : false ,
18702055 } ,
18712056 } ,
18722057 } ,
18732058 } ;
18742059
1875- if ( volumes . length > 0 ) {
1876- deploymentSpec . spec . template . spec . volumes = volumes ;
1877- }
1878-
18792060 return yaml . dump ( deploymentSpec , { lineWidth : - 1 } ) ;
18802061}
18812062
0 commit comments