diff --git a/hack/update_owners.py b/hack/update_owners.py index 97d9d3f3a67..e6c3d06d04b 100755 --- a/hack/update_owners.py +++ b/hack/update_owners.py @@ -30,6 +30,7 @@ import zlib BASE_DIR = os.path.dirname(os.path.abspath(__file__)) OWNERS_PATH = os.path.abspath( os.path.join(BASE_DIR, '..', 'test', 'test_owners.csv')) +OWNERS_JSON_PATH = OWNERS_PATH.replace('.csv', '.json') GCS_URL_BASE = 'https://storage.googleapis.com/kubernetes-test-history/' SKIP_MAINTAINERS = { 'a-robinson', 'aronchick', 'bgrant0607-nocc', 'david-mcmahon', @@ -124,12 +125,44 @@ def detect_github_username(): '`git config remote.origin.url` output, run with --user instead') +def sig_prefixes(owners): + # TODO(rmmh): make sig prefixes the only thing in test_owners! + # Precise test names aren't very interesting. + owns = [] + + for test, (owner, random_assignment, sig) in owners.iteritems(): + if 'k8s.io/' in test or not sig: + continue + owns.append([test, sig]) + + while True: + owns.sort() + for name, sig in owns: + # try removing the last word in the name, use it if all tests beginning + # with this shorter name share the same sig. + maybe_prefix = ' '.join(name.split()[:-1]) + matches = [other_sig == sig for other_name, other_sig in owns if other_name.startswith(maybe_prefix)] + if matches and all(matches): + owns = [[n, s] for n, s in owns if not n.startswith(maybe_prefix)] + owns.append([maybe_prefix, sig]) + break + else: # iterated completely through owns without any changes + break + + sigs = {} + for name, sig in owns: + sigs.setdefault(sig, []).append(name) + + return json.dumps(sigs, sort_keys=True, indent=True) + + def main(): parser = argparse.ArgumentParser() parser.add_argument('--history', action='store_true', help='Generate test list from result history.') parser.add_argument('--user', help='User to assign new tests to (or RANDOM, default: current GitHub user).') parser.add_argument('--addonly', action='store_true', help='Only add missing tests, do not change existing.') parser.add_argument('--check', action='store_true', help='Exit with a nonzero status if the test list has changed.') + parser.add_argument('--print_sig_prefixes', action='store_true', help='Emit SIG prefixes for matching.') options = parser.parse_args() if options.history: @@ -139,6 +172,15 @@ def main(): test_names = sorted(test_names) owners = load_owners(OWNERS_PATH) + prefixes = sig_prefixes(owners) + + with open(OWNERS_JSON_PATH, 'w') as f: + f.write(prefixes + '\n') + + if options.print_sig_prefixes: + print prefixes + return + outdated_tests = sorted(set(owners) - set(test_names)) new_tests = sorted(set(test_names) - set(owners)) maintainers = get_maintainers() diff --git a/test/test_owners.csv b/test/test_owners.csv index a2be215ff50..c51a6450929 100644 --- a/test/test_owners.csv +++ b/test/test_owners.csv @@ -123,7 +123,7 @@ Empty starts a pod,childsb,1, "EmptyDir volumes should support (non-root,0644,default)",timstclair,1,node "EmptyDir volumes should support (non-root,0644,tmpfs)",spxtr,1,node "EmptyDir volumes should support (non-root,0666,default)",dchen1107,1,node -"EmptyDir volumes should support (non-root,0666,tmpfs)",apelisse,1,storage +"EmptyDir volumes should support (non-root,0666,tmpfs)",apelisse,1,node "EmptyDir volumes should support (non-root,0777,default)",mwielgus,1,node "EmptyDir volumes should support (non-root,0777,tmpfs)",smarterclayton,1,node "EmptyDir volumes should support (root,0644,default)",mtaufen,1,node diff --git a/test/test_owners.json b/test/test_owners.json new file mode 100644 index 00000000000..86862b5dc3c --- /dev/null +++ b/test/test_owners.json @@ -0,0 +1,124 @@ +{ + "api-machinery": [ + "Etcd", + "Generated", + "HA-master", + "Multi-AZ", + "Namespaces", + "ResourceQuota", + "Staging", + "Summary", + "ThirdParty" + ], + "apps": [ + "Cassandra", + "ConfigMap", + "CronJob", + "Daemon", + "Deployment", + "Job", + "Mesos", + "Pet", + "Redis", + "ReplicaSet", + "ReplicationController", + "Rescheduler", + "RethinkDB", + "Secret", + "Security", + "Spark", + "StatefulSet", + "Storm" + ], + "autoscaling": [ + "Cluster size", + "Horizontal" + ], + "big-data": [ + "Hazelcast" + ], + "cli": [ + "Kubectl" + ], + "cluster-lifecycle": [ + "GKE node", + "Garbage", + "Nodes", + "Upgrade" + ], + "federation": [ + "Federated", + "Federation" + ], + "instrumentation": [ + "Cluster level", + "Kibana", + "MetricsGrabber", + "Monitoring" + ], + "network": [ + "ClusterDns", + "DNS", + "ESIPP", + "Firewall", + "Load", + "Network", + "Service" + ], + "node": [ + "AppArmor", + "Cadvisor", + "Container", + "Docker", + "Downward", + "EmptyDir", + "Events", + "HostPath", + "ImageID", + "InitContainer", + "Initial", + "Kubelet", + "LimitRange", + "Liveness", + "Logging", + "MemoryEviction", + "MirrorPod", + "NodeOutOfDisk", + "NodeProblemDetector", + "Opaque", + "Pod garbage", + "Pods", + "Port", + "PreStop", + "PrivilegedPod", + "Probing", + "Proxy", + "Reboot", + "Restart", + "SimpleMount", + "Sysctls", + "Variable", + "kubelet", + "when" + ], + "scalability": [ + "Density" + ], + "scheduling": [ + "DisruptionController", + "NoExecuteTaintManager", + "SchedulerPredicates" + ], + "storage": [ + "Dynamic", + "GCP", + "GKE local", + "PersistentVolumes", + "Pod Disks", + "Projected", + "Volume" + ], + "ui": [ + "Kubernetes" + ] +}