55 "errors"
66 "fmt"
77 "sort"
8+ "strconv"
89 "strings"
910
1011 "github.com/temporalio/tcld/protogen/api/account/v1"
@@ -18,13 +19,12 @@ import (
1819)
1920
2021const (
21- auditLogSinkTypeFlagName = "audit-log-sink-type"
22- destinationUriFlagName = "destination-uri"
23- sinkServiceAccountIDFlagName = "service-account-id"
24- topicNameFlagName = "topic-name"
25- roleNameFlagName = "role-name"
26- kinesisAuditLogSinkType = "kinesis"
27- pubsubAuditLogSinkType = "pubsub"
22+ destinationUriFlagName = "destination-uri"
23+ topicNameFlagName = "topic-name"
24+ roleNameFlagName = "role-name"
25+ kinesisAuditLogSinkType = "kinesis"
26+ pubsubAuditLogSinkType = "pubsub"
27+ sinkServiceAccountEmailFlagName = "service-account-email"
2828)
2929
3030var (
@@ -34,36 +34,55 @@ var (
3434 Aliases : []string {"du" },
3535 Required : true ,
3636 }
37- sinkServiceAccountIDFlag = & cli.StringFlag {
38- Name : sinkServiceAccountIDFlagName ,
39- Usage : "The service account ID to impersonate to write to the sink" ,
40- Aliases : []string {"sai" },
37+ destinationUriFlagOptional = & cli.StringFlag {
38+ Name : destinationUriFlagName ,
39+ Usage : "The destination URI of the audit log sink" ,
40+ Aliases : []string {"du" },
41+ }
42+ sinkServiceAccountEmailFlag = & cli.StringFlag {
43+ Name : sinkServiceAccountEmailFlagName ,
44+ Usage : "The service account email to impersonate to write to the sink" ,
45+ Aliases : []string {"sae" },
4146 Required : true ,
4247 }
48+ sinkServiceAccountEmailFlagOptional = & cli.StringFlag {
49+ Name : sinkServiceAccountEmailFlagName ,
50+ Usage : "The service account email to impersonate to write to the sink" ,
51+ Aliases : []string {"sae" },
52+ }
4353 roleNameFlag = & cli.StringFlag {
4454 Name : roleNameFlagName ,
4555 Usage : "The role name to use to write to the sink" ,
4656 Aliases : []string {"rn" },
4757 Required : true ,
4858 }
59+ roleNameFlagOptional = & cli.StringFlag {
60+ Name : roleNameFlagName ,
61+ Usage : "The role name to use to write to the sink" ,
62+ Aliases : []string {"rn" },
63+ }
4964 topicNameFlag = & cli.StringFlag {
5065 Name : topicNameFlagName ,
5166 Usage : "The topic name to write to the sink" ,
5267 Aliases : []string {"tn" },
5368 Required : true ,
5469 }
55- gcpProjectIdFlag = & cli.StringFlag {
56- Name : gcpProjectIdFlagName ,
57- Usage : "The GCP project ID to write to the sink" ,
58- Aliases : []string {"gpi" },
59- Required : true ,
70+ topicNameFlagOptional = & cli.StringFlag {
71+ Name : topicNameFlagName ,
72+ Usage : "The topic name to write to the sink" ,
73+ Aliases : []string {"tn" },
6074 }
6175 sinkRegionFlagRequired = & cli.StringFlag {
6276 Name : sinkRegionFlagName ,
6377 Usage : "The region to use for the request" ,
6478 Aliases : []string {"re" },
6579 Required : true ,
6680 }
81+ sinkRegionFlagOptional = & cli.StringFlag {
82+ Name : sinkRegionFlagName ,
83+ Usage : "The region to use for the request" ,
84+ Aliases : []string {"re" },
85+ }
6786)
6887
6988type AccountClient struct {
@@ -169,38 +188,36 @@ func (c *AccountClient) parseExistingMetricsCerts(ctx *cli.Context) (account *ac
169188 return a , existingCerts , nil
170189}
171190
172- func toAuditLogSinkSpec (ctx * cli.Context , auditLogSinkType string ) (* cloudaccount.AuditLogSinkSpec , error ) {
173- spec := & cloudaccount.AuditLogSinkSpec {
174- Name : ctx .String (sinkNameFlag .Name ),
175- Enabled : ctx .Bool (sinkEnabledFlag .Name ),
176- }
177- switch auditLogSinkType {
178- case kinesisAuditLogSinkType :
179- {
180- spec .SinkType = & cloudaccount.AuditLogSinkSpec_KinesisSink {
181- KinesisSink : & cloudSink.KinesisSpec {
182- RoleName : ctx .String (roleNameFlag .Name ),
183- DestinationUri : ctx .String (destinationUriFlag .Name ),
184- Region : ctx .String (sinkRegionFlagRequired .Name ),
185- },
186- }
187- }
188- case pubsubAuditLogSinkType :
189- {
190- spec .SinkType = & cloudaccount.AuditLogSinkSpec_PubSubSink {
191- PubSubSink : & cloudSink.PubSubSpec {
192- ServiceAccountId : ctx .String (sinkServiceAccountIDFlag .Name ),
193- TopicName : ctx .String (topicNameFlag .Name ),
194- GcpProjectId : ctx .String (gcpProjectIdFlag .Name ),
195- },
196- }
197- }
198- default :
199- {
200- return nil , fmt .Errorf ("invalid audit log sink type: %s" , auditLogSinkType )
201- }
191+ func toKinesisAuditLogSinkSpec (ctx * cli.Context , name string , enabled bool , roleName string , destinationUri string , region string ) (* cloudaccount.AuditLogSinkSpec , error ) {
192+ return & cloudaccount.AuditLogSinkSpec {
193+ Name : name ,
194+ Enabled : enabled ,
195+ SinkType : & cloudaccount.AuditLogSinkSpec_KinesisSink {
196+ KinesisSink : & cloudSink.KinesisSpec {
197+ RoleName : roleName ,
198+ DestinationUri : destinationUri ,
199+ Region : region ,
200+ },
201+ },
202+ }, nil
203+ }
204+
205+ func toPubsubAuditLogSinkSpec (ctx * cli.Context , name string , enabled bool , serviceAccountEmail string , topicName string ) (* cloudaccount.AuditLogSinkSpec , error ) {
206+ saId , gcpProjectId , err := parseSAPrincipal (serviceAccountEmail )
207+ if err != nil {
208+ return nil , err
202209 }
203- return spec , nil
210+ return & cloudaccount.AuditLogSinkSpec {
211+ Name : name ,
212+ Enabled : enabled ,
213+ SinkType : & cloudaccount.AuditLogSinkSpec_PubSubSink {
214+ PubSubSink : & cloudSink.PubSubSpec {
215+ ServiceAccountId : saId ,
216+ TopicName : topicName ,
217+ GcpProjectId : gcpProjectId ,
218+ },
219+ },
220+ }, nil
204221}
205222
206223func (c * AccountClient ) createAuditLogSink (spec * cloudaccount.AuditLogSinkSpec ) (* cloudservice.CreateAccountAuditLogSinkResponse , error ) {
@@ -213,17 +230,23 @@ func (c *AccountClient) createAuditLogSink(spec *cloudaccount.AuditLogSinkSpec)
213230 return createAuditLogSinkResp , nil
214231}
215232
216- func (c * AccountClient ) updateAuditLogSink (ctx * cli.Context , spec * cloudaccount.AuditLogSinkSpec , resourceVersion string ) (* cloudservice.UpdateAccountAuditLogSinkResponse , error ) {
217- if resourceVersion == "" {
218- getAuditLogSinkRes , err := c .cloudAPIClient .GetAccountAuditLogSink (c .ctx , & cloudservice.GetAccountAuditLogSinkRequest {
219- Name : ctx .String (sinkNameFlag .Name ),
220- })
221- if err != nil {
222- return nil , fmt .Errorf ("unable to get audit log sink: %v" , err )
223- }
224- resourceVersion = getAuditLogSinkRes .GetSink ().GetResourceVersion ()
233+ func (c * AccountClient ) isSinkToggleChange (ctx * cli.Context , sink * cloudaccount.AuditLogSink ) (bool , error ) {
234+ if ! ctx .IsSet (sinkEnabledFlag .Name ) {
235+ return false , nil
236+ }
237+
238+ enabledValue , err := strconv .ParseBool (ctx .String (sinkEnabledFlag .Name ))
239+ if err != nil {
240+ return false , fmt .Errorf ("invalid value for enabled flag: %w. Only allowed true or false" , err )
241+ }
242+
243+ if sink .GetSpec ().GetEnabled () == enabledValue {
244+ return false , nil
225245 }
246+ return true , nil
247+ }
226248
249+ func (c * AccountClient ) updateAuditLogSink (ctx * cli.Context , resourceVersion string , spec * cloudaccount.AuditLogSinkSpec ) (* cloudservice.UpdateAccountAuditLogSinkResponse , error ) {
227250 updateAuditLogSinkRes , err := c .cloudAPIClient .UpdateAccountAuditLogSink (c .ctx , & cloudservice.UpdateAccountAuditLogSinkRequest {
228251 Spec : spec ,
229252 ResourceVersion : resourceVersion ,
@@ -603,7 +626,12 @@ func NewAccountCommand(getAccountClientFn GetAccountClientFn) (CommandOut, error
603626 sinkRegionFlagRequired ,
604627 },
605628 Action : func (ctx * cli.Context ) error {
606- spec , err := toAuditLogSinkSpec (ctx , kinesisAuditLogSinkType )
629+ name := ctx .String (sinkNameFlag .Name )
630+ enabled := true
631+ roleName := ctx .String (roleNameFlag .Name )
632+ destinationUri := ctx .String (destinationUriFlag .Name )
633+ region := ctx .String (sinkRegionFlagRequired .Name )
634+ spec , err := toKinesisAuditLogSinkSpec (ctx , name , enabled , roleName , destinationUri , region )
607635 if err != nil {
608636 return err
609637 }
@@ -629,7 +657,12 @@ func NewAccountCommand(getAccountClientFn GetAccountClientFn) (CommandOut, error
629657 sinkRegionFlagRequired ,
630658 },
631659 Action : func (ctx * cli.Context ) error {
632- spec , err := toAuditLogSinkSpec (ctx , kinesisAuditLogSinkType )
660+ name := ctx .String (sinkNameFlag .Name )
661+ enabled := true
662+ roleName := ctx .String (roleNameFlag .Name )
663+ destinationUri := ctx .String (destinationUriFlag .Name )
664+ region := ctx .String (sinkRegionFlagRequired .Name )
665+ spec , err := toKinesisAuditLogSinkSpec (ctx , name , enabled , roleName , destinationUri , region )
633666 if err != nil {
634667 return err
635668 }
@@ -651,17 +684,52 @@ func NewAccountCommand(getAccountClientFn GetAccountClientFn) (CommandOut, error
651684 sinkEnabledFlag ,
652685 ResourceVersionFlag ,
653686 // kinesis audit log sink flags
654- roleNameFlag ,
655- destinationUriFlag ,
656- sinkRegionFlagRequired ,
687+ roleNameFlagOptional ,
688+ destinationUriFlagOptional ,
689+ sinkRegionFlagOptional ,
657690 },
658691 Action : func (ctx * cli.Context ) error {
659- spec , err := toAuditLogSinkSpec (ctx , kinesisAuditLogSinkType )
692+ sinkName := ctx .String (sinkNameFlag .Name )
693+ getAuditLogSinkRes , err := c .cloudAPIClient .GetAccountAuditLogSink (c .ctx , & cloudservice.GetAccountAuditLogSinkRequest {
694+ Name : sinkName ,
695+ })
660696 if err != nil {
661- return err
697+ return fmt . Errorf ( "unable to get audit log sink: %v" , err )
662698 }
699+
663700 resourceVersion := ctx .String (ResourceVersionFlag .Name )
664- updateAuditLogSinkRes , err := c .updateAuditLogSink (ctx , spec , resourceVersion )
701+ if resourceVersion == "" {
702+ resourceVersion = getAuditLogSinkRes .GetSink ().GetResourceVersion ()
703+ }
704+
705+ spec := getAuditLogSinkRes .GetSink ().GetSpec ()
706+ isToggleChanged , err := c .isSinkToggleChange (ctx , getAuditLogSinkRes .GetSink ())
707+ if err != nil {
708+ return err
709+ }
710+
711+ if ! isToggleChanged && ! ctx .IsSet (roleNameFlagOptional .Name ) && ! ctx .IsSet (destinationUriFlagOptional .Name ) && ! ctx .IsSet (sinkRegionFlagOptional .Name ) {
712+ fmt .Println ("nothing to update" )
713+ return nil
714+ }
715+
716+ if isToggleChanged {
717+ spec .Enabled = ! spec .Enabled
718+ }
719+
720+ if ctx .IsSet (roleNameFlagOptional .Name ) {
721+ spec .GetKinesisSink ().RoleName = ctx .String (roleNameFlagOptional .Name )
722+ }
723+
724+ if ctx .IsSet (destinationUriFlagOptional .Name ) {
725+ spec .GetKinesisSink ().DestinationUri = ctx .String (destinationUriFlagOptional .Name )
726+ }
727+
728+ if ctx .IsSet (sinkRegionFlagOptional .Name ) {
729+ spec .GetKinesisSink ().Region = ctx .String (sinkRegionFlagOptional .Name )
730+ }
731+
732+ updateAuditLogSinkRes , err := c .updateAuditLogSink (ctx , resourceVersion , spec )
665733 if err != nil {
666734 return err
667735 }
@@ -685,12 +753,15 @@ func NewAccountCommand(getAccountClientFn GetAccountClientFn) (CommandOut, error
685753 // general audit log sink flags
686754 sinkNameFlag ,
687755 // pubsub audit log sink flags
688- sinkServiceAccountIDFlag ,
756+ sinkServiceAccountEmailFlag ,
689757 topicNameFlag ,
690- gcpProjectIdFlag ,
691758 },
692759 Action : func (ctx * cli.Context ) error {
693- spec , err := toAuditLogSinkSpec (ctx , pubsubAuditLogSinkType )
760+ name := ctx .String (sinkNameFlag .Name )
761+ enabled := true
762+ serviceAccountEmail := ctx .String (sinkServiceAccountEmailFlag .Name )
763+ topicName := ctx .String (topicNameFlag .Name )
764+ spec , err := toPubsubAuditLogSinkSpec (ctx , name , enabled , serviceAccountEmail , topicName )
694765 if err != nil {
695766 return err
696767 }
@@ -711,12 +782,15 @@ func NewAccountCommand(getAccountClientFn GetAccountClientFn) (CommandOut, error
711782 sinkNameFlag ,
712783 sinkEnabledFlag ,
713784 // pubsub audit log sink flags
714- sinkServiceAccountIDFlag ,
785+ sinkServiceAccountEmailFlag ,
715786 topicNameFlag ,
716- gcpProjectIdFlag ,
717787 },
718788 Action : func (ctx * cli.Context ) error {
719- spec , err := toAuditLogSinkSpec (ctx , pubsubAuditLogSinkType )
789+ name := ctx .String (sinkNameFlag .Name )
790+ enabled := true
791+ serviceAccountEmail := ctx .String (sinkServiceAccountEmailFlag .Name )
792+ topicName := ctx .String (topicNameFlag .Name )
793+ spec , err := toPubsubAuditLogSinkSpec (ctx , name , enabled , serviceAccountEmail , topicName )
720794 if err != nil {
721795 return err
722796 }
@@ -738,17 +812,52 @@ func NewAccountCommand(getAccountClientFn GetAccountClientFn) (CommandOut, error
738812 sinkEnabledFlag ,
739813 ResourceVersionFlag ,
740814 // pubsub audit log sink flags
741- sinkServiceAccountIDFlag ,
742- topicNameFlag ,
743- gcpProjectIdFlag ,
815+ sinkServiceAccountEmailFlagOptional ,
816+ topicNameFlagOptional ,
744817 },
745818 Action : func (ctx * cli.Context ) error {
746- spec , err := toAuditLogSinkSpec (ctx , pubsubAuditLogSinkType )
819+ sinkName := ctx .String (sinkNameFlag .Name )
820+ getAuditLogSinkRes , err := c .cloudAPIClient .GetAccountAuditLogSink (c .ctx , & cloudservice.GetAccountAuditLogSinkRequest {
821+ Name : sinkName ,
822+ })
747823 if err != nil {
748- return err
824+ return fmt . Errorf ( "unable to get audit log sink: %v" , err )
749825 }
826+
750827 resourceVersion := ctx .String (ResourceVersionFlag .Name )
751- updateAuditLogSinkRes , err := c .updateAuditLogSink (ctx , spec , resourceVersion )
828+ if resourceVersion == "" {
829+ resourceVersion = getAuditLogSinkRes .GetSink ().GetResourceVersion ()
830+ }
831+
832+ spec := getAuditLogSinkRes .GetSink ().GetSpec ()
833+ isToggleChanged , err := c .isSinkToggleChange (ctx , getAuditLogSinkRes .GetSink ())
834+ if err != nil {
835+ return err
836+ }
837+
838+ if ! isToggleChanged && ! ctx .IsSet (sinkServiceAccountEmailFlagOptional .Name ) && ! ctx .IsSet (topicNameFlagOptional .Name ) {
839+ fmt .Println ("nothing to update" )
840+ return nil
841+ }
842+
843+ if isToggleChanged {
844+ spec .Enabled = ! spec .Enabled
845+ }
846+
847+ if ctx .IsSet (sinkServiceAccountEmailFlagOptional .Name ) {
848+ saId , gcpProjectId , err := parseSAPrincipal (ctx .String (sinkServiceAccountEmailFlagOptional .Name ))
849+ if err != nil {
850+ return err
851+ }
852+ spec .GetPubSubSink ().ServiceAccountId = saId
853+ spec .GetPubSubSink ().GcpProjectId = gcpProjectId
854+ }
855+
856+ if ctx .IsSet (topicNameFlagOptional .Name ) {
857+ spec .GetPubSubSink ().TopicName = ctx .String (topicNameFlagOptional .Name )
858+ }
859+
860+ updateAuditLogSinkRes , err := c .updateAuditLogSink (ctx , resourceVersion , spec )
752861 if err != nil {
753862 return err
754863 }
0 commit comments