11import { expect } from "chai" ;
22import * as nock from "nock" ;
3+ import type { ParsedUrlQuery } from "querystring" ;
34
45import * as cloudfunctionsv2 from "./cloudfunctionsv2" ;
56import * as backend from "../deploy/functions/backend" ;
@@ -722,6 +723,45 @@ describe("cloudfunctionsv2", () => {
722723 } ) ;
723724 } ) ;
724725
726+ it ( "should preserve null service account" , ( ) => {
727+ expect (
728+ cloudfunctionsv2 . endpointFromFunction ( {
729+ ...HAVE_CLOUD_FUNCTION_V2 ,
730+ serviceConfig : {
731+ ...HAVE_CLOUD_FUNCTION_V2 . serviceConfig ,
732+ service : "service" ,
733+ uri : RUN_URI ,
734+ serviceAccountEmail : null ,
735+ } ,
736+ } ) ,
737+ ) . to . deep . equal ( {
738+ ...ENDPOINT ,
739+ httpsTrigger : { } ,
740+ platform : "gcfv2" ,
741+ uri : GCF_URL ,
742+ serviceAccount : null ,
743+ } ) ;
744+ } ) ;
745+
746+ it ( "should leave service account unset when omitted" , ( ) => {
747+ const endpoint = cloudfunctionsv2 . endpointFromFunction ( {
748+ ...HAVE_CLOUD_FUNCTION_V2 ,
749+ serviceConfig : {
750+ ...HAVE_CLOUD_FUNCTION_V2 . serviceConfig ,
751+ service : "service" ,
752+ uri : RUN_URI ,
753+ } ,
754+ } ) ;
755+
756+ expect ( endpoint ) . to . deep . equal ( {
757+ ...ENDPOINT ,
758+ httpsTrigger : { } ,
759+ platform : "gcfv2" ,
760+ uri : GCF_URL ,
761+ } ) ;
762+ expect ( endpoint ) . not . to . have . property ( "serviceAccount" ) ;
763+ } ) ;
764+
725765 it ( "should transform fields" , ( ) => {
726766 const extraFields : backend . ServiceConfiguration = {
727767 minInstances : 1 ,
@@ -874,6 +914,19 @@ describe("cloudfunctionsv2", () => {
874914 } ) ;
875915
876916 describe ( "updateFunction" , ( ) => {
917+ const expectServiceAccountUpdateMask = ( queryParams : ParsedUrlQuery ) : boolean => {
918+ const updateMask = queryParams . updateMask ;
919+ expect ( updateMask ) . to . be . a ( "string" ) ;
920+ if ( typeof updateMask !== "string" ) {
921+ return false ;
922+ }
923+ expect ( updateMask . split ( "," ) ) . to . include . members ( [
924+ "buildConfig.serviceAccount" ,
925+ "serviceConfig.serviceAccountEmail" ,
926+ ] ) ;
927+ return true ;
928+ } ;
929+
877930 it ( "should set default environment variables" , async ( ) => {
878931 const scope = nock ( functionsV2Origin ( ) )
879932 . patch ( "/v2/projects/project/locations/region/functions/id" , ( body ) => {
@@ -897,5 +950,65 @@ describe("cloudfunctionsv2", () => {
897950 await cloudfunctionsv2 . updateFunction ( CLOUD_FUNCTION_V2 ) ;
898951 expect ( scope . isDone ( ) ) . to . be . true ;
899952 } ) ;
953+
954+ it ( "should include custom service account fields in update mask" , async ( ) => {
955+ const testFunction : cloudfunctionsv2 . InputCloudFunction = {
956+ ...CLOUD_FUNCTION_V2 ,
957+ buildConfig : {
958+ ...CLOUD_FUNCTION_V2 . buildConfig ,
959+ serviceAccount : "projects/project/serviceAccounts/inlined@google.com" ,
960+ } ,
961+ serviceConfig : {
962+ ...CLOUD_FUNCTION_V2 . serviceConfig ,
963+ serviceAccountEmail : "inlined@google.com" ,
964+ } ,
965+ } ;
966+
967+ const scope = nock ( functionsV2Origin ( ) )
968+ . patch (
969+ "/v2/projects/project/locations/region/functions/id" ,
970+ ( body : cloudfunctionsv2 . InputCloudFunction ) => {
971+ expect ( body . buildConfig . serviceAccount ) . to . equal (
972+ "projects/project/serviceAccounts/inlined@google.com" ,
973+ ) ;
974+ expect ( body . serviceConfig . serviceAccountEmail ) . to . equal ( "inlined@google.com" ) ;
975+ return true ;
976+ } ,
977+ )
978+ . query ( expectServiceAccountUpdateMask )
979+ . reply ( 200 , { name : "operations/123" , done : true } ) ;
980+
981+ await cloudfunctionsv2 . updateFunction ( testFunction ) ;
982+ expect ( scope . isDone ( ) ) . to . be . true ;
983+ } ) ;
984+
985+ it ( "should include null service account fields in update mask" , async ( ) => {
986+ const testFunction : cloudfunctionsv2 . InputCloudFunction = {
987+ ...CLOUD_FUNCTION_V2 ,
988+ buildConfig : {
989+ ...CLOUD_FUNCTION_V2 . buildConfig ,
990+ serviceAccount : null ,
991+ } ,
992+ serviceConfig : {
993+ ...CLOUD_FUNCTION_V2 . serviceConfig ,
994+ serviceAccountEmail : null ,
995+ } ,
996+ } ;
997+
998+ const scope = nock ( functionsV2Origin ( ) )
999+ . patch (
1000+ "/v2/projects/project/locations/region/functions/id" ,
1001+ ( body : cloudfunctionsv2 . InputCloudFunction ) => {
1002+ expect ( body . buildConfig . serviceAccount ) . to . equal ( null ) ;
1003+ expect ( body . serviceConfig . serviceAccountEmail ) . to . equal ( null ) ;
1004+ return true ;
1005+ } ,
1006+ )
1007+ . query ( expectServiceAccountUpdateMask )
1008+ . reply ( 200 , { name : "operations/123" , done : true } ) ;
1009+
1010+ await cloudfunctionsv2 . updateFunction ( testFunction ) ;
1011+ expect ( scope . isDone ( ) ) . to . be . true ;
1012+ } ) ;
9001013 } ) ;
9011014} ) ;
0 commit comments