77import click
88import json
99
10- from newrelic_lambda_cli .cliutils import failure , success
10+ from newrelic_lambda_cli .cliutils import failure , success , warning
1111from newrelic_lambda_cli .functions import get_function
1212from newrelic_lambda_cli .types import (
1313 IntegrationInstall ,
1414 IntegrationUninstall ,
1515 IntegrationUpdate ,
1616)
17- from newrelic_lambda_cli .utils import catch_boto_errors
17+ from newrelic_lambda_cli .utils import catch_boto_errors , NR_DOCS_ACT_LINKING_URL
1818
1919INGEST_STACK_NAME = "NewRelicLogIngestion"
2020LICENSE_KEY_STACK_NAME = "NewRelicLicenseKeySecret"
2121
2222__cached_license_key_policy_arn = None
23+ __cached_license_key_nr_account_id = None
2324
2425
2526def _get_role (session , role_name ):
@@ -44,10 +45,27 @@ def _check_for_ingest_stack(session):
4445 return _get_cf_stack_status (session , INGEST_STACK_NAME )
4546
4647
47- def _get_cf_stack_status (session , stack_name ):
48+ def _get_cf_stack_status (session , stack_name , nr_account_id = None ):
4849 """Returns the status of the CloudFormation stack if it exists"""
4950 try :
5051 res = session .client ("cloudformation" ).describe_stacks (StackName = stack_name )
52+ if nr_account_id is not None :
53+ stack_output_account_id = _get_stack_output_value (session , ["NrAccountId" ])
54+ # Checking length of outputs here to protect against installs done with older CLI versions.
55+ # We don't want to constantly warn users who installed on previous versions with no outputs.
56+ if (
57+ len (stack_output_account_id ) > 0
58+ and str (nr_account_id ) not in stack_output_account_id
59+ ):
60+ warning (
61+ "WARNING: Managed secret already exists in this region for New Relic account {0}.\n "
62+ "Current CLI behavior limits the setup of one managed secret per region.\n "
63+ "To set up an additional secret for New Relic account {1} see our docs:\n {2}.\n "
64+ "Or run this command with --disable-license-key-secret to avoid attemping to create a new managed secret." .format (
65+ stack_output_account_id , nr_account_id , NR_DOCS_ACT_LINKING_URL
66+ )
67+ )
68+
5169 except botocore .exceptions .ClientError as e :
5270 if (
5371 e .response
@@ -590,7 +608,9 @@ def auto_install_license_key(input):
590608@catch_boto_errors
591609def install_license_key (input , nr_license_key , policy_name = None , mode = "CREATE" ):
592610 assert isinstance (input , (IntegrationInstall , IntegrationUpdate ))
593- lk_stack_status = _get_cf_stack_status (input .session , LICENSE_KEY_STACK_NAME )
611+ lk_stack_status = _get_cf_stack_status (
612+ input .session , LICENSE_KEY_STACK_NAME , input .nr_account_id
613+ )
594614 if lk_stack_status is not None :
595615 success ("Managed secret already exists" )
596616 return True
@@ -611,8 +631,14 @@ def install_license_key(input, nr_license_key, policy_name=None, mode="CREATE"):
611631 elif update_mode :
612632 parameters .append ({"ParameterKey" : "PolicyName" , "UsePreviousValue" : True })
613633
614- parameters .append (
615- {"ParameterKey" : "LicenseKey" , "ParameterValue" : nr_license_key }
634+ parameters .extend (
635+ (
636+ {"ParameterKey" : "LicenseKey" , "ParameterValue" : nr_license_key },
637+ {
638+ "ParameterKey" : "NrAccountId" ,
639+ "ParameterValue" : str (input .nr_account_id ),
640+ },
641+ )
616642 )
617643
618644 change_set_name = "%s-%s-%d" % (
@@ -677,11 +703,24 @@ def remove_license_key(input):
677703 success ("Done" )
678704
679705
680- def _get_license_key_policy_arn (session ):
681- """Returns the policy ARN for the license key secret if it exists"""
706+ def _get_license_key_outputs (session ):
707+ """Returns the account id and policy ARN for the license key secret if they exist"""
708+ global __cached_license_key_nr_account_id
682709 global __cached_license_key_policy_arn
683- if __cached_license_key_policy_arn :
684- return __cached_license_key_policy_arn
710+ if __cached_license_key_nr_account_id and __cached_license_key_policy_arn :
711+ return [__cached_license_key_nr_account_id , __cached_license_key_policy_arn ]
712+
713+ account_id , policy_arn = _get_stack_output_value (
714+ session , ["NrAccountId" , "ViewPolicyARN" ]
715+ )
716+ if account_id is not None :
717+ __cached_license_key_nr_account_id = account_id
718+ if policy_arn is not None :
719+ __cached_license_key_policy_arn = policy_arn
720+ return [account_id , policy_arn ]
721+
722+
723+ def _get_stack_output_value (session , output_keys ):
685724 client = session .client ("cloudformation" )
686725 try :
687726 stacks = client .describe_stacks (StackName = LICENSE_KEY_STACK_NAME ).get (
@@ -700,13 +739,13 @@ def _get_license_key_policy_arn(session):
700739 if not stacks :
701740 return None
702741 stack = stacks [0 ]
703- output_key = "ViewPolicyARN"
704- for output in stack . get ( "Outputs" , []) :
705- if output [ "OutputKey" ] == output_key :
706- __cached_license_key_policy_arn = output ["OutputValue" ]
707- return __cached_license_key_policy_arn
708- else :
709- return None
742+ output_values = []
743+ for output_key in output_keys :
744+ for output in stack . get ( "Outputs" , []) :
745+ if output ["OutputKey" ] == output_key :
746+ value = output [ "OutputValue" ] or None
747+ output_values . append ( value )
748+ return output_values
710749
711750
712751@catch_boto_errors
0 commit comments