def get_service_ref(k8s_path): service_file_path = os.path.join(k8s_path, "service.yaml") if not os.path.exists(service_file_path): service_file_path = os.path.join(k8s_path, "kservice.yaml") try: with open(service_file_path) as f: service_components = list(yaml.load_all(f, Loader=yaml.SafeLoader)) if len(service_components) == 1: service_components = service_components[0] except FileNotFoundError: error("%s not found" % service_file_path) return None if isinstance(service_components, Mapping): if service_components.get("kind") == "Service": name = service_components.get("metadata", {}).get("name") if name is not None: return { "serviceApiVersion": service_components.get("apiVersion"), "rulesetName": name } elif isinstance(service_components, list): for c in service_components: if c.get("kind") == "Service": name = c.get("metadata", {}).get("name") if name is not None: return { "serviceApiVersion": c.get("apiVersion"), "rulesetName": name } return None
def get_default_namespace(): error("fetching kubectl config...") namespace = subprocess.check_output( ["kubectl", "config", "current-context", "namespace"]) if namespace is None: return "default" return namespace.decode("utf-8").replace("\n", "")
def add_profile(profile_name, project_root, namespace, docker_registry, set_default=False): config_path = os.path.join(project_root, PROJECT_CONF_DIR, PROJECT_CONF_FILE_NAME) config = get_config(config_path) if PROFILES_SECTION not in config: config[PROFILES_SECTION] = {} elif profile_name in config[PROFILES_SECTION]: error("%s profile already exists" % profile_name) return if namespace is None or len(namespace) == 0: default_namespace = get_default_namespace() while namespace is None or len(namespace) == 0: answer = get_user_input("Namespace [%s]: " % default_namespace) if answer == "": namespace = default_namespace else: namespace = answer if docker_registry is None or len(docker_registry) == 0: docker_registry = "" default_docker_registry = get_default_docker_registry() while len(docker_registry) == 0: if default_docker_registry is not None: output_request = "Docker Registry [%s]: " % default_docker_registry else: output_request = "Docker Registry: " answer = get_user_input(output_request) if answer == "": if default_docker_registry is not None: docker_registry = default_docker_registry else: error("You must set value for Docker Registry") else: docker_registry = answer.replace(" ", "") profile = {"namespace": namespace, "docker_registry": docker_registry} config[PROFILES_SECTION][profile_name] = profile save_config(config, config_path) print("Profile %s added properly" % profile_name) if set_default: workspace_path = os.path.join(project_root, PROJECT_CONF_DIR, PROJECT_WORKSPACE_FILE_NAME) update_workspace(workspace_path, current_profile=profile_name) print("Profile %s is now the current one" % profile_name) return profile
def set_current_profile(profile_name): project_root = get_project_root(os.getcwd()) config_path = os.path.join(project_root, PROJECT_CONF_DIR, PROJECT_CONF_FILE_NAME) config = get_config(config_path) profiles = list(config.get(PROFILES_SECTION, {}).keys()) if profile_name not in profiles: error("\"%s\" is not a valid profile name" % profile_name) error("Choose between %s" % str(profiles)) else: workspace_path = os.path.join(project_root, PROJECT_CONF_DIR, PROJECT_WORKSPACE_FILE_NAME) update_workspace(workspace_path, current_profile=profile_name) print("%s now is the current profile" % profile_name)
def patch_kustomization(path, images): if path is None or path == "": path = os.getcwd() if not os.path.exists(os.path.join(path, "kustomization.yaml")): path = os.path.join(path, "k8s") if not os.path.exists(path): error( "\"kustomization.yaml\" not found in the current directory or in the subdirectory \"k8s\"" ) return if images is not None: build_kustomization(path, images=images) else: build_kustomization(path)
def build_docker_file(path): origin_filepath = os.path.join(path, "Dockerfile.origin") if os.path.exists(origin_filepath): project_root = get_project_root(path) with open(os.path.join(project_root, "base", "VERSION")) as v: version = v.read() profile = get_current_profile() config = get_config( os.path.join(project_root, PROJECT_CONF_DIR, PROJECT_CONF_FILE_NAME)) parsed_content = load_template( path, "Dockerfile.origin", dockerRegistry=profile["docker_registry"], projectName=config[PROJECT_SECTION]["name"], baseVersion=version) dockerfile_path = os.path.join(path, "Dockerfile") with open(dockerfile_path, "w") as dockerfile: dockerfile.write(parsed_content) else: error("Dockerfile.origin not found!") return
def update_ruleset(merge_strategy, pk=None, **values): values["action"] = "update" cwd = os.getcwd() project_root = get_project_root(cwd) _, ruleset_name = os.path.split(cwd) project_config = get_config( os.path.join(project_root, PROJECT_CONF_DIR, PROJECT_CONF_FILE_NAME)) template_dir = project_config[PROJECT_SECTION].get( DEFAULT_RS_TEMPLATE_PATH_KEY, None) if template_dir is None: template_dir = os.path.join(ASSETS_PATH, "ruleset_tmpl") else: template_dir = os.path.join(project_root, template_dir) parent, current_folder_name = os.path.split(cwd) if current_folder_name == "k8s": ruleset_path = parent k8s_path = cwd else: k8s_path = os.path.join(cwd, "k8s") if os.path.exists(k8s_path): ruleset_path = cwd else: error("k8s folder not found!") return service_ref = get_service_ref(k8s_path) if service_ref is None: error( "No Service found in the current directory or in the subdirectory \"k8s\"" ) return values.update(service_ref) recursive_copy(template_dir, ruleset_path, values, merge_strategy=merge_strategy, pk=pk)
def init_project_tree(project_name, project_location, namespace, docker_registry, image_base): if project_location is None: project_location = os.getcwd() project_location = os.path.abspath(project_location) if os.path.exists(os.path.join(project_location, PROJECT_CONF_DIR)): error('Project already exists in %s' % project_location) return if project_name is not None and not is_valid_project_name(project_name): error("Project name must match %s" % VALID_PROJECT_NAME_REGEX) return if project_name is None or len(project_name) == 0: default_project_name = get_default_project_name(project_location) while project_name is None or len(project_name) == 0: answer = get_user_input("Project name [%s]: " % default_project_name) if answer == "": project_name = default_project_name else: if is_valid_project_name(answer): project_name = answer else: error("Project name must match %s" % VALID_PROJECT_NAME_REGEX) config = {PROJECT_SECTION: {"name": project_name}} save_config( config, os.path.join(project_location, PROJECT_CONF_DIR, PROJECT_CONF_FILE_NAME)) profile = add_profile(DEFAULT_KEY, project_location, namespace, docker_registry, set_default=True) defaults = { "projectName": project_name, "dockerRegistry": profile["docker_registry"], "projectNamespace": profile["namespace"] } with open(os.path.join(ASSETS_PATH, "defaults.yaml")) as df: defaults.update(yaml.load(df.read(), Loader=yaml.SafeLoader)) if image_base is not None: defaults["imageBase"] = image_base os.makedirs(project_location, exist_ok=True) recursive_copy(os.path.join(ASSETS_PATH, "project_tmpl"), project_location, defaults) print("Project %s created successfully" % project_name) print("Now you have to configure subject storage support\n" "Look at \"Config subject storage support\" section in README")
def parse_args(args): scope = args.get("scope") command = args.get("command") if scope == "project": if command == "init": init_project_tree(args.get("name"), args.get("location"), args.get("namespace"), args.get("docker_registry"), args.get("image_base")) else: project_parser.print_help(sys.stdout) elif scope == "ruleset": if command == "create": init_ruleset_tree(args.get("name"), args.get("template_dir"), args.get("service_type")) elif command == "patch": patch_kustomization(args.get("path"), args.get("set_image")) elif command == "build-dockerfile": build_docker_file(os.getcwd()) else: ruleset_parser.print_help(sys.stdout) elif scope == "trigger": name = args.get("name") if args.get("type"): if args.get("on_propchange") or args.get("attrs"): error(UPDATE_TRIGGER_ERROR_MESSAGE) return else: update_ruleset(resourceKinds=["Trigger"], triggerKind="trigger-for-type", type=args.get("type"), merge_strategy=MERGE_STRATEGY_MIXED, pk="metadata.name", triggerName=name) elif args.get("on_propchange"): if args.get("type") or args.get("attrs"): error(UPDATE_TRIGGER_ERROR_MESSAGE) return else: update_ruleset(resourceKinds=["Trigger"], triggerKind="trigger-on-propchange", propertyName=args.get("on_propchange"), merge_strategy=MERGE_STRATEGY_MIXED, pk="metadata.name", triggerName=name) elif args.get("attrs"): if args.get("type") or args.get("on_propchange"): error(UPDATE_TRIGGER_ERROR_MESSAGE) return else: attributes = {} for attr in args.get("attrs"): try: k, v = attr.split("=") except ValueError: error("Bad formatted attributes (expected attr=value)") return if k in attributes: error("Duplicated attribute %s" % k) return attributes[k] = v update_ruleset(resourceKinds=["Trigger"], triggerKind="trigger-attrs", triggerAttributes=attributes, merge_strategy=MERGE_STRATEGY_MIXED, pk="metadata.name", triggerName=name) else: update_ruleset(resourceKinds=["Trigger"], triggerKind="trigger-sourced", triggerSourced=name, merge_strategy=MERGE_STRATEGY_MIXED, pk="metadata.name", triggerName=name) elif scope == "gen-rs-template": location = args.get("location") if location is not None: export_rs_template_from_assets(location, args.get("set_default")) elif args.get("unset_default"): unset_default() else: gen_rs_template_parser.print_help() elif scope == "profile": if command == "get": print(get_current_profile_name()) elif command == "set": set_current_profile(args.get("profile_name")) elif command == "list": get_profiles_list() elif command == "get-value": print(get_profile_value(args.get("key"))) elif command == "set-value": set_profile_value(args.get("key"), args.get("value")) elif command == "values": print_current_profile_values() elif command == "add": project_root = get_project_root(os.getcwd()) add_profile(args.get("name"), project_root, args.get("namespace"), args.get("docker_registry"), args.get("set_default")) else: profile_parser.print_help() else: parser.print_help()