#!/usr/bin/env python # Copyright (C) 2016 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ This script will populate an empty standard Gerrit instance with some data for local testing. This script requires 'requests'. If you do not have this module, run 'pip3 install requests' to install it. TODO(hiesel): Make real git commits instead of empty changes TODO(hiesel): Add comments """ import atexit import json import os import random import shutil import subprocess import tempfile import requests import requests.auth DEFAULT_TMP_PATH = "/tmp" TMP_PATH = "" BASE_URL = "http://localhost:8080/a/" ACCESS_URL = BASE_URL + "access/" ACCOUNTS_URL = BASE_URL + "accounts/" CHANGES_URL = BASE_URL + "changes/" CONFIG_URL = BASE_URL + "config/" GROUPS_URL = BASE_URL + "groups/" PLUGINS_URL = BASE_URL + "plugins/" PROJECTS_URL = BASE_URL + "projects/" ADMIN_DIGEST = requests.auth.HTTPDigestAuth("admin", "secret") # GROUP_ADMIN stores a GroupInfo for the admin group (see Gerrit rest docs) # In addition, GROUP_ADMIN["name"] stores the admin group"s name. GROUP_ADMIN = {} HEADERS = {"Content-Type": "application/json", "charset": "UTF-8"} # Random names from US Census Data FIRST_NAMES = [ "Casey", "Yesenia", "Shirley", "Tara", "Wanda", "Sheryl", "Jaime", "Elaine", "Charlotte", "Carly", "Bonnie", "Kirsten", "Kathryn", "Carla", "Katrina", "Melody", "Suzanne", "Sandy", "Joann", "Kristie", "Sally", "Emma", "Susan", "Amanda", "Alyssa", "Patty", "Angie", "Dominique", "Cynthia", "Jennifer", "Theresa", "Desiree", "Kaylee", "Maureen", "Jeanne", "Kellie", "Valerie", "Nina", "Judy", "Diamond", "Anita", "Rebekah", "Stefanie", "Kendra", "Erin", "Tammie", "Tracey", "Bridget", "Krystal", "Jasmin", "Sonia", "Meghan", "Rebecca", "Jeanette", "Meredith", "Beverly", "Natasha", "Chloe", "Selena", "Teresa", "Sheena", "Cassandra", "Rhonda", "Tami", "Jodi", "Shelly", "Angela", "Kimberly", "Terry", "Joanna", "Isabella", "Lindsey", "Loretta", "Dana", "Veronica", "Carolyn", "Laura", "Karen", "Dawn", "Alejandra", "Cassie", "Lorraine", "Yolanda", "Kerry", "Stephanie", "Caitlin", "Melanie", "Kerri", "Doris", "Sandra", "Beth", "Carol", "Vicki", "Shelia", "Bethany", "Rachael", "Donna", "Alexandra", "Barbara", "Ana", "Jillian", "Ann", "Rachel", "Lauren", "Hayley", "Misty", "Brianna", "Tanya", "Danielle", "Courtney", "Jacqueline", "Becky", "Christy", "Alisha", "Phyllis", "Faith", "Jocelyn", "Nancy", "Gloria", "Kristen", "Evelyn", "Julie", "Julia", "Kara", "Chelsey", "Cassidy", "Jean", "Chelsea", "Jenny", "Diana", "Haley", "Kristine", "Kristina", "Erika", "Jenna", "Alison", "Deanna", "Abigail", "Melissa", "Sierra", "Linda", "Monica", "Tasha", "Traci", "Yvonne", "Tracy", "Marie", "Maria", "Michaela", "Stacie", "April", "Morgan", "Cathy", "Darlene", "Cristina", "Emily" "Ian", "Russell", "Phillip", "Jay", "Barry", "Brad", "Frederick", "Fernando", "Timothy", "Ricardo", "Bernard", "Daniel", "Ruben", "Alexis", "Kyle", "Malik", "Norman", "Kent", "Melvin", "Stephen", "Daryl", "Kurt", "Greg", "Alex", "Mario", "Riley", "Marvin", "Dan", "Steven", "Roberto", "Lucas", "Leroy", "Preston", "Drew", "Fred", "Casey", "Wesley", "Elijah", "Reginald", "Joel", "Christopher", "Jacob", "Luis", "Philip", "Mark", "Rickey", "Todd", "Scott", "Terrence", "Jim", "Stanley", "Bobby", "Thomas", "Gabriel", "Tracy", "Marcus", "Peter", "Michael", "Calvin", "Herbert", "Darryl", "Billy", "Ross", "Dustin", "Jaime", "Adam", "Henry", "Xavier", "Dominic", "Lonnie", "Danny", "Victor", "Glen", "Perry", "Jackson", "Grant", "Gerald", "Garrett", "Alejandro", "Eddie", "Alan", "Ronnie", "Mathew", "Dave", "Wayne", "Joe", "Craig", "Terry", "Chris", "Randall", "Parker", "Francis", "Keith", "Neil", "Caleb", "Jon", "Earl", "Taylor", "Bryce", "Brady", "Max", "Sergio", "Leon", "Gene", "Darin", "Bill", "Edgar", "Antonio", "Dalton", "Arthur", "Austin", "Cristian", "Kevin", "Omar", "Kelly", "Aaron", "Ethan", "Tom", "Isaac", "Maurice", "Gilbert", "Hunter", "Willie", "Harry", "Dale", "Darius", "Jerome", "Jason", "Harold", "Kerry", "Clarence", "Gregg", "Shane", "Eduardo", "Micheal", "Howard", "Vernon", "Rodney", "Anthony", "Levi", "Larry", "Franklin", "Jimmy", "Jonathon", "Carl", ] LAST_NAMES = [ "Savage", "Hendrix", "Moon", "Larsen", "Rocha", "Burgess", "Bailey", "Farley", "Moses", "Schmidt", "Brown", "Hoover", "Klein", "Jennings", "Braun", "Rangel", "Casey", "Dougherty", "Hancock", "Wolf", "Henry", "Thomas", "Bentley", "Barnett", "Kline", "Pitts", "Rojas", "Sosa", "Paul", "Hess", "Chase", "Mckay", "Bender", "Colins", "Montoya", "Townsend", "Potts", "Ayala", "Avery", "Sherman", "Tapia", "Hamilton", "Ferguson", "Huang", "Hooper", "Zamora", "Logan", "Lloyd", "Quinn", "Monroe", "Brock", "Ibarra", "Fowler", "Weiss", "Montgomery", "Diaz", "Dixon", "Olson", "Robertson", "Arias", "Benjamin", "Abbott", "Stein", "Schroeder", "Beck", "Velasquez", "Barber", "Nichols", "Ortiz", "Burns", "Moody", "Stokes", "Wilcox", "Rush", "Michael", "Kidd", "Rowland", "Mclean", "Saunders", "Chung", "Newton", "Potter", "Hickman", "Ray", "Larson", "Figueroa", "Duncan", "Sparks", "Rose", "Hodge", "Huynh", "Joseph", "Morales", "Beasley", "Mora", "Fry", "Ross", "Novak", "Hahn", "Wise", "Knight", "Frederick", "Heath", "Pollard", "Vega", "Mcclain", "Buckley", "Conrad", "Cantrell", "Bond", "Mejia", "Wang", "Lewis", "Johns", "Mcknight", "Callahan", "Reynolds", "Norris", "Burnett", "Carey", "Jacobson", "Oneill", "Oconnor", "Leonard", "Mckenzie", "Hale", "Delgado", "Spence", "Brandt", "Obrien", "Bowman", "James", "Avila", "Roberts", "Barker", "Cohen", "Bradley", "Prince", "Warren", "Summers", "Little", "Caldwell", "Garrett", "Hughes", "Norton", "Burke", "Holden", "Merritt", "Lee", "Frank", "Wiley", "Ho", "Weber", "Keith", "Winters", "Gray", "Watts", "Brady", "Aguilar", "Nicholson", "David", "Pace", "Cervantes", "Davis", "Baxter", "Sanchez", "Singleton", "Taylor", "Strickland", "Glenn", "Valentine", "Roy", "Cameron", "Beard", "Norman", "Fritz", "Anthony", "Koch", "Parrish", "Herman", "Hines", "Sutton", "Gallegos", "Stephenson", "Lozano", "Franklin", "Howe", "Bauer", "Love", "Ali", "Ellison", "Lester", "Guzman", "Jarvis", "Espinoza", "Fletcher", "Burton", "Woodard", "Peterson", "Barajas", "Richard", "Bryan", "Goodman", "Cline", "Rowe", "Faulkner", "Crawford", "Mueller", "Patterson", "Hull", "Walton", "Wu", "Flores", "York", "Dickson", "Barnes", "Fisher", "Strong", "Juarez", "Fitzgerald", "Schmitt", "Blevins", "Villa", "Sullivan", "Velazquez", "Horton", "Meadows", "Riley", "Barrera", "Neal", "Mendez", "Mcdonald", "Floyd", "Lynch", "Mcdowell", "Benson", "Hebert", "Livingston", "Davies", "Richardson", "Vincent", "Davenport", "Osborn", "Mckee", "Marshall", "Ferrell", "Martinez", "Melton", "Mercer", "Yoder", "Jacobs", "Mcdaniel", "Mcmillan", "Peters", "Atkinson", "Wood", "Briggs", "Valencia", "Chandler", "Rios", "Hunter", "Bean", "Hicks", "Hays", "Lucero", "Malone", "Waller", "Banks", "Myers", "Mitchell", "Grimes", "Houston", "Hampton", "Trujillo", "Perkins", "Moran", "Welch", "Contreras", "Montes", "Ayers", "Hayden", "Daniel", "Weeks", "Porter", "Gill", "Mullen", "Nolan", "Dorsey", "Crane", "Estes", "Lam", "Wells", "Cisneros", "Giles", "Watson", "Vang", "Scott", "Knox", "Hanna", "Fields", ] def clean(json_string): # Strip JSON XSS Tag json_string = json_string.strip() if json_string.startswith(")]}'"): return json_string[5:] return json_string def digest_auth(user): return requests.auth.HTTPDigestAuth(user["username"], user["http_password"]) def fetch_admin_group(): global GROUP_ADMIN # Get admin group r = json.loads(clean(requests.get(GROUPS_URL + "?suggest=ad&p=All-Projects", headers=HEADERS, auth=ADMIN_DIGEST).text)) admin_group_name = r.keys()[0] GROUP_ADMIN = r[admin_group_name] GROUP_ADMIN["name"] = admin_group_name def generate_random_text(): return " ".join([random.choice("lorem ipsum " "doleret delendam " "\n esse".split(" ")) for _ in xrange(1, 100)]) def set_up(): global TMP_PATH TMP_PATH = tempfile.mkdtemp() atexit.register(clean_up) os.makedirs(TMP_PATH + "/ssh") os.makedirs(TMP_PATH + "/repos") fetch_admin_group() def get_random_users(num_users): users = random.sample([(f, l) for f in FIRST_NAMES for l in LAST_NAMES], num_users) names = [] for u in users: names.append({"firstname": u[0], "lastname": u[1], "name": u[0] + " " + u[1], "username": u[0] + u[1], "email": u[0] + "." + u[1] + "@gerritcodereview.com", "http_password": "secret", "groups": []}) return names def generate_ssh_keys(gerrit_users): for user in gerrit_users: key_file = TMP_PATH + "/ssh/" + user["username"] + ".key" subprocess.check_output(["ssh-keygen", "-f", key_file, "-N", ""]) with open(key_file + ".pub", "r") as f: user["ssh_key"] = f.read() def create_gerrit_groups(): groups = [ {"name": "iOS-Maintainers", "description": "iOS Maintainers", "visible_to_all": True, "owner": GROUP_ADMIN["name"], "owner_id": GROUP_ADMIN["id"]}, {"name": "Android-Maintainers", "description": "Android Maintainers", "visible_to_all": True, "owner": GROUP_ADMIN["name"], "owner_id": GROUP_ADMIN["id"]}, {"name": "Backend-Maintainers", "description": "Backend Maintainers", "visible_to_all": True, "owner": GROUP_ADMIN["name"], "owner_id": GROUP_ADMIN["id"]}, {"name": "Script-Maintainers", "description": "Script Maintainers", "visible_to_all": True, "owner": GROUP_ADMIN["name"], "owner_id": GROUP_ADMIN["id"]}, {"name": "Security-Team", "description": "Sec Team", "visible_to_all": False, "owner": GROUP_ADMIN["name"], "owner_id": GROUP_ADMIN["id"]}] for g in groups: requests.put(GROUPS_URL + g["name"], json.dumps(g), headers=HEADERS, auth=ADMIN_DIGEST) return [g["name"] for g in groups] def create_gerrit_projects(owner_groups): projects = [ {"id": "android", "name": "Android", "parent": "All-Projects", "branches": ["master"], "description": "Our android app.", "owners": [owner_groups[0]], "create_empty_commit": True}, {"id": "ios", "name": "iOS", "parent": "All-Projects", "branches": ["master"], "description": "Our ios app.", "owners": [owner_groups[1]], "create_empty_commit": True}, {"id": "backend", "name": "Backend", "parent": "All-Projects", "branches": ["master"], "description": "Our awesome backend.", "owners": [owner_groups[2]], "create_empty_commit": True}, {"id": "scripts", "name": "Scripts", "parent": "All-Projects", "branches": ["master"], "description": "some small scripts.", "owners": [owner_groups[3]], "create_empty_commit": True}] for p in projects: requests.put(PROJECTS_URL + p["name"], json.dumps(p), headers=HEADERS, auth=ADMIN_DIGEST) return [p["name"] for p in projects] def create_gerrit_users(gerrit_users): for user in gerrit_users: requests.put(ACCOUNTS_URL + user["username"], json.dumps(user), headers=HEADERS, auth=ADMIN_DIGEST) def create_change(user, project_name): random_commit_message = generate_random_text() change = { "project": project_name, "subject": random_commit_message.split("\n")[0], "branch": "master", "status": "NEW", } requests.post(CHANGES_URL, json.dumps(change), headers=HEADERS, auth=digest_auth(user)) def clean_up(): shutil.rmtree(TMP_PATH) def main(): set_up() gerrit_users = get_random_users(100) group_names = create_gerrit_groups() for idx, u in enumerate(gerrit_users): u["groups"].append(group_names[idx % len(group_names)]) if idx % 5 == 0: # Also add to security group u["groups"].append(group_names[4]) generate_ssh_keys(gerrit_users) create_gerrit_users(gerrit_users) project_names = create_gerrit_projects(group_names) for idx, u in enumerate(gerrit_users): for _ in xrange(random.randint(1, 5)): create_change(u, project_names[4 * idx / len(gerrit_users)]) main()