def ssm_run_command()

in source/msam/chalicelib/periodic.py [0:0]


def ssm_run_command():
    """
    Runs all applicable SSM document commands on a given managed instance.
    """
    try:
        table_name = CONTENT_TABLE_NAME
        ssm_client = boto3.client('ssm', config=MSAM_BOTO3_CONFIG)
        db_resource = boto3.resource('dynamodb', config=MSAM_BOTO3_CONFIG)
        db_table = db_resource.Table(table_name)
        instance_ids = {}
        # get all the managed instances from the DB with tag MSAM-NodeType
        response = db_table.query(
            IndexName="ServiceRegionIndex",
            KeyConditionExpression=Key("service").eq("ssm-managed-instance"),
            FilterExpression="contains(#data, :tagname)",
            ExpressionAttributeNames={"#data": "data"},
            ExpressionAttributeValues={":tagname": "MSAM-NodeType"}
            )
        items = response.get("Items", [])
        while "LastEvaluatedKey" in response:
            response = db_table.query(
            IndexName="ServiceRegionIndex",
            KeyConditionExpression=Key("service").eq("ssm-managed-instance"),
            FilterExpression="contains(#data, :tagname)",
            ExpressionAttributeNames={"#data": "data"},
            ExpressionAttributeValues={":tagname": "MSAM-NodeType"},
            ExclusiveStartKey=response['LastEvaluatedKey']
            )
            items.append(response.get("Items", []))

        for item in items:
            data = json.loads(item['data'])
            if "MSAM-NodeType" in data["Tags"]:
                instance_ids[data['Id']] = data['Tags']['MSAM-NodeType']

        # get all the SSM documents applicable to MSAM, filtering by MSAM-NodeType tag
        # When we support more than just ElementalLive, add to the list of values for MSAM-NodeType during filtering
        document_list = ssm_client.list_documents(
            Filters=[
                {
                    'Key': 'tag:MSAM-NodeType',
                    'Values': [
                        'ElementalLive',
                    ]
                },
                {
                    'Key': 'Owner',
                    'Values': [
                        'Self'
                    ]
                }
            ]
        )
        document_ids = document_list['DocumentIdentifiers']
        while "NextToken" in document_list:
            document_list = ssm_client.list_documents(
                Filters=[
                    {
                        'Key': 'tag:MSAM-NodeType',
                        'Values': [
                            'ElementalLive',
                        ]
                    },
                    {
                        'Key': 'Owner',
                        'Values': [
                            'Self'
                        ]
                    }
                ],
                NextToken=document_list["NextToken"]
            )
            document_ids.append(document_list['DocumentIdentifiers'])

        document_names = {}
        for document in document_ids:
            if "Tags" in document:
                for tag in document["Tags"]:
                    if tag['Key'] == "MSAM-NodeType":
                        document_names[document["Name"]] = tag['Value']

        # loop over all instances and run applicable commands based on node type
        for instance_id, id_type in instance_ids.items():
            for name, doc_type in document_names.items():
                if id_type in doc_type:
                    # maybe eventually doc type could be comma-delimited string if doc applies to more than one type?
                    print("running command: %s on %s " % (name, instance_id))
                    try:
                        response = ssm_client.send_command(
                            InstanceIds=[
                                instance_id,
                            ],
                            DocumentName=name,
                            TimeoutSeconds=600,
                            Parameters={
                            },
                            MaxConcurrency='50',
                            MaxErrors='0',
                            CloudWatchOutputConfig={
                                'CloudWatchLogGroupName': SSM_LOG_GROUP_NAME,
                                'CloudWatchOutputEnabled': True
                            }
                        )
                        print(response)
                    except ClientError as error:
                        print(error)
                        if error.response['Error']['Code'] == "InvalidInstanceId":
                            continue
    except ClientError as error:
        print(error)