def install_package_version(request, namespace, number): oauth = request.session.get('oauth_response', None) if not oauth: raise HttpResponse('Unauthorized', status=401) version = get_object_or_404(PackageVersion, package__namespace = namespace, number = number) # Log the install install = PackageInstallation( package = version.package, version = version, action = 'install', username = oauth['username'], org_id = oauth['org_id'], org_type = oauth['org_type'], status = 'Starting', ) install.save() request.session['mpinstaller_current_install'] = install.id endpoint = build_endpoint_url(oauth) # If we have a version number, install via a custom built metadata package using InstalledPackage if version.number: # Build a zip for the install package package_zip = PackageZipBuilder(namespace, number).install_package() else: try: zip_resp = requests.get(version.zip_url) zipfp = TemporaryFile() zipfp.write(zip_resp.content) zipfile = ZipFile(zipfp, 'r') zipfile.close() zipfp.seek(0) package_zip = base64.b64encode(zipfp.read()) # FIXME: Implement handling of the subdir field except: raise ValueError('Failed to fetch zip from %s' % version.zip_url) # Construct the SOAP envelope message message = SOAP_DEPLOY % {'package_zip': package_zip} message = message.encode('utf-8') headers = { 'Content-Type': "text/xml; charset=UTF-8", 'Content-Length': len(message), 'SOAPAction': 'deploy', } response = call_mdapi(request, url=endpoint, headers=headers, data=message) id = parseString(response.content).getElementsByTagName('id')[0].firstChild.nodeValue # Delete the cached org package versions if request.session.get('mpinstaller_org_packages', None) is not None: del request.session['mpinstaller_org_packages'] return HttpResponse(json.dumps({'process_id': id}), content_type='application/json')
def uninstall_package(request, namespace): package = get_object_or_404(Package, namespace = namespace) oauth = request.session.get('oauth_response', None) if not oauth: sf = SalesforceOAuth2(settings.MPINSTALLER_CLIENT_ID, settings.MPINSTALLER_CLIENT_SECRET, settings.MPINSTALLER_CALLBACK_URL) request.session['mpinstaller_package'] = namespace request.session['mpinstaller_version'] = 'uninstall' return HttpResponseRedirect(sf.authorize_url()) # Log the install install = PackageInstallation( package = package, action = 'uninstall', username = oauth['username'], org_id = oauth['org_id'], org_type = oauth['org_type'], status = 'Starting', ) install.save() request.session['mpinstaller_current_install'] = install.id endpoint = build_endpoint_url(oauth) # Build a zip for the install package package_zip = PackageZipBuilder(namespace).uninstall_package() # Construct the SOAP envelope message message = SOAP_DEPLOY % {'package_zip': package_zip} message = message.encode('utf-8') headers = { 'Content-Type': "text/xml; charset=UTF-8", 'Content-Length': len(message), 'SOAPAction': 'deploy', } response = call_mdapi(request, url=endpoint, headers=headers, data=message) id = parseString(response.content).getElementsByTagName('id')[0].firstChild.nodeValue # Delete the cached org package versions if request.session.get('mpinstaller_org_packages', None) is not None: del request.session['mpinstaller_org_packages'] return HttpResponse(json.dumps({'process_id': id}), content_type='application/json')
def start_package_installation(request, namespace, version_id): """ Kicks off a package installation and redirects to the installation's page """ version = get_object_or_404(PackageVersion, package__namespace=namespace, id=version_id) oauth = request.session.get('oauth', None) git_ref = request.GET.get('git_ref', None) fork = request.GET.get('fork', None) # Redirect back to the package overview page if not connected to an org if not oauth or not oauth.get('access_token'): redirect = version.get_installer_url(request) return HttpResponseRedirect(redirect) # Ensure installation is available in connected org, logout and redirect if not reason = check_installation_available(request, version) if reason: return HttpResponseRedirect( '/mpinstaller/%s/version/%s/installation-unavailable/%s' % (version.package.namespace, version.id, reason)) # This view should only be used for executing a map already reviewed by the user. # If there is no installed list or metadata list in session, that didn't happen for some reason installed = request.session.get('org_packages', None) if installed is None: return HttpResponseRedirect(version.get_installer_url(request)) metadata = request.session.get('metadata', None) if metadata is None: return HttpResponseRedirect(version.get_installer_url(request)) install_map = version_install_map(version, installed, metadata, git_ref, fork) installation_obj = PackageInstallation( package=version.package, version=version, git_ref=git_ref, fork=fork, org_id=oauth['org_id'], org_type=oauth['org_type'], instance_url=oauth['instance_url'], status='Pending', username=oauth['username'], install_map=install_map_to_json(install_map), ) installation_obj.save() # Temporarily save the needed session variables so background processes can do the work session_obj = PackageInstallationSession( installation=installation_obj, oauth=json.dumps(oauth), org_packages=json.dumps(installed), metadata=json.dumps(request.session.get('metadata', {})), ) session_obj.save() order = 0 for step in install_map: step_obj = PackageInstallationStep( installation=installation_obj, package=step['version'].package, version=step['version'], previous_version=step['installed'], action=step['action'], status='Pending', order=order, ) order += 1 if step_obj.action == 'skip': step_obj.status = 'Succeeded' step_obj.save() # Clear out the org_packages and metadata cached in session if 'org_packages' in request.session: del request.session['org_packages'] if 'metadata' in request.session: del request.session['metadata'] return HttpResponseRedirect('/mpinstaller/installation/%s' % installation_obj.id)
def deploy_commit_to_org(self, commit=None, sync=None): if not self.sf_oauth: if sync: sync.log += 'FAILED: No Saleforce Org credentials available to sync with DE org\n' sync.status = 'failed' sync.save() return # If there is currently an installation running, return None if self.last_deployment_installation and self.last_deployment_installation.status in ('Pending','In Progress'): if sync: sync.log += 'FAILED: Another installation is already in progress for this contribution. Please try again later\n' sync.status = 'failed' sync.save() return version = self.package_version oauth = self.decode_sf_oauth() if commit: git_ref = commit else: git_ref = self.fork_branch fork = self.contributor.user.username # Get installed packages in org api = ApiRetrieveInstalledPackages(oauth) if sync: sync.log += '--- Getting list of installed packages in org\n' sync.save() installed = api() if sync: sync.log += 'DONE' sync.save() if not installed: installed = {} # Store the access token from the api call if it changed if api.oauth != oauth: self.sf_oauth = json.dumps(api.oauth) # With GitHub installations, we don't run conditions since we dynamically construct the install map metadata = {} # Build the install map install_map = version_install_map(version, installed, metadata, git_ref, fork) if sync: sync.log += '--- Configuring installation steps\n' sync.save() # Build the Installation object installation_obj = PackageInstallation( package = version.package, version = version, git_ref = git_ref, fork = fork, org_id = oauth['org_id'], org_type = oauth['org_type'], instance_url = oauth['instance_url'], status = 'Pending', username = oauth['username'], install_map = install_map_to_json(install_map), ) installation_obj.save() # Create a PackageInstallationSession so we can reuse the same install method from mpinstaller session_obj = PackageInstallationSession( installation = installation_obj, oauth = json.dumps(oauth), org_packages = json.dumps(installed), metadata = json.dumps(metadata) ) session_obj.save() order = 0 # Create the PackageInstallationStep objects for step in install_map: step_obj = PackageInstallationStep( installation = installation_obj, package = step['version'].package, version = step['version'], previous_version = step['installed'], action = step['action'], status = 'Pending', order = order, ) order += 1 if step_obj.action == 'skip': step_obj.status = 'Succeeded' else: if sync: sync.log += '--- * %s: %s\n' % (step_obj.version, step_obj.action) sync.save() step_obj.save() if sync: sync.log += 'DONE\n\n' sync.log += '--- Starting installation #%s\n' % installation_obj.id sync.log += '--- * NOTE: This can take anywhere from 5-15 minutes to complete\n' sync.log += '--- * <a href="/mpinstaller/installation/%s" target="_blank">View installation status in separate tab</a>\n' % installation_obj.id sync.save() # Run the installer synchronously since we should already be inside a background process install_package_version(installation_obj.id) if sync: sync.log += 'DONE\n\n' sync.save() # Record the deployment on the Contribution if successful self.last_deployment_installation = installation_obj self.last_deployment_date = datetime.now() if installation_obj.status != 'Failed': if commit: self.last_deployed_commit = commit else: branch = self.get_fork_branch() self.last_deployed_commit = branch['object']['sha'] return installation_obj
def start_package_installation(request, namespace, version_id): """ Kicks off a package installation and redirects to the installation's page """ version = get_object_or_404(PackageVersion, package__namespace=namespace, id=version_id) oauth = request.session.get('oauth', None) git_ref = request.GET.get('git_ref',None) fork = request.GET.get('fork',None) # Redirect back to the package overview page if not connected to an org if not oauth or not oauth.get('access_token'): redirect = version.get_installer_url(request) return HttpResponseRedirect(redirect) # Ensure installation is available in connected org, logout and redirect if not reason = check_installation_available(request, version) if reason: return HttpResponseRedirect('/mpinstaller/%s/version/%s/installation-unavailable/%s' % (version.package.namespace, version.id, reason)) # This view should only be used for executing a map already reviewed by the user. # If there is no installed list or metadata list in session, that didn't happen for some reason installed = request.session.get('org_packages', None) if installed is None: return HttpResponseRedirect(version.get_installer_url(request)) metadata = request.session.get('metadata', None) if metadata is None: return HttpResponseRedirect(version.get_installer_url(request)) install_map = version_install_map(version, installed, metadata, git_ref, fork) installation_obj = PackageInstallation( package = version.package, version = version, git_ref = git_ref, fork = fork, org_id = oauth['org_id'], org_type = oauth['org_type'], instance_url = oauth['instance_url'], status = 'Pending', username = oauth['username'], install_map = install_map_to_json(install_map), ) installation_obj.save() # Temporarily save the needed session variables so background processes can do the work session_obj = PackageInstallationSession( installation = installation_obj, oauth = json.dumps(oauth), org_packages = json.dumps(installed), metadata = json.dumps(request.session.get('metadata', {})), ) session_obj.save() order = 0 for step in install_map: step_obj = PackageInstallationStep( installation = installation_obj, package = step['version'].package, version = step['version'], previous_version = step['installed'], action = step['action'], status = 'Pending', order = order, ) order += 1 if step_obj.action == 'skip': step_obj.status = 'Succeeded' step_obj.save() # Clear out the org_packages and metadata cached in session if 'org_packages' in request.session: del request.session['org_packages'] if 'metadata' in request.session: del request.session['metadata'] return HttpResponseRedirect('/mpinstaller/installation/%s' % installation_obj.id)