
    !                     R   d Z ddlmZ ddlmZ ddlmZ ddlmZ ddlZddlZddlZddl	Z	ddl
Z	ddlZddlZddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddl m!Z! ddl m"Z" ddl m#Z# ddl m$Z$ ddl m%Z% ddl&m'Z' ddl(m)Z) ddl*m+Z+ ddl*mZ ddl*m,Z, ddl*m-Z- ddl*m.Z. ddl/m0Z0 ddl1m2Z2 ddl1m3Z3 ddl4Z4 ejj                  dd      Z6 ejj                  d d      Z7 ejj                  d!d      Z8d"Z9d#Z: e;       Z< G d$ d%e=      Z> G d& d'e#j~                        Z@ G d( d)e#j~                        ZAd* ZBd+ ZC G d, d-e#j~                        ZD G d. d/e#j~                        ZE G d0 d1e#j~                        ZF G d2 d3e#j~                        ZGd4 ZHd5 ZId6 ZJd7 ZKd8 ZLd9ZMd:ZNd;ZO	 	 	 	 djd<ZPd=ZQd> ZRd? ZSd@ ZTdA ZU ej                  dB      ZW ej                  dC      ZX ej                  dD      ZYdE ZZ ej                  dF      Z[dG Z\dH Z]dI Z^dJ Z_dK Z`dL Za G dM dNe;      Zb G dO dPeb      Zc G dQ dRe;      ZddS ZedT Zf G dU dVeb      ZgdWZh G dX dYeb      Zi G dZ d[ej                        Zk G d\ d]eb      Zld^Zmd_ Znd`Zoda Zpdb Zqdc ZrdkddZsde Ztdf Zudg Zvdh Zwdi Zxy)lz<Library for manipulating serverless local development setup.    )absolute_import)division)print_function)unicode_literalsN)encoding_helper)
exceptions)yaml_parsing)container_resourceservice)apis)messages)base)	auth_util)builders)common)
dataobject)secrets)yaml_helper)iam_util)secrets_mapping)config)log)
properties)yaml)
console_io)encoding)filesiamv1cloudresourcemanagerrunzgcr.io/buildpacks/builderz^[a-zA-Z_][a-zA-Z_0-9]*$c                       e Zd ZdZy)_ParseErrorz-File does not parse with the expected schema.N__name__
__module____qualname____doc__     ,lib/googlecloudsdk/command_lib/code/local.pyr$   r$   E   s    5r+   r$   c                       e Zd ZdZdZy)ServiceAccountSettingz.Setting object representing a service account.nameNr&   r'   r(   r)   NAMESr*   r+   r,   r.   r.   I   s
    6
%r+   r.   c                   &     e Zd ZdZdZ fdZ xZS )#ApplicationDefaultCredentialSettingz?Setting object representing the application default credential.Nc                 f    | j                   st        t        |   | fi || _         | j                   S N)	_instancesuperr4   __new__)clskwargs	__class__s     r,   r9   z+ApplicationDefaultCredentialSetting.__new__S   s8    ==?)),8068cm ==r+   )r&   r'   r(   r)   r7   r9   __classcell__)r<   s   @r,   r4   r4   N   s    G) r+   r4   c                     d| z  S )zGCR package path for a builder that works on the given appengine runtime.

  Args:
    runtime: Name of a runtime from app.yaml, e.g. 'python38'.

  Returns:
    gcr.io image path.
  z0gcr.io/gae-runtimes/buildpacks/%s/builder:latestr*   )runtimes    r,   _GaeBuilderPackagePathr@   [   s     
<g	EEr+   c                     | t         k(  S )zReturn true if the builder is the GCP base builder.

  Args:
    bldr: Name of the builder.

  Returns:
    True if the builder is the GCP base builder.
  )_DEFAULT_BUILDPACK_BUILDER)bldrs    r,   _IsGcpBaseBuilderrD   g   s     
+	++r+   c                       e Zd ZdZdZy)_SecretPathzConfiguration for a single secret version.

    Attributes:
      key: The secret version to mount.
      path: The file path to mount it on.
  keypathNr1   r*   r+   r,   rF   rF   s   s     %r+   rF   c                   .    e Zd ZdZdZe	 dd       Zd Zy)_SecretVolumea  Configuration for a single volume that mounts secret versions.

    Attributes:
      name: (str) The name of the volume to be referenced in the k8s resource.
      mount_path: (str) The filesystem location where the volume is mounted.
      secret_name: (str) The secret manager reference.
      mapped_secret: (str) If set, the path of the secret in another project to
        use. For example 'projects/123/secrets/foo'.
      items: (List[SecretPath]) The list of keys and paths for the secret.
  )r0   mapped_secret
mount_pathsecret_nameitemsNc                    g }|xs i }|j                   D ]2  }|j                  t        |j                  |j                               4 |j
                  }|j                  |j
                  d      }|sHt        j                  |      s3|}|j                  |d      }|st        |j
                        \  }}|||<    | |j                  |j                  |||      S )zFMake a SecretVolume based on the volumeMount and secret from the yaml.rG   Nr0   rM   rN   rO   rL   )rO   appendrF   rH   rI   
secretNamegetr   IsValidK8sName_BuildReachableSecretr0   	mountPath)	r:   mountvolume_secretsecret_aliasesrenamed_secretsrO   itemr0   rL   s	            r,   FromParsedYamlz_SecretVolume.FromParsedYaml   s     E%+O##ll;488$))<= $##D"&&}'?'?FM'"8"8">m  t,d3M4L4LMm)-&ZZ??#% %r+   c                     | j                   s|j                   r| j                   |j                   k(  S | j                  |j                  k(  S r6   )rL   rN   )selfothers     r,   IsSameSecretz_SecretVolume.IsSameSecret   sA    U005#6#666u0000r+   r6   )r&   r'   r(   r)   r2   classmethodr]   ra   r*   r+   r,   rK   rK   ~   s+    	 J%
 &*	% %21r+   rK   c                       e Zd ZdZdZy)_SecretEnvVara  Configuration for a single env var that's pulled from a secret.

  Attributes:
    name: (str) the name of the secret in the resource
    key: (str) the secret version to use
    mapped_secret: (str) if set, the path of the secret from the other project
      that this secret will pull from. For example 'projects/123/secrets/foo'.
      If not set, will pull from the secret called 'name' in the current
      project.
  r0   rH   rL   Nr1   r*   r+   r,   rd   rd      s    	 +%r+   rd   c                   P    e Zd ZdZdZed        ZddZd Zd Z	d Z
d Zd	 Zd
 Zy)SettingsaG  Settings for local development environments.

    Attributes:
      service_name: Name of the kuberntes service.
      image: Docker image tag.
      credential: Credential setting for either service account or application
        default credential.
      context: Path to directory to use as the current working directory for the
        docker build.
      builder: The builder specification or None.
      local_port: Local port to which to forward the service connection.
      env_vars: Container environment variables.
      env_vars_secrets: Container environment variables where the values come
        from Secret Manager.
      volumes_secrets: Volumes where the values come from secret manager.
      renamed_secrets: internal map of secrets that don't correspond to k8s
        naming conventions.
      cloudsql_instances: Cloud SQL instances.
      memory: Memory limit.
      cpu: CPU limit.
      namespace: Kubernetes namespace to run in.
      readiness_probe: If true, create readiness probe.
      allow_secret_manager: If true, allow fetching secrets from secret manager
  )service_nameimage
credentialcontextbuilder
local_portenv_varsenv_vars_secretsvolumes_secretsr[   cloudsql_instancesmemorycpu	namespacereadiness_probeallow_secret_managerc                 ~   t         j                  j                  t        j                               }|j                  dd      j                  dd      j                         }d}t        j                  |      } | |g t         j                  j                  t        j                               d|i i g i t        
      S )z5The settings you get with no args or other overrides._- 
Dockerfile
dockerfileN)
rl   rq   rk   ri   rh   rn   ro   rp   r[   rv   )osrI   basenamer   GetCWDreplacelowerr   DockerfileBuilderabspath_FLAG_UNSPECIFIED)r:   dir_namerh   dockerfile_arg_defaultrl   s        r,   DefaultszSettings.Defaults   s     ww/H##C-55c3?EEGL)((4JKG/!. r+   c           	      ,	   | j                  |      }d|j                  j                  i}	 |j                  j                  j                  j
                  \  }i }|j                  j                  t        j                  d      }t        j                  |d      j                         D 	ci c]  \  }}	||	j!                          }}}	|j                  j#                         r|j$                  j                  t        j                  d      }
|j'                  t        j                  |
d      j                         D 	ci c]  \  }}	||	j!                          c}	}       i }i }|j(                  D ],  }|j*                  r|j*                  j,                  rt        j                  d      |j*                  j.                  sS|j*                  j.                  j                  }|j                  |d      }|sRt1        j2                  |      s=|}| j4                  j                  |d      }|st7        |      \  }}|| j4                  |<   t9        |j*                  j.                  j:                  ||      ||j                  <   |j<                  ||j                  <   / |j'                  t?        | j@                  | jB                  ||             |j                  j                  j                  jD                  }|rtG        |      |d	<   |jH                  }|r||d
<   |j'                  | jK                  |             i }|j                  j                  j                  jL                  D ]U  }|jN                  r|jN                  ||j                  <   )t        j                  djQ                  |j                               g }|jR                  D ]|  }|j                  |vr.t        j                  djQ                  |j                              |jU                  tV        jY                  |||j                     || j4                               ~ ||d<    | jZ                  di |S # t        $ r t        j                  d      w xY wc c}	}w c c}	}w )a1  Overrides settings with service.yaml and returns a new Settings object.

    Args:
      yaml_path: Filename to read.
      is_alpha: boolean set to true if alpha features should be used.

    Returns:
      New Settings object.

    Raises:
      _ParseError: Input does not look like a service.yaml
    rh   z0knative Service must have exactly one container. Tz+env_vars from config_maps are not supportedN)rH   r0   rL   r/   rj   ri   zGCould not process volume "{}". Only volumes from secrets are supported.z5Container referenced volume "{}" which was not found.rp   r*   )._ParseServiceYamlmetadatar0   spectemplate
containers
ValueErrorr   ErrorannotationsrT   r
   SECRETS_ANNOTATIONr   ParseAnnotationrO   FormatAnnotationItemIsFullObjecttemplate_annotationsupdateenv	valueFromconfigMapKeyRefsecretKeyRefr   rU   r[   rV   rd   rH   value_MergedEnvVarsrn   ro   serviceAccountNamer.   ri   _ResourceRequestsvolumessecretformatvolumeMountsrR   rK   r]   r   )r_   	yaml_pathis_alphaknative_servicereplacements	containerrZ   aliaseskvtemplate_aliasesnew_env_varsnew_env_vars_secretsvarrN   rL   service_account_name
image_nameall_volsvolreferenced_volss                        r,   WithServiceYamlzSettings.WithServiceYaml   s$    ,,Y7O 	0055LQ#((1166AAky N))----r3G $33GTBHHJJDAq 	
1!!##J   ,,.(==AA

/
/5/>/N/N0&&+eg0.0.tq! 

 
 
"#0. 	
 L}}	==((  !NO
O]]''2277+(,,[$?-w'='=k'J'M..22=$GK+@+O(k=4?d""=1+8--,,00),+
sxx
(
 "%SXX' ( t}}d&;&;\+	-. +//88==PP#8#$%l<  J(l7..y9:H##,,1199	 ZZ  ==CVCHH=MO 	O	 : O%%		!  ((.sxx(8: 	:

&
&sHSXX,>'+';';=>	 & '6L"#4<<',''Y  QOPPQs   ,Q( *R
>R
(Rc                    	 t        j                  |      }t        j                  |t        j
                        }t        j
                  |t              }|S # t         j                  t        j                  f$ r t               w xY wr6   )
r   	load_pathmessages_utilDictToMessageWithErrorCheckRUN_MESSAGES_MODULEServicek8s_servicer   DecodeErrorr$   )r_   r   	yaml_dictmessager   s        r,   r   zSettings._ParseServiceYamlR  st    ..+i99
(002g#++G5HIo  JJ112 Ms   AA .Bc                    |j                   r|j                   j                  si S i }|j                   j                  j                  D ]?  }|j                  dk(  r|j                  |d<   |j                  dk(  s1|j                  |d<   A |S )Nrs   rr   )	resourceslimitsadditionalPropertiesrH   r   )r_   r   retprops       r,   r   zSettings._ResourceRequests\  sy    i&9&9&@&@i
C##**??	U	ZZE
	X	

H	 @
 Jr+   c                    	 t         j                  j                  |      }t        |j                  j                        }t        j                  |dd      }| j                  |      S # t        j                  $ r t               w xY w)zOverrides settings with app.yaml and returns a new Settings object.

    Args:
      yaml_path: Filename to read.

    Returns:
      New Settings object.

    Raises:
      ParseError: Input does not look like an app.yaml
    TFrl   trustdevmode)rl   )app_engine_yaml_parsingServiceYamlInfoFromFiler   r   r$   r@   parsedr?   r   BuildpackBuilderr   )r_   r   service_configbuilder_urlrl   s        r,   WithAppYamlzSettings.WithAppYamlg  s}    .>>GG
n ))>)>)F)FGK''48G<<<(( :: Ms   A* *Bc                    i }dD ]#  }|j                  |      st        ||      ||<   % |j                  d      rt               |d<   n*|j                  d      rt	        |j
                        |d<   | j                  }|j                  r)t        j                  j                  |j                        }||d<   t        |dd      rd	|d
<   n|j                  d
      rt        |j                        |d
<   n}|j                  d      r$t        j                  |j                        |d
<   nHt!        | j                  t        j                        r$	 | j                  |d
<   |d
   j#                  |       t        |dd	      r|j.                  }nt        |di       xs i }| j1                  t        |di       xs i       \  }}|j3                  t5        | j.                  | j6                  ||             t9        | j:                  |      |d<    | j<                  di |S # t        j$                  $ r4 t&        j(                  j+                  d       t        t,              |d
<   Y w xY w)z?Overrides settings with args and returns a new Settings object.)	rm   rr   rs   rt   ru   rq   ri   rh   rv   application_default_credentialrj   service_accountr/   rk   no_skaffold_fileFNrl   r}   r|   zCNo Dockerfile detected. Using GCP buildpacks to build the containerrn   env_vars_filer   rp   r*   )IsKnownAndSpecifiedgetattrIsSpecifiedr4   r.   r   rk   sourcer~   rI   r   _BuilderFromArgrl   r   r   r}   
isinstanceValidateInvalidLocationErrorr   statusPrintrB   rn   _GetSecretsr   r   ro   _MergeSecretVolumesrp   r   )r_   argsr   override_argrk   new_envsnew_env_secretsnew_sec_volumess           r,   WithArgszSettings.WithArgs}  s5    L
 
	!	!,	/%,T<%@\"
 89#F#Hl< 			+	,#8##$%l< llG{{,g%Lt'/ $l9		!	!)	,"1$,,"?Y##L1"*"<"<#(Y dllH$>$>?,&*llL##,,W5 tZ&h39rh'+'7'7i$*(,$O_t}}d&;&;X&	() ':o'/L"#4<<',''% .. ,JJ K L&5*',L#,s   #H AI%$I%c                 v   i }i }i }|j                         D ]  \  }}|j                  d      }t        |      dk7  r$t        j                  dj                  |            |\  }}	d }
|j                  d      rV|}
|
|vrJ|j                         j                  dd      d d dz   t        t        j                               z   }|||
<   nI||
   }nCt        j                  |      s.|| j                  v r|}
| j                  |   }nt        |      \  }}
|j                  d	      rit         j"                  j                  |      \  }}||vrt%        |||g |

      }|||<   n||   }|j                   j'                  t)        |	|             ut+        ||	|
      ||<    |t-        |j/                               fS )N:   z<Expected secret to be of form <secretName>:<version>, got {}	projects/rx   .   ry   /rQ   rG   re   )rO   splitlenr   r   r   
startswithr   r   struuiduuid1r   rU   r[   rV   r~   rI   rK   rR   rF   rd   listvalues)r_   secrets_argsrn   r   r   rH   r   partsrN   versionrL   rM   filenamevolumes                 r,   r   zSettings._GetSecrets  s   HGG#))+Vll3e	Uq  @@FvP 	P"k7m				,#'!))#s3BQ7#=$**,   $/'-
 .+%%k2$...%-,,[9+'<['I
$+}		!ww}}S1
HW$ #%)+& !''*
:&&KG(CD%'HO ,R T'..*+++r+   c                    t        | j                  t        j                        r%| j                  j	                  | j
                         i }| j                  t        | j                        |d<    | j                  di |S )zCValidate and compute settings after all user inputs have been read.ri   r*   )
r   rl   r   r   r   rk   ri   _DefaultImageNamerh   r   )r_   r   s     r,   BuildzSettings.Build  sd    $,, : :;
llDLL)Lzz/0A0ABl74<<',''r+   N)F)r&   r'   r(   r)   r2   rb   r   r   r   r   r   r   r   r   r*   r+   r,   rg   rg      sJ    2C%
  ,a(F	),;(z.,`(r+   rg   c                 \   | j                         } |j                         }t        |      j                  |      }|r$t        j                  dj                  |            |j                         D ]  \  }}||v r||= || |<    |j                         D ]  \  }}|| v r| |= |||<    | |dS )zDAdd the new env vars (both values and secrets) to the existing ones.z{} cannot be secret and literal)rn   ro   )copysetintersectionr   r   r   rO   )rn   ro   r   r   	conflictsnew_envval
new_secrets           r,   r   r     s     ]]_(%**, ,,,-AB)


<CCIN
OO
 #((*lgs""
7
#HW + .335oj#X
:
#&Z  6 4D	EEr+   c                 .   | D ci c]  }|j                   | }}|D ]  }|j                   |vr|||j                   <   !||j                      }|j                  |      r|j                  D ci c]  }|j                  | }}|j                  D ci c]  }|j                  | }}|j	                  |       t        |j                               |j                  dd |||j                   <    t        |j                               S c c}w c c}w c c}w )zACombine the secret volumes from existing source with new volumes.N)rM   ra   rO   rI   r   r   r   )	cur_volsnew_volsr   vol_mapnew_volcur_volr\   	cur_items	new_itemss	            r,   r   r     s   ,45HSS^^S H'5g($+gg  !**+g			g	&18?TYY_	?18?TYY_	?#	 0 0 23a '.""#  
gnn	 6 @?s   D,DDc                 d   |t         j                  j                  k(  }t        j	                         }t        | dd      xs t        j                  j                  }t        | dd      }t        j                  ||      }|r.	 |j                  ||t         j                  j                  k(        }|j!                  |       }|j#                         }|S # t        $ rU |r8	 |j                  |      }n=# t        $ r t        j                  d|z        w xY wt        j                  d|z        Y w xY w)zHLayer the defaults, service.yaml/app.yaml values, and cmdline overrides.r   Nr   z4%r is unreadable as a service.yaml or app.yaml file.z(%r is unreadable as a service.yaml file.)r   ReleaseTrackALPHArg   r   r   r~   rI   curdirr   ChooseExistingServiceYamlr   r$   r   r   r   r   r   )r   release_trackservice_config_may_be_app_yamlsettingscontext_dirservice_config_arg	yaml_files          r,   AssembleSettingsr  "  s3    $1D4E4E4K4K#K  (h-?+t%5t<..{<NO)*))
]d&7&7&=&==?h t$(^^(	/  
*	'	)))4( 	  D 	
 I( ) * 	* 
*s*   -C D/C/.D//"DD/.D/c                     t         j                  j                  j                  j	                         }|rdj                  ||       }n| }|j                         }|S )zComputes a default image name.zgcr.io/{project}/{service})projectr   )r   VALUEScorer  Getr   r   )rh   project_nameri   s      r,   r   r   @  sX    ""''//335,(//l 0 4E E ++-%	,r+   c                 H    t        |       }t        j                  | ||      S )Nr   )rD   r   r   )builder_argis_gcp_base_builders     r,   r   r   Q  s)    )+6		"	"!
# #r+   a.  
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {service}
  labels:
    service: {service}
spec:
  replicas: 1
  selector:
    matchLabels:
      app: {service}
  template:
    metadata:
      labels:
        app: {service}
    spec:
      containers: []
      terminationGracePeriodSeconds: 0
zi
name: {service}-container
image: {image}
env:
- name: PORT
  value: "8080"
ports:
- containerPort: 8080
z
name: {service}-readiness-probe
image: gcr.io/gcp-runtimes/ubuntu_18_0_4:latest
command: ["sleep"]
args: ["infinity"]
readinessProbe:
  exec:
    command:
    - "grep"
    - ":1F90"
    - "/proc/net/tcp"
    - "/proc/net/tcp6"
  periodSeconds: 1
c                 |   t        j                  t        j                  |             }t        j                  t        j                  | |            }|t        j                  |d      }||d<   |.t        j                  |d      }t        j                  |      |d<   |.t        j                  |d      }	t        j                  |      |	d<   t        j                  |dt              }
|
j                  |       |r:t        j                  t        j                  |             }|
j                  |       ||fS )	a  Create a deployment specification for a service.

  Args:
    service_name: Name of the service.
    image_name: Image tag.
    memory_limit: Container memory limit.
    cpu_limit: Container cpu limit.
    cpu_request: Container cpu request.
    readiness_probe: If true, add a readiness probe.

  Returns:
    Dictionary object representing the deployment yaml, and the main container.
  r   )r   ri   )r   r   rr   rs   )r   requestsr   r   r   r   constructor)r   load_POD_TEMPLATEr   _CONTAINER_TEMPLATEr   GetOrCreatesix	text_typer   rR   #_READINESS_PROBE_CONTAINER_TEMPLATE)rh   r   memory_limit	cpu_limitcpu_requestru   
deploymentr   r   r'  r   readiness_containers               r,   _CreateDeploymentr7    s    & yy--l-CD*ii  Z HJ)$$Y0GHF#F8$$Y0GHFMM),F5M&&y2KLHmmK0HUO&&<$P*I))+22<2HJ)*	Y	r+   z
apiVersion: v1
kind: Service
metadata:
  name: {service}
spec:
  type: LoadBalancer
  selector:
    app: {service}
  ports:
  - protocol: TCP
    port: 8080
    targetPort: 8080
c                 X    t         j                  |       }t        j                  |      S )zCreate a service specification.

  Args:
    service_name: Name of the service.

  Returns:
    Dictionary objects representing the service yaml.
  r   )_SERVICE_TEMPLATEr   r   r+  )rh   	yaml_texts     r,   CreateServicer;    s&      &&|&<)	9	r+   c                 H   t        j                  | dt              }g }t        |j	                               D ]X  \  }}t        j                  t        |      s%|j                  t        j                  |             E|j                  ||d       Z |rt        d|z        y)zAdd environment variable settings to a container.

  Args:
    container: (dict) Container to edit.
    env_vars: (dict) Key value environment variable pairs.
  r   r)  r0   r   zCEnvironment variable name must be a C_IDENTIFIER. Invalid names: %rN)r   r.  r   sortedrO   rematch_C_IDENTIFIERrR   r/  
ensure_strr   )r   rn   env_listinvalid_keysrH   r   s         r,   _AddEnvironmentVariablesrF    s     $$YdK(,8>>+,jc588M3'#..-.OOS512	 -
 
 )+78 9 9 r+   c                     t        j                  | dt              }t        |j	                               D ]2  \  }}|j                  |d|j                  |j                  did       4 y)zAdd environment variables from secrets to a container.

  Args:
    container: (dict) Container to edit.
    env_vars_secrets: (dict) Key value environment variable pairs. Values are
      dict with key/name keys in them.
  r=  r)  r   )r0   rH   )r0   r   N)r   r.  r   r?  rO   rR   r0   rH   )r   ro   rD  rH   r   s        r,   _AddSecretEnvironmentVariablesrH    sd     $$YdK(+1134jc5OO

yy
  5r+   c                 :   t        |       }dj                  ||       }t        |      }t        |       r|st	        d| z        |S |sRt        |       }t        d||       d}dj                  |       }t        j                  ||      rt        |d| z   d	       |S )
zCreates a service account for local development.

  Args:
    service_account_email: Email of the service account.

  Returns:
    The resource name of the service account.
  z,projects/{project}/serviceAccounts/{account})r  accountz9%s cannot be created because it is a service account namez,Serverless Local Development Service AccountzoThe project editor role allows the service account to create, delete, and modify most resources in the project.zAdd project editor role to {}?r   prompt_stringzserviceAccount:zroles/editor)
_GetServiceAccountProjectr   _ServiceAccountExists_IsReservedServiceAccountNamer   _GetServiceAccountId_CreateAccountr   PromptContinue_AddBinding)service_account_email
project_idr   exists
account_idpermission_msgrL  s          r,   CreateDevelopmentServiceAccountrY    s     ))>?*GNN"7 O 9 !!56&"#89 &(=> ? ? "!	%&;<JA:!N 	)//0EF    m=*/2GG " 
r+   z9(?P<id>[^@]+)@(?P<project>[^\.]+).iam.gserviceaccount.comz=(?P<project_id>[^\.]+).google.com@appspot.gserviceaccount.comz=(?P<project_number>\d+)-compute@developer.gserviceaccount.comc                     t         j                  |       }|r|j                  d      S t        j                  |       }|r|j                  d      S t        j                  |       }|rt        |j                  d            S t        | dz         )zGet the project id from a service account email.

  Args:
    service_account_email: (str) Email address of service account.

  Returns:
    The project id of the project to which the service account belongs.
  r  rU  project_number' is not a valid service account address)_PROJECT_SERVICE_ACCOUNT_RErA  group_APPENGINE_SERVICE_ACCOUNT_COMPUTE_SERVICE_ACCOUNT_ProjectNumberToIdr   rT  matchers     r,   rM  rM  3  s     (--.CD'==##&,,-BC'==&&$**+@A'gmm,<=>>(<= 	> >r+   z&(?P<id>[^@]+)@.*\.gserviceaccount\.comc                 n    t         j                  |       }|st        | dz         |j                  d      S )Nr\  id)_SERVICE_ACCOUNT_RErA  r   r^  rb  s     r,   rP  rP  O  s?    %%&;<'	
*>? @ @	t	r+   c                     t        j                  dd      }t        j                  |       }|j                  j                  |      }t        j                  |j                        S )zCoverts project number to project id.

  Args:
    project_number: (str) The project number as a string.

  Returns:
    The project id.
  r!   r    )	projectId)	r   GetClientInstanceCRM_MESSAGE_MODULE&CloudresourcemanagerProjectsGetRequestprojectsr!  r/  ensure_textrh  )r[  resource_managerreqr  s       r,   ra  ra  W  s\     ++,BDIAA 	B 	 #%%))#.'	**	++r+   c                 Z    t         j                  |       xs t        j                  |       S r6   )r_  rA  r`  )rT  s    r,   rO  rO  g  s,    
$
*
*+@
A @
"
(
()>
?Ar+   c                     t        j                  dd      }	 t        j                  |       }|j                  j                  |       y# t        j                  $ r Y yw xY w)zTests if service account email.

  Args:
    service_account_name: (str) Service account resource name.

  Returns:
    True if the service account exists.
  r   r    r/   TF)r   ri  IAM_MESSAGE_MODULE$IamProjectsServiceAccountsGetRequestprojects_serviceAccountsr!  apitools_exceptionsHttpNotFoundError)r   r   requests      r,   rN  rN  l  sc     ""5$/' EE! F #G$$((1		.	. s   1A
 
A A c                 $   t        j                  dd      }	 t        j                  |       }t        j	                  ||      }|j
                  j                  t        j                  d|z   |             y# t        j                  $ r Y yw xY w)zCreate an account if it does not already exist.

  Args:
    display_name: (str) Display name.
    account_id: (str) User account id.
    project: (str) Project name.
  r   r    )displayName)	accountIdserviceAccountr   )r0   createServiceAccountRequestN)
r   ri  rr  ServiceAccountCreateServiceAccountRequestrt  Create'IamProjectsServiceAccountsCreateRequestru  HttpConflictError)display_namerW  r  r   service_account_msgrw  s         r,   rQ  rQ    s     ""5$/'
	,;;  < " <<-@ = BG$$++BBw&G 	C 	MN 
	.	. 		s   A A9 9BBc                    t        j                  dd      }|j                  j                  t        j                  |             }t        j                  |||      smt        j                  t        j                  |||       t        j                  | t        j                  |            }|j                  j                  |       yy)zsAdds a binding.

  Args:
    project: (str) Project name.
    account: (str) User account.
    role: (str) Role.
  r!   r    )resource)policy)r  setIamPolicyRequestN)r   ri  rl  GetIamPolicyrj  /CloudresourcemanagerProjectsGetIamPolicyRequestr   BindingInPolicyAddBindingToIamPolicyBinding/CloudresourcemanagerProjectsSetIamPolicyRequestSetIamPolicyRequestSetIamPolicy)r  rJ  role
crm_clientr  ro  s         r,   rS  rS    s     %%&<dC*++HH I & 
	!	!&'4	8""#5#=#=vw#')

L
L.BB C  M C $$S) 
9r+   c                   "    e Zd ZdZd Zd Zd Zy)KubeConfigGeneratorzlThe base code generator with default return values.

  Subclasses may override any of the member methods.
  c                     g S )z}Create top level kubernetes configs.

    Returns:
      List of kubernetes configuration yamls encoded as dictionaries.
    r*   r_   s    r,   CreateConfigsz!KubeConfigGenerator.CreateConfigs  s	     Ir+   c                      y)a  Modify a deployment.

    Subclasses that override this method should use this method for adding
    or deleting resources (e.g. containers, volumes, metadata) to the
    deployment.

    Args:
      deployment: (dict) Deployment yaml in dictionary form.
    Nr*   )r_   r5  s     r,   ModifyDeploymentz$KubeConfigGenerator.ModifyDeployment      r+   c                      y)zModify a container.

    Subclasses that override this method should use this method for adding,
    deleting, or modifying any of the yaml for a container.

    Args:
      container: (dict) Container yaml in dictionary form.
    Nr*   )r_   r   s     r,   ModifyContainerz#KubeConfigGenerator.ModifyContainer  r  r+   N)r&   r'   r(   r)   r  r  r  r*   r+   r,   r  r    s    
	r+   r  c                   *    e Zd ZdZ	 	 	 	 	 	 ddZd Zy)AppContainerGeneratorz6Generate deployment and service for a developer's app.Nc	                 t    || _         || _        || _        || _        || _        || _        || _        || _        y r6   )_service_name_image_name	_env_vars_env_vars_secrets_memory_limit
_cpu_limit_cpu_request_readiness_probe)	r_   rh   r   rn   ro   r2  r3  r4  ru   s	            r,   __init__zAppContainerGenerator.__init__  sB     &D!DDN-D%DDO#D+Dr+   c                    t        | j                  | j                  | j                  | j                  | j
                  | j                        \  }}| j                  ddd}t        ||       | j                  rt        || j                         | j                  rt        || j                         t        | j                        }||gS )Ndevzdev-0001)	K_SERVICEK_CONFIGURATION
K_REVISION)r7  r  r  r  r  r  r  rF  r  r  rH  r;  )r_   r5  r   default_env_varsr   s        r,   r  z#AppContainerGenerator.CreateConfigs  s    -D,,d.@.@**D,A,ACJ	 ''   Y(89~~y$..9$Y0F0FGD../G  r+   )NNNNNF)r&   r'   r(   r)   r  r  r*   r+   r,   r  r    s#    >
  $ $,$!r+   r  c                       e Zd ZdZd Zy)
SecretInfoz%Information about a generated secret.c                 `    d| _         d| j                   j                  dd      z   dz   | _        y )Nzlocal-development-credential/etc/ry   rx   z'/local_development_service_account.json)rN   r   rI   r  s    r,   r  zSecretInfo.__init__  s1    5D4++33C==:;DIr+   N)r&   r'   r(   r)   r  r*   r+   r,   r  r    s
    -<r+   r  c                 .    t        |       }t        |      S )zGet a service account secret file as text.

  Args:
    account_name: (str) Name of the service account.

  Returns:
    Context of the service account secret as a string.
  )rY  CreateServiceAccountKey)account_namer   s     r,   GetServiceAccountSecretr    s     4LA/	 	11r+   c                  x    t        j                          t        j                  t        j                               S )zGet a copy of the application default credential for a user.

  Returns:
    Text version of the user's application default credential.
  )r   AssertADCExistsjsondumpsGetADCAsJsonr*   r+   r,   GetUserCredentialr    s(     	I**,	--r+   c                   .    e Zd ZdZd Zd Zd Zd Zd Zy)CredentialGeneratorz"Configures service account secret.c                     || _         y r6   )_credential_fetcher)r_   credential_fetchers     r,   r  zCredentialGenerator.__init__  s
    1Dr+   c                     t               S r6   )r  r  s    r,   GetInfozCredentialGenerator.GetInfo  s
    <r+   c                 6    t        | j                               gS )zCreate a secret.)LocalDevelopmentSecretSpecr  r  s    r,   r  z!CredentialGenerator.CreateConfigs!  s    &t'?'?'ABCCr+   c                     | j                         }t        j                  |dt              }t	        ||j
                         y)z$Add a secret volume to a deployment.r   r   r   r   N)r  r   r.  r   _AddSecretVolumerN   )r_   r5  secret_infor   s       r,   r  z$CredentialGenerator.ModifyDeployment%  s7    ,,.K%%j&M&*,G Wk556r+   c                     | j                         }t        j                  |dt              }t	        ||j
                         t        j                  |dt              }t        ||j                         y)zEAdd volume mount and set application credential environment variable.r   r=  N)r  r   r.  r   _AddSecretVolumeMountrN   _AddSecretEnvVarrI   )r_   r   r  mountsenvss        r,   r  z#CredentialGenerator.ModifyContainer-  sV    ,,.K$$Y0A4HF&+"9"9:""9h=DT;++,r+   N)	r&   r'   r(   r)   r  r  r  r  r  r*   r+   r,   r  r    s    *2D7-r+   r  zcloud-sql-proxyc                   "    e Zd ZdZd Zd Zd Zy)CloudSqlProxyGeneratorzDGenerate kubernetes configurations for a Cloud SQL proxy connection.c                      || _         || _        y r6   )_instance_names_secret_info)r_   instance_namesr  s      r,   r  zCloudSqlProxyGenerator.__init__<  s    )D#Dr+   c                    t        j                  |dt              }|j                  di d       t        j                  |dt              }|j                  t	        | j
                  | j                  j                               y)z7Add sidecar container and empty volume for unix socket.r  r)  cloudsql)r0   emptyDirr(  N)r   r.  r   rR   _CreateCloudSqlProxyContainerr  r  rI   )r_   r5  r   r   s       r,   r  z'CloudSqlProxyGenerator.ModifyDeployment@  st    %%;OGNNJB78((>J %d&:&:&*&7&7&<&<	>?r+   c                     |d   t         k(  ryt        j                  |dt              }|j	                  dddd       y)	zAdd volume mount to continer.

    This method will not modify the CloudSql proxy container.

    Args:
      container: (dict) Container yaml as a dict.
    r0   Nr  r)  r  	/cloudsqlTr0   rW   readOnly)_CLOUD_PROXY_CONTAINER_NAMEr   r.  r   rR   )r_   r   volume_mountss      r,   r  z&CloudSqlProxyGenerator.ModifyContainerM  sI     77++$$8M  r+   N)r&   r'   r(   r)   r  r  r  r*   r+   r,   r  r  9  s    L$?r+   r  c                       e Zd ZdZy)SecretsNotAllowedErrorzEError thrown when the deploy is not allowed to access secret manager.Nr%   r*   r+   r,   r  r  `  s    Mr+   r  c                   ,    e Zd ZdZefdZd Zd Zd Zy)SecretsGeneratorz3Generate kubernetes secrets for referenced secrets.c                 J   t         j                  j                  j                  j	                         | _        || _        || _        i | _        t        j                  t              }|j                         D ]9  \  }}||j                  |j                  f   j                  |j                          ; |D ]  }|j                  sC||j"                  |j                  f   j                  t$        j&                  j(                         R|j                  D ]6  }	||j"                  |j                  f   j                  |	j                          8  |j                         D ]6  \  \  }
}}t+        j,                  |
t/        |      |      | j                  |
<   8 || _        || _        y )N)r0   versionsrL   )r   r  r   r  r!  r"  rh   secret_volumesall_secretscollectionsdefaultdictr  rO   r0   rL   addrH   rN   r   SpecialVersion	MOUNT_ALLr   SecretManagerSecret	frozensetrt   rv   )r_   rh   env_secretsr  rt   rv   secrets_builderrx   r   r\   rN   rL   r  s                r,   r  zSecretsGenerator.__init__h  sh    #))..66::<D$D(DD!--c2O &&(	6v{{F$8$89:>>vzzJ ) !\\++V-A-ABCGG**44	6 LLD
6--!//1 225#dhh- ! ! 3B2G2G2I.$mh&-&A&AX&%''d{# 3J
 DN 4Dr+   c                    | j                   sg S | j                  t        u rg }| j                   j                         D ]>  \  }}|j                  r|j                  |j                         .|j                  |       @ d}dj                  |      }t        j                         r=t        j                  ||      r&t        j                  j                  d       d| _        | j                  r| j                  t        u rt        d      t        j                  | j                   t#        | j                   j%                               | j&                        S )NzThis config references secrets stored in secret manager. Continuing will fetch the secret values and download the secrets to your local machine.z)Fetch secrets from secret manager for {}?rK  zRYou can skip this message in the future by passing the flag --allow-secret-managerTzConfig requires secrets but access to secret manager was not allowed. Replace secrets with environment variables or allow secret manager with --allow-secret-manager to proceed.)r  rv   r   rO   rL   rR   r   r   	CanPromptrR  r   r   r   r  r   BuildSecretsr"  r  r   rt   )r_   	requestedrH   secsecrets_msgrL  s         r,   r  zSecretsGenerator.CreateConfigs  s2   i  $55i&&,,.(#s


3,,
-


3
	 /
:k 6
<
<Y
G  
			J$=$=]%<

*	+ %)!%%!!%66"IJ J  1 1 #D$4$4$;$;$= >P Pr+   c                     |d   d   | j                   k7  ry | j                  sy t        j                  |dt              }| j                  D ].  }t        ||j                  |j                  |j                         0 y )Nr   r0   r  )	rh   r  r   r.  r   _AddSecretVolumeByNamerN   r0   rO   )r_   r5  r   r   s       r,   r  z!SecretsGenerator.ModifyDeployment  st     *f%):)::%%j&M&*,G %%Wf&8&8&++#\\+ &r+   c                     |d   dj                  | j                        k7  ry | j                  sy t        j                  |dt
              }| j                  D ]#  }t        ||j                  |j                         % y )Nr0   z{}-containerr  )	r   rh   r  r   r.  r   _AddVolumeMountr0   rM   )r_   r   r  r   s       r,   r  z SecretsGenerator.ModifyContainer  sj    N11$2C2CDD$$Y0A4HF%%ffkk6+<+<= &r+   N)	r&   r'   r(   r)   r   r  r  r  r  r*   r+   r,   r  r  e  s!    ; %65BPB+>r+   r  z1.16c                 b    t         dt        z   dgdddj                  |       z   d|z   gddd	gd
S )Nz!gcr.io/cloudsql-docker/gce-proxy:z/cloud_sql_proxyz-dir=/cloudsqlz-instances=,z-credential_file=r  r  )r0   rW   )r0   ri   commandr   r   )r  _CLOUD_SQL_PROXY_VERSIONjoin)	instancessecret_paths     r,   r  r    sP    )25MM$%
MCHHY,??

+
 " 	
 r+   zY
apiVersion: v1
kind: Secret
metadata:
  name: local-development-credential
type: Opaque
c                    t         j                  j                  t        j                         j
                  t        |       dz         }t        j                  t         j                  d|      }t         j                  j                  |      rt        j                  |      S dj                  | |      }t        j                  |dd       t!        j"                  dd	      }|j$                  }|j'                  | |j)                  |j(                  j*                  j,                  
            }|j.                  j1                  |      }t        j2                  ||j4                         t7        j8                  |j4                        S )zCreate a service account key.

  Args:
    service_account_name: Name of service acccount.

  Returns:
    The contents of the generated private key file as a string.
  z.jsonLOCAL_CREDENTIAL_PATHa  Creating a user-managed service account key for {service_account_name}. This service account key will be the default credential pointed to by GOOGLE_APPLICATION_CREDENTIALS in the local development environment. The user is responsible for the storage,rotation, and deletion of this key. A copy of this key will be stored at {local_key_path}.
Only use service accounts from a test project. Do not use service accounts from a production project.)r   local_key_pathz	Continue?T)r   rL  cancel_on_nor   r    )privateKeyType)r0   createServiceAccountKeyRequest)r~   rI   r  r   Pathsglobal_config_dir_Utf8ToBase64r   GetEncodedValueenvironrV  r   ReadFileContentsr   r   rR  r   ri  MESSAGES_MODULE+IamProjectsServiceAccountsKeysCreateRequestCreateServiceAccountKeyRequestPrivateKeyTypeValueValuesEnumTYPE_GOOGLE_CREDENTIALS_FILEprojects_serviceAccounts_keysr  WriteFileContentsprivateKeyDatar/  rm  )r   default_credential_pathcredential_file_pathwarning_msgr   message_modulecreate_key_requestrH   s           r,   r  r    sc    GGLLlln&&()G35 "11"**2I2IK WW^^()!!"677? AG*>$8 AG A:  4I ""5$/'**. @@#)7))+JJ,,-I-I * K A L  	--445GH#.0B0BC	++	,,r+   c                 X    t        j                  t              }dt        |       i|d<   |S )zCreate a kubernetes yaml spec for a secret.

  Args:
    key: (str) The private key as a JSON string.

  Returns:
    Dictionary representing yaml dictionary.
  z&local_development_service_account.jsondata)r   r+  _SECRET_TEMPLATEr	  )rH   yaml_configs     r,   r  r    s1     		*++.c0B+f 
r+   c                      t        | ||       y )N)rN   volume_name)r  )r   rN   s     r,   r  r     s    ;KAr+   c                 N   t        fd| D              ry|xs g D cg c]-  }t        j                  |j                  |j                        / }}| j                  t        j                  t        j                  t        j                  ||                         yc c}w )a'  Add a secret volume to a list of volumes.

  Args:
    volumes: (list[dict]) List of volume specifications.
    secret_name: (str) Name of the secret.
    volume_name: (str) Name of the volume to add.
    items: (list[_SecretPath]) Optional list of SecretPaths to map on the
      filesystem.
  c              3   .   K   | ]  }|d    k(    ywr0   Nr*   ).0r   r  s     r,   	<genexpr>z)_AddSecretVolumeByName.<locals>.<genexpr>/  s     =W6;	&W   NrG   )rS   rO   )r0   r   )
anyr   	KeyToPathrH   rI   rR   r   MessageToDictVolumeSecretVolumeSource)r   rN   r  rO   secpath	items_lsts     `   r,   r  r  %  s     	=W==
 krk!' ##',,#G!   
..##

$
$(;;(	 < ; % <=>	s   2B"c           	      F    t        | |d|j                  dd      z          y)zAdd a secret volume mount.

  Args:
    mounts: (list[dict]) List of volume mount dictionaries.
    secret_name: (str) Name of the secret.
  r  ry   rx   )
mount_namerM   N)r  r   )r  rN   s     r,   r  r  =  s'     ;..sC88:r+   c                     t        fd| D              ry t        j                  |d      }| j                  t	        j
                  |             y )Nc              3   .   K   | ]  }|d    k(    ywr"  r*   )r#  rX   r.  s     r,   r$  z"_AddVolumeMount.<locals>.<genexpr>K  s     9&uV}	$&r%  Tr  )r&  r   VolumeMountrR   r   r(  )r  r.  rM   rX   s    `  r,   r  r  J  sG    9&99


)
)d * <%----e45r+   c                 D    dd | D        vr| j                  d|d       yy)a6  Adds a environmental variable that points to the secret file.

  Add a environment varible where GOOGLE_APPLICATION_CREDENTIALS is the name
  and the path to the secret file is the value.

  Args:
    envs: (list[dict]) List of dictionaries with a name entry and value entry.
    path: (str) Path to secret.
  GOOGLE_APPLICATION_CREDENTIALSc              3   &   K   | ]	  }|d      ywr"  r*   )r#  r   s     r,   r$  z#_AddSecretEnvVar.<locals>.<genexpr>\  s     -JTcc&kTs   r>  N)rR   )r  rI   s     r,   r  r  R  s*     &-JT-JJKK9DIJ Kr+   c                 x    t        j                  t        j                  t        j                  |                   S )z*Encode a utf-8 string as a base 64 string.)r/  rm  base64	b64encodeensure_binary)ss    r,   r	  r	  `  s'    	))#*;*;A*>?	@@r+   c                     | j                  dd      j                         }t        t        j                               }|d dt        |      z
   |z   }d }|| k7  r| }||fS )Nrx   r      )r   r   r   r   r   r   )r0   new_nameumappeds       r,   rV   rV   e  sa    \\#s#))+(	$**,!msSV|$q((&F	6	r+   )NNNFr6   )yr)   
__future__r   r   r   r   r6  r  r  r~   os.pathr@  r   apitools.base.pyr   r   ru  googlecloudsdk.api_lib.appr	   r   googlecloudsdk.api_lib.runr
   r   r   googlecloudsdk.api_lib.utilr   r   r   googlecloudsdk.callioper   googlecloudsdk.command_lib.authr   googlecloudsdk.command_lib.coder   r   r   r   r   googlecloudsdk.command_lib.iamr   googlecloudsdk.command_lib.runr   googlecloudsdk.corer   r   r   r   googlecloudsdk.core.consoler   googlecloudsdk.core.utilr   r   r/  GetMessagesModulerr  rj  r   rB   rB  objectr   	TypeErrorr$   
DataObjectr.   r4   r@   rD   rF   rK   rd   rg   r   r   r  r   r   r,  r-  r1  r7  r9  r;  rF  rH  rY  compiler]  r_  r`  rM  rf  rP  ra  rO  rN  rQ  rS  r  r  r  r  r  r  r  r  r   r  r  r  r  r  r  r  r  r  r  r  r  r	  rV   r*   r+   r,   <module>rR     s   C &  % '    	  	  , > N 9 = , A ( 5 4 2 6 3 7 3 : & * # * $ 2 - * 
+T++E48 +T++,BDI ,d,,UD9 8 +
 H 6) 6J11 

**?*? 
	F	,*'' *1J)) *1Z+J)) +x(z$$ x(v	F6 &<"#* ' #$ $( $"&&+(V  
9&*%T )bjj@B 
 (RZZDF 
 &2::DF >2 !bjj!JK , A
&	,*.!& !H%!/ %!P< <
2.-- -< 0 $0 $NZ-- 
[>* [>| "   .-b A
>0
:6KA
r+   