def __init__(self, component, version, **kwargs): """Class initialization Parameters ---------- component : str the extension component version : str the extension component version **kwargs : optional keyword arguments Keyword Arguments ----------------- use_latest_metadata : bool use latest metadata (will be retrieved from remote CDN) Returns ------- None """ self.logger = Logger(__name__).get_logger() self.use_latest_metadata = kwargs.pop('use_latest_metadata', False) self.extension_metadata = self._load_metadata() self.component = self._validate_component(component) self.version = self._validate_component_version( self.component, version or self.get_latest_version())
def __init__(self, host, **kwargs): """Class initialization Parameters ---------- host : str the hostname of the device **kwargs : optional keyword arguments Keyword Arguments ----------------- port : int the port to assign to the port attribute user : str the username for device authentication password : str the password for device authentication private_key_file : str the file containing the private key for device authentication set_user_password : str sets the user password to this value - used along with private_key_file token : str the token to assign to the token attribute skip_ready_check : bool skips the device ready check if set to true Returns ------- None """ self.logger = Logger(__name__).get_logger() self.host = host.split(':')[0] # disallow providing port here self.port = int(kwargs.pop('port', None) or self._discover_port()) self._user = kwargs.pop('user', None) self._password = kwargs.pop('password', None) self._private_key_file = kwargs.pop('private_key_file', None) self._set_user_password = kwargs.pop('set_user_password', None) self.token = kwargs.pop('token', None) self.token_details = {} # check device is ready if not kwargs.pop('skip_ready_check', False): self._is_ready() # handle multiple authentication mechanisms if self._user and self._password: self._login_using_credentials() elif self._user and self._private_key_file: self._set_password_using_key() self._login_using_credentials() elif self.token: pass else: raise Exception( 'user|password, user|private_key_file or token required')
def test_logger_can_log(): """Test: logger can log Assertions ---------- - _log method should be called with 40, 'foo' """ # pylint: disable=protected-access logger = Logger(LOGGER_NAME).get_logger() logger._log = Mock() logger.error('foo') logger._log.assert_called_with(40, 'foo', ())
def test_logger_with_custom_trace_level(): """Test: logger can log with custom trace level Assertions ---------- - _log method should be called with 5, 'foo' """ # pylint: disable=protected-access logger = Logger(LOGGER_NAME, level='TRACE').get_logger() logger._log = Mock() logger.trace('foo') logger._log.assert_called_with(5, 'foo', ())
def __init__(self, client, component, **kwargs): """Class initialization Parameters ---------- client : object the management client object component : str the extension component **kwargs : optional keyword arguments Keyword Arguments ----------------- version : str a string specifying the component version to use use_latest_metadata : bool use latest metadata (will be retrieved from remote CDN) Returns ------- None """ self.logger = Logger(__name__).get_logger() self._client = client self._metadata_client = MetadataClient( component, kwargs.pop('version', None), use_latest_metadata=kwargs.pop('use_latest_metadata', False) ) self.component = self._metadata_client.component self.version = self._metadata_client.version
def __init__(self, client, **kwargs): """Class initialization Parameters ---------- **kwargs : optional keyword arguments Keyword Arguments ----------------- logger_name : str the logger name to use in log messages uri : str the REST URI against which this client operates Returns ------- None """ self.logger = Logger(kwargs.pop('logger_name', __name__)).get_logger() self._client = client self._metadata = {'uri': kwargs.pop('uri', None)} self._exceptions = {'InputRequiredError': InputRequiredError}
def __init__(self, **kwargs): """Class initialization Parameters ---------- **kwargs : optional keyword arguments Keyword Arguments ----------------- user : str the username for service authentication password : str the password for service authentication Returns ------- None """ self.logger = Logger(__name__).get_logger() # process kwargs self._api_endpoint = kwargs.pop('api_endpoint', None) if self._api_endpoint is None: self._api_endpoint = API_ENDPOINT self._user = kwargs.pop('user', None) self._password = kwargs.pop('password', None) self._subscription_id = kwargs.pop('subscription_id', None) self.access_token = None self.token_details = None if self._user and self._password: self._login_using_credentials() else: raise InputRequiredError('user|password required')
def __init__(self, host, **kwargs): """Class initialization Parameters ---------- host : str the hostname of the device **kwargs : optional keyword arguments Keyword Arguments ----------------- port : int the port to assign to the port attribute user : str the username for device authentication password : str the password for device authentication Returns ------- None """ self.logger = Logger(__name__).get_logger() self.host = host.split(':')[0] self.port = kwargs.pop('port', 443) self._user = kwargs.pop('user', None) self._password = kwargs.pop('password', None) # account for multiple authentication schemes if self._user and self._password: self._login_using_credentials() else: raise Exception('user|password required')
class ManagementClient(object): """A class used as a management client for BIG-IP Attributes ---------- host : str the hostname of the device port : str the port of the device token : str the token of the device token_details : dict the token details of the device logger : object instantiated logger object Methods ------- get_info() Refer to method documentation make_request() Refer to method documentation make_ssh_request() Refer to method documentation """ def __init__(self, host, **kwargs): """Class initialization Parameters ---------- host : str the hostname of the device **kwargs : optional keyword arguments Keyword Arguments ----------------- port : int the port to assign to the port attribute user : str the username for device authentication password : str the password for device authentication private_key_file : str the file containing the private key for device authentication set_user_password : str sets the user password to this value - used along with private_key_file token : str the token to assign to the token attribute skip_ready_check : bool skips the device ready check if set to true Returns ------- None """ self.logger = Logger(__name__).get_logger() self.host = host.split(':')[0] # disallow providing port here self.port = int(kwargs.pop('port', None) or self._discover_port()) self._user = kwargs.pop('user', None) self._password = kwargs.pop('password', None) self._private_key_file = kwargs.pop('private_key_file', None) self._set_user_password = kwargs.pop('set_user_password', None) self.token = kwargs.pop('token', None) self.token_details = {} # check device is ready if not kwargs.pop('skip_ready_check', False): self._is_ready() # handle multiple authentication mechanisms if self._user and self._password: self._login_using_credentials() elif self._user and self._private_key_file: self._set_password_using_key() self._login_using_credentials() elif self.token: pass else: raise Exception( 'user|password, user|private_key_file or token required') def _test_socket(self, port): """Test TCP connection can be established Parameters ---------- None Returns ------- bool a boolean true/false """ _socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) _socket.settimeout(1) check = False try: _socket.connect((self.host, port)) check = True except (socket.timeout, OSError) as err: self.logger.debug('connection timeout: %s', err) finally: _socket.close() return check def _discover_port(self): """Discover management port (best effort) Try 443 -> 8443, set port to 443 if neither responds. Timeout set to 1 second, if connect or connect refused assume it is the right port. Parameters ---------- None Keyword Arguments ----------------- None Returns ------- int the discovered management port """ if self._test_socket(DFL_PORT): return DFL_PORT if self._test_socket(DFL_PORT_1NIC): return DFL_PORT_1NIC return DFL_PORT @retry(tries=constants.RETRIES['LONG'], delay=constants.RETRIES['DELAY_IN_SECS']) def _is_ready(self): """Checks that the device is ready Notes ----- Retries up to 5 minutes Parameters ---------- None Returns ------- bool boolean true if device is ready """ self.logger.debug('Performing ready check using port %s' % self.port) if self._test_socket(self.port): return True raise DeviceReadyError('Unable to complete device ready check') def _make_ssh_request(self, command): """See public method for documentation: make_ssh_request """ # note: command *might* contain sensitive information # logger should scrub those: i.e. secret foo -> secret *** self.logger.debug('Making SSH request: %s' % (command)) # create client kwargs client_kwargs = {'username': self._user} if self._password: client_kwargs['password'] = self._password elif self._private_key_file: private_key_file = os.path.expanduser(self._private_key_file) client_kwargs['pkey'] = paramiko.RSAKey.from_private_key_file( private_key_file) else: raise Exception('password or private key file required') # workaround for deprecation warning described here, until fixed # https://github.com/paramiko/paramiko/issues/1369 # workaround: temporarily catch warnings on client.connect with warnings.catch_warnings(record=True) as _: # create client client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.client.AutoAddPolicy) try: client.connect(self.host, **client_kwargs) except SSH_EXCEPTIONS as _e: self.logger.error(_e) raise _e # collect result result = client.exec_command(command) # command output (tuple): stdin, stdout, stder stdout = result[1].read().decode('utf-8') stderr = result[2].read().decode('utf-8') client.close() if stderr: raise SSHCommandStdError('Error: %s' % stderr) return stdout.rstrip('\n\r') @retry(tries=constants.RETRIES['DEFAULT'], delay=constants.RETRIES['DELAY_IN_SECS']) def _set_password_using_key(self): """Sets password on device using user + private key Updates user's password using set_user_password Retries if unsuccessful, up to maximum allotment Parameters ---------- None Returns ------- None """ # get password to set password = self._set_user_password if not password: raise Exception('set_user_password required') # get user shell - tmsh or bash tmsh = '' # note: if the shell is in fact bash the first command will fail, so catch # the exception and try with 'tmsh' explicitly added to the command auth_list_cmd = constants.BIGIP_CMDS['AUTH_LIST'] try: user_info = self._make_ssh_request(auth_list_cmd % (tmsh, self._user)) except SSHCommandStdError: user_info = self._make_ssh_request(auth_list_cmd % ('tmsh', self._user)) if 'shell bash' in user_info: tmsh = 'tmsh' # add tmsh to command # set password self._make_ssh_request(constants.BIGIP_CMDS['AUTH_MODIFY'] % (tmsh, self._user, password)) self._password = password @retry(exceptions=HTTPError, tries=constants.RETRIES['DEFAULT'], delay=constants.RETRIES['DELAY_IN_SECS']) def _get_token(self): """Gets authentication token Retries if unsuccessful, up to maximum allotment Parameters ---------- None Returns ------- dict a dictionary containing authentication token, expiration date and expiration in seconds: {'token': 'token', 'expirationDate': '2019-01-01T01:01:01.00', 'expirationIn': 3600} """ self.logger.debug('Getting authentication token') expiration_date = (datetime.now() + timedelta(hours=1)).isoformat() timeout = 3600 # set timeout to 1 hour uri = '/mgmt/shared/authn/login' body = { 'username': self._user, 'password': self._password, 'loginProviderName': 'tmos' } # get token try: response = http_utils.make_request(self.host, uri, port=self.port, method='POST', body=body, basic_auth={ 'user': self._user, 'password': self._password }) except HTTPError as error: if constants.HTTP_STATUS_CODE['FAILED_AUTHENTICATION'] in str( error): _exception = InvalidAuthError(error) _exception.__cause__ = None raise _exception raise error token = response['token']['token'] # now extend token lifetime token_uri = '/mgmt/shared/authz/tokens/%s' % token http_utils.make_request(self.host, token_uri, port=self.port, method='PATCH', body={'timeout': timeout}, basic_auth={ 'user': self._user, 'password': self._password }) return { 'token': token, 'expirationDate': expiration_date, 'expirationIn': timeout } def _login_using_credentials(self): """Logs in to device using user + password Parameters ---------- None Returns ------- None """ self.logger.debug('Logging in using user + password') token = self._get_token() self.token = token['token'] self.token_details = token @check_auth @add_auth_header def make_request(self, uri, **kwargs): """Makes request to device (HTTP/S) Parameters ---------- uri : str the URI where the request should be made **kwargs : optional keyword arguments Keyword Arguments ----------------- method : str the HTTP method to use headers : str the HTTP headers to use body : str the HTTP body to use body_content_type : str the HTTP body content type to use bool_response : bool return boolean based on HTTP success/failure advanced_return : bool return additional information, like HTTP status code to caller Returns ------- dict a dictionary containing the JSON response """ return http_utils.make_request(self.host, uri, port=self.port, **kwargs) @check_auth def make_ssh_request(self, command): """Makes request to device (SSH) Parameters ---------- command : str the command to execute on the device Returns ------- str the command response """ return self._make_ssh_request(command) def get_info(self): """Gets device info Parameters ---------- None Returns ------- dict the device information :: { 'version': 'x.x.x.x' } """ uri = '/mgmt/tm/sys/version' response = self.make_request(uri) version = response['entries'][ 'https://localhost/mgmt/tm/sys/version/0']['nestedStats'][ 'entries']['Version']['description'] return {'version': version}
Set local environment variables first """ # export F5_SDK_HOST='192.0.2.10' # export F5_SDK_USERNAME='******' # export F5_SDK_PWD='admin' # export F5_SDK_AS3_DECL='./my_declaration.json' # export F5_SDK_LOG_LEVEL='INFO' import os from f5sdk.bigip import ManagementClient from f5sdk.bigip.extension import AS3Client from f5sdk.logger import Logger LOGGER = Logger(__name__).get_logger() def run_example(): """ Update AS3 configuration Notes ----- Includes package installation, service check while maintaining idempotency """ # create management client mgmt_client = ManagementClient( os.environ['F5_SDK_HOST'], user=os.environ['F5_SDK_USERNAME'], password=os.environ['F5_SDK_PWD'])
# export F5_SDK_USERNAME='******' # export F5_SDK_PWD='admin' # export F5_SDK_CS_SUBSCRIPTION_ID='' # export F5_SDK_LOG_LEVEL='DEBUG' #!/usr/bin/python3 import os, sys, json, requests import argparse, getpass from f5sdk.cs import ManagementClient from f5sdk.cs.accounts import AccountClient from f5sdk.cs.subscriptions import SubscriptionClient from f5sdk.logger import Logger # from netaddr import * LOGGER = Logger(__name__).get_logger() def parse_args(): parser = argparse.ArgumentParser(description="command line client") subparsers = parser.add_subparsers(dest='command', metavar='command') subparsers.required = True parser.set_defaults(funct=argparser_handler) # Login sub_parser = subparsers.add_parser("login", help="Login with email and password") sub_parser.add_argument('-u', dest='user', help='user. If this argument is not passed it will be requested.') sub_parser.add_argument('-p', dest='password', help='password. If this argument is not passed it will be requested.') args = parser.parse_args()
----- Set local environment variables first """ # export F5_SDK_USERNAME='******' # export F5_SDK_PWD='admin' # export F5_SDK_CS_SUBSCRIPTION_ID='' # export F5_SDK_LOG_LEVEL='DEBUG' import os from f5sdk.cloud_services import ManagementClient from f5sdk.cloud_services.subscriptions import SubscriptionClient from f5sdk.logger import Logger LOGGER = Logger(__name__).get_logger() def get_cs_config(): """ Get Cloud Services configuration """ # create management client cs_client = ManagementClient( user=os.environ['F5_SDK_USERNAME'], password=os.environ['F5_SDK_PWD']) # create subscription client subscription_client = SubscriptionClient(cs_client) # get subscription details return subscription_client.show(name=os.environ['F5_SDK_CS_SUBSCRIPTION_ID'])
class MetadataClient(object): """A class used as a metadata client Attributes ---------- component : str the extension component version : str the extension component version extension_metadata : dict the extension metadata Methods ------- get_download_url() Refer to method documentation get_package_name() Refer to method documentation get_endpoints() Refer to method documentation """ def __init__(self, component, version, **kwargs): """Class initialization Parameters ---------- component : str the extension component version : str the extension component version **kwargs : optional keyword arguments Keyword Arguments ----------------- use_latest_metadata : bool use latest metadata (will be retrieved from remote CDN) Returns ------- None """ self.logger = Logger(__name__).get_logger() self.use_latest_metadata = kwargs.pop('use_latest_metadata', False) self.extension_metadata = self._load_metadata() self.component = self._validate_component(component) self.version = self._validate_component_version( self.component, version or self.get_latest_version()) def _load_metadata(self): """Load extension metadata Load metadata using the follow order: - metadata from CDN (unless use_latest_metadata=False) - metadata included in package (local file) Parameters ---------- None Returns ------- dict a dictionary containg the JSON metadata """ metadata = None # retrieve metadata from URL - unless opted out if self.use_latest_metadata: parsed_url = http_utils.parse_url(EXTENSION_METADATA['URL']) try: metadata = http_utils.make_request(parsed_url['host'], parsed_url['path']) except Exception as err: # pylint: disable=broad-except self.logger.warning('Error downloading metadata file: %s', err) # fallback to local metadata file if metadata is None: local_file = os.path.join(os.path.dirname(__file__), EXTENSION_METADATA['FILE']) try: with open(local_file) as m_file: metadata = json.loads(m_file.read()) except Exception as err: # pylint: disable=broad-except raise FileLoadError(err) return metadata def _validate_component(self, component): """Validates the extension component exists in metadata Parameters ---------- component : str a extension component to check Returns ------- str the extension component provided if it exists (see Raises) Raises ------ Exception if the extension component does not exist in metadata """ components = list(self.extension_metadata['components'].keys()) if not [i for i in components if i == component]: raise InvalidComponentError( 'Valid component must be provided: %s' % (components)) return component def _validate_component_version(self, component, version): """Validates the extension component version exists in metadata Parameters ---------- component : str a extension component to check version : str a extension component version to check Returns ------- str the extension component version provided if it exists (see Raises) Raises ------ Exception if the extension component version does not exist in metadata """ versions = list(self.extension_metadata['components'][component] ['versions'].keys()) if not [i for i in versions if i == version]: raise InvalidComponentVersionError( 'Valid component version must be provided: %s' % (versions)) return version def _get_component_metadata(self): """Gets the metadata for a specific component from the extension metadata Parameters ---------- None Returns ------- dict a dictionary containing the metadata """ return self.extension_metadata['components'][self.component] def _get_version_metadata(self): """Gets the metadata for a specific component version from the extension metadata Parameters ---------- None Returns ------- dict a dictionary containing the metadata """ return self.extension_metadata['components'][ self.component]['versions'][self.version] def get_latest_version(self): """Gets the latest component version from the extension metadata Parameters ---------- None Returns ------- str a string containing the latest version """ c_v_metadata = self.extension_metadata['components'][ self.component]['versions'] latest = {k: v for (k, v) in c_v_metadata.items() if v['latest']} return list(latest.keys())[0] # we should only have one def get_download_url(self): """Gets the component versions download url from extension metadata Parameters ---------- None Returns ------- str a string containing the download url """ return self._get_version_metadata()['downloadUrl'] def get_package_name(self): """Gets the component versions package name from extension metadata Parameters ---------- None Returns ------- str a string containing the package name """ return self._get_version_metadata()['packageName'] def get_component_package_name(self): """Gets the component's package name from extension metadata Parameters ---------- None Returns ------- str a string containing the component's package name. Example: 'telemetry' """ return re.split( '-[0-9]', re.split('f5-?', self._get_version_metadata()['packageName'])[1])[0] def get_component_dependencies(self): """Gets the component dependencies Parameters ---------- None Returns ------- dict describes the component dependencies """ return self._get_component_metadata()['componentDependencies'] def get_endpoints(self): """Gets the component endpoints from extension metadata Parameters ---------- None Returns ------- dict a dictionary containing the endpoints """ return self._get_component_metadata()['endpoints']
class ManagementClient(object): """A class used as a management client for F5 Cloud Services Attributes ---------- access_token : str the access token for the service token_details : dict the token details for the service logger : object instantiated logger object Methods ------- make_request() Refer to method documentation """ def __init__(self, **kwargs): """Class initialization Parameters ---------- **kwargs : optional keyword arguments Keyword Arguments ----------------- user : str the username for service authentication password : str the password for service authentication Returns ------- None """ self.logger = Logger(__name__).get_logger() # process kwargs self._api_endpoint = kwargs.pop('api_endpoint', None) if self._api_endpoint is None: self._api_endpoint = API_ENDPOINT self._user = kwargs.pop('user', None) self._password = kwargs.pop('password', None) self._subscription_id = kwargs.pop('subscription_id', None) self.access_token = None self.token_details = None if self._user and self._password: self._login_using_credentials() else: raise InputRequiredError('user|password required') @retry(exceptions=HTTPError, tries=constants.RETRIES['DEFAULT'], delay=constants.RETRIES['DELAY_IN_SECS']) def _get_token(self): """Gets access token Retries if unsuccessful, up to maximum allotment Parameters ---------- None Returns ------- dict a dictionary containing access token and expiration in seconds: {'accessToken': 'token', 'expirationIn': 3600} """ try: response = http_utils.make_request(self._api_endpoint, '/v1/svc-auth/login', method='POST', body={ 'username': self._user, 'password': self._password }) except HTTPError as error: if constants.HTTP_STATUS_CODE['BAD_REQUEST_BODY'] in str(error) or \ constants.HTTP_STATUS_CODE['FAILED_AUTHENTICATION'] in str(error): _exception = InvalidAuthError(error) _exception.__cause__ = None raise _exception raise error return { 'accessToken': response['access_token'], 'expirationIn': response['expires_at'] } def _login_using_credentials(self): """Logs in to service using user + password Parameters ---------- None Returns ------- None """ self.logger.info('Logging in using user + password') self.token_details = self._get_token() self.access_token = self.token_details['accessToken'] def make_request(self, uri, **kwargs): """Makes request to service (HTTP/S) Parameters ---------- uri : str the URI where the request should be made **kwargs : optional keyword arguments Keyword Arguments ----------------- method : str the HTTP method to use headers : str the HTTP headers to use body : str the HTTP body to use body_content_type : str the HTTP body content type to use bool_response : bool return boolean based on HTTP success/failure Returns ------- dict a dictionary containing the JSON response """ # merge default authentication headers with any user supplied ones dfl_headers = {AUTH_TOKEN_HEADER: 'Bearer %s' % self.access_token} dfl_headers.update(kwargs.pop('headers', {})) return http_utils.make_request(self._api_endpoint, uri, headers=dfl_headers, **kwargs)
class ManagementClient(object): """A class used as a management client for BIG-IQ Attributes ---------- host : str the hostname of the device port : str the port of the device Methods ------- get_info() Refer to method documentation make_request() Refer to method documentation """ def __init__(self, host, **kwargs): """Class initialization Parameters ---------- host : str the hostname of the device **kwargs : optional keyword arguments Keyword Arguments ----------------- port : int the port to assign to the port attribute user : str the username for device authentication password : str the password for device authentication Returns ------- None """ self.logger = Logger(__name__).get_logger() self.host = host.split(':')[0] self.port = kwargs.pop('port', 443) self._user = kwargs.pop('user', None) self._password = kwargs.pop('password', None) # account for multiple authentication schemes if self._user and self._password: self._login_using_credentials() else: raise Exception('user|password required') @retry(tries=constants.RETRIES['DEFAULT'], delay=constants.RETRIES['DELAY_IN_SECS']) def _get_token(self): """Gets authentication token Retries if unsuccessful, up to maximum allotment Parameters ---------- None Returns ------- dict a dictionary containing authentication token, expiration date and expiration in seconds: { 'token': 'token', 'expirationDate': '2019-01-01T01:01:01.00' } """ self.logger.debug('Getting authentication token') response = http_utils.make_request(self.host, '/mgmt/shared/authn/login', port=self.port, method='POST', body={ 'username': self._user, 'password': self._password }, basic_auth={ 'user': self._user, 'password': self._password }) token_details = response['token'] return { 'token': token_details['token'], 'expirationDate': (datetime.now() + timedelta(seconds=token_details['timeout'])).isoformat() } def _login_using_credentials(self): """Login to device using user + password Parameters ---------- None Returns ------- None """ self.logger.info('Logging in using user + password') self.token = self._get_token()['token'] @check_auth @add_auth_header def make_request(self, uri, **kwargs): """Makes request to device (HTTP/S) Parameters ---------- uri : str the URI where the request should be made **kwargs : optional keyword arguments Keyword Arguments ----------------- method : str the HTTP method to use headers : str the HTTP headers to use body : str the HTTP body to use body_content_type : str the HTTP body content type to use bool_response : bool return boolean based on HTTP success/failure advanced_return : bool return additional information, like HTTP status code to caller Returns ------- dict a dictionary containing the JSON response """ return http_utils.make_request(self.host, uri, port=self.port, **kwargs) def get_info(self): """Gets device info Parameters ---------- None Returns ------- dict the device information :: { 'version': 'x.x.x.x' } """ response = self.make_request('/mgmt/tm/sys/version') version_info = response['entries'][ 'https://localhost/mgmt/tm/sys/version/0']['nestedStats'][ 'entries'] return {'version': version_info['Version']['description']}
import getopt import os import sys import yaml import json import jsonschema import requests from jinja2 import Environment, FileSystemLoader from f5sdk.bigip import ManagementClient from f5sdk.bigip.extension import AS3Client, DOClient from f5sdk.logger import Logger LOGGER = Logger(__name__).get_logger() def create_declaration(data, atc_type): """ create automation toolchain declaration """ file_loader = FileSystemLoader('templates') env = Environment(loader=file_loader) # load the template template_type = "as3_template" if atc_type == "as3" else "do_template" template = env.get_template(data[template_type] + '.j2') # render the template output = template.render(data=data) # write the template to file LOGGER.info('writing declaration for {}'.format(data['hostname']))
# export F5_SDK_HOST='192.0.2.10' # export F5_SDK_USERNAME='******' # export F5_SDK_PWD='admin' # export F5_SDK_ADDRESS_TO_REVOKE='192.0.2.100' # export F5_SDK_LICENSE_POOL='my_pool' # export F5_SDK_LOG_LEVEL='INFO' import os from f5sdk.bigiq import ManagementClient from f5sdk.bigiq.licensing import AssignmentClient from f5sdk.bigiq.licensing.pools import MemberManagementClient from f5sdk.logger import Logger LOGGER = Logger(__name__).get_logger() def run_example(address, pool): """ Revoke license""" # create management client mgmt_client = ManagementClient(os.environ['F5_SDK_HOST'], user=os.environ['F5_SDK_USERNAME'], password=os.environ['F5_SDK_PWD']) # create assignment client, member management client assignment_client = AssignmentClient(mgmt_client) member_mgmt_client = MemberManagementClient(mgmt_client) # list assignments
"""Python module containing helper http utility functions """ import json import os import warnings import requests import urllib3 from f5sdk import constants from f5sdk.logger import Logger from f5sdk.exceptions import HTTPError logger = Logger(__name__).get_logger() # pylint: disable=invalid-name def download_to_file(url, file_name): """Downloads an artifact to a local file Notes ----- Uses a stream to avoid loading into memory Parameters ---------- url : str the URL where the artifact should be downloaded from file_name : str the local file name where the artifact should be downloaded Returns
Set local environment variables first """ # export F5_CS_USER='******' # export F5_CS_PWD='example_password' # export F5_SDK_LOG_LEVEL='INFO' import os import json from f5sdk.cs import ManagementClient from f5sdk.cs.accounts import AccountClient from f5sdk.cs.subscriptions import SubscriptionClient from f5sdk.logger import Logger LOGGER = Logger(__name__).get_logger() def run_example(): """ Get Cloud Services configuration """ # create management client mgmt_client = ManagementClient(user=os.environ['F5_CS_USER'], password=os.environ['F5_CS_PWD']) # create account/subscription client account_client = AccountClient(mgmt_client) subscription_client = SubscriptionClient(mgmt_client) # discover account/subscription ID account_id = account_client.show_user()['primary_account_id'] subscription_id = subscription_client.list(
Set local environment variables first """ # export F5_SDK_HOST='192.0.2.10' # export F5_SDK_USERNAME='******' # export F5_SDK_PWD='admin' # export F5_SDK_AS3_DECL='./my_declaration.json' # export F5_SDK_LOG_LEVEL='DEBUG' import os from f5sdk.bigip import ManagementClient from f5sdk.bigip.extension import ExtensionClient from f5sdk.logger import Logger LOGGER = Logger(__name__).get_logger() def update_as3_config(): """ Update AS3 configuration Notes ----- Includes package installation, service check while maintaining idempotency """ # create management client mgmt_client = ManagementClient(os.environ['F5_SDK_HOST'], user=os.environ['F5_SDK_USERNAME'], password=os.environ['F5_SDK_PWD'])