def attach_with_token( cfg: config.UAConfig, token: str, allow_enable: bool ) -> None: """ Common functionality to take a token and attach via contract backend :raise UrlError: On unexpected connectivity issues to contract server or inability to access identity doc from metadata service. :raise ContractAPIError: On unexpected errors when talking to the contract server. """ from uaclient.jobs.update_messaging import update_apt_and_motd_messages try: contract.request_updated_contract( cfg, token, allow_enable=allow_enable ) except exceptions.UrlError as exc: # Persist updated status in the event of partial attach ua_status.status(cfg=cfg) update_apt_and_motd_messages(cfg) raise exc except exceptions.UserFacingError as exc: # Persist updated status in the event of partial attach ua_status.status(cfg=cfg) update_apt_and_motd_messages(cfg) raise exc current_iid = identity.get_instance_id() if current_iid: cfg.write_cache("instance-id", current_iid) update_apt_and_motd_messages(cfg)
def test_use_cloud_init_query_when_non_trusty(self, m_get_platform_info, m_subp, series): """Get instance_id from cloud-init query when not on trusty.""" m_get_platform_info.return_value = {"series": series} assert "my-iid" == get_instance_id(_iid_file="IRRELEVANT") assert 1 == m_get_platform_info.call_count assert [mock.call(["cloud-init", "query", "instance_id"])] == m_subp.call_args_list
def test_use_var_lib_cloud_data_instance_id_when_cloud_id_unavailable( self, m_get_platform_info, m_subp, tmpdir): """Get instance-id from cloud-init instance-id artifact on trusty""" m_get_platform_info.return_value = {"series": "trusty"} iid_file = tmpdir.join("instance-id") iid_file.write("persisted-iid") assert "persisted-iid" == get_instance_id(_iid_file=iid_file.strpath) assert 1 == m_get_platform_info.call_count assert 0 == m_subp.call_count
def _get_contract_token_from_cloud_identity(cfg: config.UAConfig) -> str: """Detect cloud_type and request a contract token from identity info. :param cfg: a ``config.UAConfig`` instance :raise NonAutoAttachImageError: When not on an auto-attach image type. :raise UrlError: On unexpected connectivity issues to contract server or inability to access identity doc from metadata service. :raise ContractAPIError: On unexpected errors when talking to the contract server. :raise NonAutoAttachImageError: If this cloud type does not have auto-attach support. :return: contract token obtained from identity doc """ try: instance = identity.cloud_instance_factory() except exceptions.UserFacingError as e: if cfg.is_attached: # We are attached on non-Pro Image, just report already attached raise exceptions.AlreadyAttachedError(cfg) # Unattached on non-Pro return UserFacing error msg details raise e current_iid = identity.get_instance_id() if cfg.is_attached: prev_iid = cfg.read_cache("instance-id") if current_iid == prev_iid: raise exceptions.AlreadyAttachedError(cfg) print("Re-attaching Ubuntu Advantage subscription on new instance") if _detach(cfg, assume_yes=True) != 0: raise exceptions.UserFacingError( ua_status.MESSAGE_DETACH_AUTOMATION_FAILURE ) contract_client = contract.UAContractClient(cfg) try: tokenResponse = contract_client.request_auto_attach_contract_token( instance=instance ) except contract.ContractAPIError as e: if e.code and 400 <= e.code < 500: raise exceptions.NonAutoAttachImageError( ua_status.MESSAGE_UNSUPPORTED_AUTO_ATTACH ) raise e if current_iid: cfg.write_cache("instance-id", current_iid) return tokenResponse["contractToken"]
def test_none_when_cloud_init_query_fails(self, m_subp): """Return None when cloud-init query fails.""" assert None is get_instance_id() assert [mock.call(["cloud-init", "query", "instance_id"])] == m_subp.call_args_list
def test_use_cloud_init_query(self, m_subp): """Get instance_id from cloud-init query.""" assert "my-iid" == get_instance_id() assert [mock.call(["cloud-init", "query", "instance_id"])] == m_subp.call_args_list