def get_yaml_all(filename): with open(filename,'r') as input_file: return list(yaml.safe_load_all(input_file))
def main(): global cpx_count global output_yaml parser = argparse.ArgumentParser( description= 'Taking service yamls or name as input. And namespace in case service names is provided' ) parser.add_argument( 'ServiceList', action="store", help= 'Please provide comma seperated list of service yamls or names to convert into SML' ) parser.add_argument( 'Namespace', action="store", nargs='?', help='Please provide namespace in which services are deployed') svcs = parser.parse_args().ServiceList.split(',') namespace = parser.parse_args().Namespace converted_yamls_dict_list = [] if (".yaml" not in svcs[0]): ''' Code for connecting to Kubenetes Cluster ''' if not namespace: logger.error( "Please provide namespace as well in which services are deployed while starting the script" ) sys.exit(0) prompts = chain( ["Do you want to connect to a Remote Kubernetes Cluster? (Y/N): "], repeat("Invaild input. Please respond with (Y/N): ")) remote_access = validate_input(prompts, "yesORno") if remote_access.lower() == 'n': prompts = chain([ 'Do you want to use default kubeconfig file present at "/root/.kube/config"? (Y/N): ' ], repeat("Invaild input. Please respond with (Y/N): ")) default_kube_config = validate_input(prompts, "yesORno") if default_kube_config.lower() == "y": kube_config_path = "/root/.kube/config" else: prompts = chain( ["Please provide path of kubeconfig file: "], repeat( "This path doesn't exist! Please provide a valid kubeconfig file path: " )) kube_config_path = validate_input(prompts, "path") config.load_kube_config(config_file=kube_config_path) v1 = client.CoreV1Api() elif remote_access.lower() == 'y': prompts = chain([ "Do you want to use Bearer Token for connecting to a Remote Kubernetes Cluster? (Y/N): " ], repeat("Invaild input. Please respond with (Y/N): ")) use_bearer_token = validate_input(prompts, "yesORno") if use_bearer_token.lower() == "y": configuration = client.Configuration() bearer_token = input( "Please provide bearer token key of SA having permission to access given service: " ) configuration.api_key = { "authorization": "Bearer " + bearer_token } prompts = chain( ["Please provide API server <IP:PORT>: "], repeat( "Invaild input. Please provide valid IP and port in format <IP:PORT>: " )) api_server = validate_input(prompts, "apiServerIPPort") configuration.host = 'https://' + api_server configuration.verify_ssl = False v1 = client.CoreV1Api(client.ApiClient(configuration)) elif use_bearer_token.lower() == "n": prompts = chain( ["Please provide path of kubeconfig file: "], repeat( "This path doesn't exist! Please provide a valid kubeconfig file path: " )) kube_config_path = validate_input(prompts, "path") config.load_kube_config(config_file=kube_config_path) v1 = client.CoreV1Api() app_frontend_svc_name = input( "Please provide name of the service exposed to tier-1: ") app_hostname = input("Please provide hostname for exposing \"" + app_frontend_svc_name + "\" service: ") if not namespace: namespace = "default" ''' Coverting YAMLs to SML YAMLs ''' for svc in svcs: if (".yaml" in svc): ''' When applcation YAMLs is provided as input. ''' with open(svc, 'r') as stream: try: yaml_dictionaries = yaml.safe_load_all(stream) for yaml_instance in yaml_dictionaries: if yaml_instance: converted_yamls_dict_list.extend( convert_yaml_to_sml(yaml_instance, app_frontend_svc_name, app_hostname)) except Exception as e: logger.error( "Retrieving yaml from service yamls provided failed with error: {}" .format(e)) sys.exit("Please ensure service yaml is in proper format") else: ''' When service name running in Kubernetes cluster is provided as input. ''' try: service = v1.read_namespaced_service(svc, namespace) except Exception as e: logger.error( "Retrieving service from KubeAPI server failed with error: {}" .format(e)) sys.exit("Please ensure service name and namespace is correct") service = service.__dict__ service = convert_kube_object_to_dict(service) # service = OrderedDict([('apiVersion',service['apiVersion']), # ('kind',service['kind']), # ('metadata',service['metadata']), # ('spec',service['spec']), converted_yamls_dict_list.extend( convert_yaml_to_sml(service, app_frontend_svc_name, app_hostname)) ''' Checking if required HELM is there or not. ''' helm_ver = subprocess.run(["helm version"], shell=True, capture_output=True).stdout.decode('utf-8') matchObj = re.search(r'Version:"v3.*', helm_ver, re.M | re.I) if not matchObj: logger.error("Couldn't find Helm with version 3.x and above.") sys.exit( "Please install Helm 3.x and put it in the PATH. This https://github.com/citrix/citrix-helm-charts/blob/master/Helm_Installation_version_3.md can be followed for the same." ) subprocess.run( ["helm repo add citrix https://citrix.github.io/citrix-helm-charts/"], shell=True, capture_output=True) ''' Getting ADM details ''' prompts = chain(['Citrix ADM required? (Y/N): '], repeat("Invaild input. Please respond with (Y/N): ")) adm_required = validate_input(prompts, "yesORno") if adm_required.lower() == "y": prompts = chain([ 'Please provide IP of ADM Agent(svcIP of container agent) for Citrix ADC CPX: ' ], repeat("Invaild IP. Please enter and IPv4 IP: ")) cpx_adm_agent_ip = validate_input(prompts, "ip") adm_secret = input( "Please provide name of K8s Secret created using ADM Agent credentials. Press ENTER for 'admlogin': "******"admlogin" ''' Adding CPX yamls ''' for i in range(1, cpx_count + 1): if adm_required.lower() == "y": output = subprocess.run([ "helm template " + chart_name + str(i) + " citrix/citrix-cloud-native --set cpx.enabled=true,cpx.license.accept=yes,cpx.ingressClass[0]=" + cpx_ingress_class + str(i) + ",cpx.coeConfig.required=true,cpx.coeConfig.timeseries.metrics.enable=true,cpx.coeConfig.distributedTracing.enable=true,cpx.coeConfig.endpoint.server=" + cpx_adm_agent_ip + ",cpx.ADMSettings.ADMIP=" + cpx_adm_agent_ip + ",cpx.ADMSettings.loginSecret=" + adm_secret + " -n " + namespace + " > temp.yaml" ], shell=True, capture_output=True) # output = subprocess.run(["helm template "+ chart_name + str(i) + " citrix/citrix-cloud-native --set cpx.enabled=true,cpx.license.accept=yes,cpx.ingressClass[0]="+cpx_ingress_class+str(i)+",cpx.coeConfig.required=true,cpx.coeConfig.timeseries.metrics.enable=true,cpx.coeConfig.distributedTracing.enable=true,cpx.coeConfig.endpoint.server="+ cpx_adm_agent_ip +",cpx.ADMSettings.ADMIP=" + cpx_adm_agent_ip +",cpx.ADMSettings.loginSecret=" + adm_secret + " -n "+namespace+" > temp.yaml"],shell=True,capture_output=True) if output.stderr: logger.error("Helm chart command failed with error {}".format( output.stderr)) sys.exit("Please ensure you have provided proper inputs.") else: output = subprocess.run([ "helm template " + chart_name + str(i) + " citrix/citrix-cloud-native --set cpx.enabled=true,cpx.license.accept=yes,cpx.ingressClass[0]=" + cpx_ingress_class + str(i) + " -n " + namespace + " > temp.yaml" ], shell=True, capture_output=True) if output.stderr: logger.error("Helm chart command failed with error {}".format( output.stderr)) sys.exit("Please ensure you have provided proper inputs.") with open('temp.yaml', 'r') as stream: yaml_dictionaries = list(yaml.safe_load_all(stream)) if i > 1: list_to_remove = [] for yaml_instance in yaml_dictionaries: if yaml_instance['kind'] == "ServiceAccount" or yaml_instance[ 'kind'] == "ClusterRole" or yaml_instance[ 'kind'] == "ClusterRoleBinding": list_to_remove.append(yaml_instance) elif yaml_instance['kind'] == "Deployment": yaml_instance['spec']['template']['spec'][ 'serviceAccountName'] = re.sub( "sml" + str(i), "sml1", yaml_instance['spec'] ['template']['spec']['serviceAccountName']) elif yaml_instance['kind'] == "Service": yaml_instance['metadata']['labels']['citrix-adc'] = 'cpx' yaml_dictionaries = [ x for x in yaml_dictionaries if x not in list_to_remove ] converted_yamls_dict_list.extend(yaml_dictionaries) else: for yaml_instance in yaml_dictionaries: if yaml_instance['kind'] == "Service": yaml_instance['metadata']['labels']['citrix-adc'] = 'cpx' converted_yamls_dict_list.extend(yaml_dictionaries) # rbac = manifestCreator.rbac() # rbac = rbac.createRbac() # converted_yamls_dict_list.extend(rbac) # cpx_cic_yaml = manifestCreator.cpxCic({"name":chart_name+str(i),"ingressClass":cpx_ingress_class+str(i)}) # cpx_cic_yaml = cpx_cic_yaml.create() # converted_yamls_dict_list.extend(cpx_cic_yaml) ''' Getting details for Tier-1 ADC ''' prompts = chain( ['Citrix Ingress Controller for tier-1 ADC required? (Y/N): '], repeat("Invaild input. Please respond with (Y/N): ")) create_cic = validate_input(prompts, "yesORno") if create_cic.lower() == "y": prompts = chain(['Please provide tier-1 ADC NSIP: '], repeat("Invaild IP. Please enter and IPv4 IP: ")) ns_ip = validate_input(prompts, "ip") prompts = chain(['Please provide tier-1 ADC VIP: '], repeat("Invaild IP. Please enter and IPv4 IP: ")) ns_vip = validate_input(prompts, "ip") ns_secret = input( "Please provide name of K8s Secret created using ADC credentials. Press ENTER for 'nslogin': "******"nslogin" if adm_required.lower() == "y": prompts = chain([ 'Please provide IP of ADM Agent(podIP of container agent) for Citrix ADC VPX/MPX: ' ], repeat("Invaild IP. Please enter and IPv4 IP: ")) vpx_adm_agent_ip = validate_input(prompts, "ip") app_frontend_svc_port = input( "Please provide port used to expose CPX service to Tier-1 ADC: ") prompts = chain( [ "Please provide protocol used to expose CPX service to Tier-1 ADC (tcp/udp/http/https/grpc): " ], repeat( "Invaild protocol. Please choose a protocol from (tcp/udp/http/https/grpc): " )) app_frontend_svc_protocol = validate_input(prompts, "protocol") if app_frontend_svc_protocol == "grpc": app_frontend_svc_protocol = "tcp" if app_frontend_svc_protocol == "https": tls = input("Please give secret-name for TLS certificate for \"" + app_frontend_svc_name + "\" svc: ") else: tls = "" if adm_required.lower() == "y": output = subprocess.run([ "helm template " + chart_name + " citrix/citrix-cloud-native --set cic.enabled=true,cic.nsIP=" + ns_ip + ",cic.nsVIP=" + ns_vip + ",cic.license.accept=yes,cic.adcCredentialSecret=" + ns_secret + ",cic.ingressClass[0]=" + vpx_ingress_class + ",cic.coeConfig.required=true,cic.coeConfig.timeseries.metrics.enable=true,cic.coeConfig.timeseries.port=5563,cic.coeConfig.distributedTracing.enable=true,cic.coeConfig.transactions.enable=true,cic.coeConfig.transactions.port=5557,cic.coeConfig.endpoint.server=" + vpx_adm_agent_ip + " -n " + namespace + " > temp.yaml" ], shell=True, capture_output=True) if output.stderr: logger.error("Helm chart command failed with error {}".format( output.stderr)) sys.exit("Please ensure you have provided proper inputs.") ingress_yaml = manifestCreator.ingress({ "name": tier1_ingress_name, "protocol": app_frontend_svc_protocol.lower(), "ingressClass": vpx_ingress_class, "tls": tls, "admRequired": True, "serviceDetails": { app_hostname: [{ "serviceName": "sml" + str(frontend_cpx_count) + "-cpx-service", "servicePort": app_frontend_svc_port }] } }) else: output = subprocess.run([ "helm template " + chart_name + " citrix/citrix-cloud-native --set cic.enabled=true,cic.nsIP=" + ns_ip + ",cic.nsVIP=" + ns_vip + ",cic.license.accept=yes,cic.adcCredentialSecret=" + ns_secret + ",cic.ingressClass[0]=" + vpx_ingress_class + " -n " + namespace + " > temp.yaml" ], shell=True, capture_output=True) if output.stderr: logger.error("Helm chart command failed with error {}".format( output.stderr)) sys.exit("Please ensure you have provided proper inputs.") ingress_yaml = manifestCreator.ingress({ "name": tier1_ingress_name, "protocol": app_frontend_svc_protocol.lower(), "ingressClass": vpx_ingress_class, "tls": tls, "serviceDetails": { app_hostname: [{ "serviceName": "sml" + str(frontend_cpx_count) + "-cpx-service", "servicePort": app_frontend_svc_port }] } }) with open('temp.yaml', 'r') as stream: yaml_dictionaries = list(yaml.safe_load_all(stream)) converted_yamls_dict_list.extend(yaml_dictionaries) ingress_yaml = ingress_yaml.create() converted_yamls_dict_list.append(ingress_yaml) ''' Deleting temp.yaml which got created via Helm ''' my_file = Path("temp.yaml") if my_file.is_file(): os.remove("temp.yaml") ''' Writing dictionay of YAML into a .yaml file ''' write_dictionaries_into_yaml(converted_yamls_dict_list, output_yaml)
def test_load_all(): gen = yaml.safe_load_all("{x: 1, z: 3, y: 2}\n--- {}\n") assert isinstance(gen, GeneratorType) ordered_data, empty_dict = gen assert empty_dict == {} assert ordered_data == data
def main(): global cpx_count global output_yaml parser = argparse.ArgumentParser( description= 'Taking service yamls or name as input. And namespace in case service names is provided' ) parser.add_argument( 'ServiceList', action="store", help= 'Please provide comma seperated list of service yamls or names to convert into SML' ) parser.add_argument( 'Namespace', action="store", nargs='?', help='Please provide namespace in which services are deployed') svcs = parser.parse_args().ServiceList.split(',') namespace = parser.parse_args().Namespace converted_yamls_dict_list = [] if (".yaml" not in svcs[0]): if not namespace: logger.error( "Please provide namespace as well in which services are deployed while starting the script" ) sys.exit(0) prompts = chain( ["Do you want to connect to a Remote Kubernetes Cluster? (Y/N): "], repeat("Invaild input. Please respond with (Y/N): ")) remote_access = validate_input(prompts, "yesORno") if remote_access.lower() == 'n': prompts = chain([ 'Do you want to use default kubeconfig file present at "/root/.kube/config"? (Y/N): ' ], repeat("Invaild input. Please respond with (Y/N): ")) default_kube_config = validate_input(prompts, "yesORno") if default_kube_config.lower() == "y": kube_config_path = "/root/.kube/config" else: prompts = chain( ["Please provide path of kubeconfig file: "], repeat( "This path doesn't exist! Please provide a valid kubeconfig file path: " )) kube_config_path = validate_input(prompts, "path") config.load_kube_config(config_file=kube_config_path) v1 = client.CoreV1Api() elif remote_access.lower() == 'y': prompts = chain([ "Do you want to use Bearer Token for connecting to a Remote Kubernetes Cluster? (Y/N): " ], repeat("Invaild input. Please respond with (Y/N): ")) use_bearer_token = validate_input(prompts, "yesORno") if use_bearer_token.lower() == "y": configuration = client.Configuration() bearer_token = input( "Please provide bearer token key of SA having permission to access given service: " ) configuration.api_key = { "authorization": "Bearer " + bearer_token } prompts = chain( ["Please provide API server <IP:PORT>: "], repeat( "Invaild input. Please provide valid IP and port in format <IP:PORT>: " )) api_server = validate_input(prompts, "apiServerIPPort") configuration.host = 'https://' + api_server configuration.verify_ssl = False v1 = client.CoreV1Api(client.ApiClient(configuration)) elif use_bearer_token.lower() == "n": prompts = chain( ["Please provide path of kubeconfig file: "], repeat( "This path doesn't exist! Please provide a valid kubeconfig file path: " )) kube_config_path = validate_input(prompts, "path") config.load_kube_config(config_file=kube_config_path) v1 = client.CoreV1Api() app_frontend_svc_name = input( "Please provide name of the service exposed to tier-1: ") app_hostname = input("Please provide hostname for exposing \"" + app_frontend_svc_name + "\" service: ") for svc in svcs: if (".yaml" in svc): with open(svc, 'r') as stream: try: yaml_dictionaries = yaml.safe_load_all(stream) for yaml_instance in yaml_dictionaries: if yaml_instance: converted_yamls_dict_list.extend( convert_yaml_to_sml(yaml_instance, app_frontend_svc_name, app_hostname)) except Exception as e: logger.error( "Retrieving yaml from service yamls provided failed with error: {}" .format(e)) sys.exit("Please ensure service yaml is in proper format") else: try: service = v1.read_namespaced_service(svc, namespace) except Exception as e: logger.error( "Retrieving service from KubeAPI server failed with error: {}" .format(e)) sys.exit("Please ensure service name and namespace is correct") service = service.__dict__ service = convert_kube_object_to_dict(service) # service = OrderedDict([('apiVersion',service['apiVersion']), # ('kind',service['kind']), # ('metadata',service['metadata']), # ('spec',service['spec']), converted_yamls_dict_list.extend( convert_yaml_to_sml(service, app_frontend_svc_name, app_hostname)) ''' Adding CPX yamls ''' rbac = manifestCreator.rbac() rbac = rbac.createRbac() converted_yamls_dict_list.extend(rbac) for i in range(1, cpx_count + 1): cpx_cic_yaml = manifestCreator.cpxCic({ "name": cpx_ingress_name + str(i), "ingressClass": ingress_class + str(i) }) cpx_cic_yaml = cpx_cic_yaml.create() converted_yamls_dict_list.extend(cpx_cic_yaml) ''' Writing dictionay of YAML into a .yaml file ''' write_dictionaries_into_yaml(converted_yamls_dict_list, output_yaml)