diff --git a/scripts/preprocess_spec.py b/scripts/preprocess_spec.py index 229bf4f4f..d871cbdd4 100644 --- a/scripts/preprocess_spec.py +++ b/scripts/preprocess_spec.py @@ -115,6 +115,8 @@ def process_swagger(spec): except PreprocessingException as e: print(e.message) + remove_model_prefixes(spec) + # TODO: Kubernetes does not set a version for OpenAPI spec yet, # remove this when that is fixed. spec['info']['version'] = SPEC_VERSION @@ -122,6 +124,73 @@ def process_swagger(spec): return spec +def rename_model(spec, old_name, new_name): + if new_name in spec['definitions']: + raise PreprocessingException( + "Cannot rename model %s. new name %s exists." % + (old_name, new_name)) + find_rename_ref_recursive(spec, + "#/definitions/" + old_name, + "#/definitions/" + new_name) + spec['definitions'][new_name] = spec['definitions'][old_name] + del spec['definitions'][old_name] + + +def find_rename_ref_recursive(root, old, new): + if isinstance(root, list): + for r in root: + find_rename_ref_recursive(r, old, new) + if isinstance(root, dict): + if "$ref" in root: + if root["$ref"] == old: + root["$ref"] = new + for k, v in root.iteritems(): + find_rename_ref_recursive(v, old, new) + + +def remove_model_prefixes(spec): + """Remove full package name from OpenAPI model names. + + Starting kubernetes 1.6, all models has full package name. This is + verbose and inconvenient in python client. This function tries to remove + parts of the package name but will make sure there is no conflicting model + names. This will keep most of the model names generated by previous client + but will change some of them. + """ + models = {} + for k, v in spec['definitions'].iteritems(): + if k.startswith("io.k8s"): + models[k] = {"split_n": 2} + + conflict = True + while conflict: + for k, v in models.iteritems(): + splits = k.rsplit(".", v["split_n"]) + v["removed_prefix"] = splits.pop(0) + v["new_name"] = ".".join(splits) + + conflict = False + for k, v in models.iteritems(): + for k2, v2 in models.iteritems(): + if k != k2 and v["new_name"] == v2["new_name"]: + v["conflict"] = True + v2["conflict"] = True + conflict = True + + if conflict: + for k, v in models.iteritems(): + if "conflict" in v: + print("Resolving conflict for %s" % k) + v["split_n"] += 1 + del v["conflict"] + + for k, v in models.iteritems(): + if "new_name" not in v: + raise PreprocessingException("Cannot rename model %s" % k) + print("Removing prefix %s from %s...\n" % (v["removed_prefix"], k)) + rename_model(spec, k, v["new_name"]) + + def main(): pool = urllib3.PoolManager() with pool.request('GET', SPEC_URL, preload_content=False) as response: