def ProvisionProducts()

in bulkprovision/bulkexecute/__init__.py [0:0]


    def ProvisionProducts(self):
        '''
        This will go through the Dynamo table from the config and provision the given product using the params from matching the incoming scparams list.
        '''
        # config overides SSM
        sc_param_keys = self.get_config_value("scparams").split(',')
        sc_productid = self.get_config_value("scproductid")
        sc_paid = self.get_config_value("scpaid")
        provision_threshold = self.get_config_value("provision_threshold")
        if provision_threshold is None:
            provision_threshold = 10
        
        # try to get them from SSM
        if sc_productid is None:
            sc_productid = self.ssm_get_parameter("/bulkdeploy/productid")
        if sc_paid is None:
            arr = self.ssm_get_parameter("/bulkdeploy/provisioningid").split('|')
            # grab the first if there are many
            sc_paid = arr[0]
        
        # get new items        
        new_items = self.dynamo_query_multi("status",["NEW","RETRY"])
        logger.info("Found {} new items to provision".format(len(new_items)))
        count = 0
        errors = 0
        for drow in new_items[:provision_threshold]:
            # setup variables to use later
            arr_params = []
            guidkey = drow["guidkey"]                                                    
            param_dict = drow["launchparams"]
            failed = False
            ppdetails = None
            errordetails = None
            dbstatus = "PROVISIONING"
            # keep the error message if we have one
            if "errordetails" in drow:
                errordetails = drow["errordetails"]
            
            try:
                # Map the incoming launchparams from the dynamo entry to the launch params from our event config
                for paramkey in sc_param_keys:
                    par_obj = { "Key":paramkey,"Value":param_dict[paramkey] }
                    arr_params.append(par_obj)               
                
                # provision the product and record the important parts of the response
                resp = self.sc_provision_product(sc_productid, sc_paid, guidkey, arr_params)
                ppdetails = {
                    'ProvisionedProductId':resp['RecordDetail']['ProvisionedProductId'],
                    'RecordId':resp['RecordDetail']['RecordId'],
                    'CreatedTime':str(resp['RecordDetail']['CreatedTime']),
                    'Status': resp['RecordDetail']['Status']
                }
            except ClientError as ce:
                # something wrong from the API call. this is where you will see the CFn Errors
                msg = ce.response['Error']['Message']
                logger.error("ClientError: {}".format(msg))
                if ce.response['Error']['Code'] == "InvalidParametersException" and msg == "A stack named {} already exists.".format(guidkey):
                    # we got a duplicate???  just fail it, no need to retry
                    errors += 1
                    dbstatus = "DUPLICATE"
                else:
                    errordetails = ce.response['Error']
                    failed = True            
            except  KeyError as ke:
                msg = "PROVISION-ERROR: Keys from CSV do not match template! Could not find {}".format(ke)
                logger.error(msg)
                errordetails = msg
                failed = True            
            except Exception as e:
                # Something else wrong?
                logger.error(e)                                
                failed = True
            else:
                count += 1
            
            # mark the status according to the outcome from above            
            if failed:
                errors += 1
                dbstatus = "PROVISION-ERROR"
                
            #update the dynamo table
            self.updateItem(guidkey,drow["status"],dbstatus, param_dict, ppdetails, errordetails)            
                    
        if len(new_items) > 0:
            logger.info("Provisioned {} of {} new products with {} errors using ProductID:{} PAID:{}".format(count, len(new_items), errors, sc_productid, sc_paid))
        return(self.generate_return(count))