aboutsummaryrefslogtreecommitdiff
path: root/node/prepare_build_config.py
blob: 60ddcf32eb2c093b1085d7146944f163e32bc3d8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#!/usr/bin/env python
import sys
import os
import base64
import re
import pipes
import optparse

SLAVE_TYPE_FILE_EC2 = "/var/run/build-tools/slave-type"
# sf-safe build config is written to this file
BUILD_CONFIG_FILE_EC2 = "/var/run/build-tools/build-config"
SLAVE_TYPE_FILE_VPS = "/tmp/build-tools/slave-type"
# sf-safe build config is written to this file
BUILD_CONFIG_FILE_VPS = "/tmp/build-tools/build-config"
SLAVE_TYPE_RESTRICTED = "restricted builds"


class BuildConfigMismatchException(Exception):
    pass


def shell_unquote(s):
    # Primitive implementation, but we didn't really advertize
    # support for shell quoting, and I never saw it used
    if len(s) < 2:
        return s
    if s[0] == '"' and s[-1] == '"':
        return s[1:-1]
    if s[0] == "'" and s[-1] == "'":
        return s[1:-1]
    return s

def is_on_ec2():
    return os.path.exists("/etc/cloud/cloud.cfg")

def get_slave_type():
    slave_type = ""
    try:
        if is_on_ec2():
            f = open(SLAVE_TYPE_FILE_EC2)
        else:
            f = open(SLAVE_TYPE_FILE_VPS)
        slave_type = f.read().rstrip()
        f.close()
    except:
        pass
    return slave_type


def validate_config(config, slave_type):
    """Validate various constraints on the config params and overall
    environment."""
    full_job_name = os.environ.get("JOB_NAME")
    owner, job_subname = full_job_name.split("_", 1)

    # Deduce parameter "categories" which we can directly match
    # against each other
    if SLAVE_TYPE_RESTRICTED in slave_type:
        slave_type_cat = "restricted"
    else:
        slave_type_cat = "normal"

    if owner == "projectara-software-dev" or owner.endswith("-restricted"):
        owner_cat = "restricted"
    else:
        owner_cat = "normal"

    if config.get("BUILD_TYPE", "build-android") in ["build-android-private",
                                                     "build-android-restricted",
                                                     "build-android-toolchain-linaro-restricted",
                                                     "build-android-testsuite-restricted"]:
        build_type_cat = "restricted"
    else:
        build_type_cat = "normal"

    # Now, process few most expected mismatches in adhoc way,
    # to provide better error messages
    if slave_type_cat == "restricted" and owner_cat != "restricted":
        raise BuildConfigMismatchException("Only jobs owned by ~linaro-android-*-restricted may run on this build slave type")

    if owner_cat == "restricted" and build_type_cat != "restricted":
        raise BuildConfigMismatchException("Jobs owned by ~linaro-android-*-restricted must use BUILD_TYPE=build-android-*-restricted")

    # Finally, generic mismatch detection
    if slave_type_cat != owner_cat or slave_type_cat != build_type_cat:
        raise BuildConfigMismatchException("Incompatible slave type, job owner and build type")


def convert_config_to_shell(config_text, out_filename):
    config = {}
    out = open(out_filename, "w")

    for l in config_text.split("\n"):
        l = l.strip()
        if not l or l[0] == "#":
            continue
        if not re.match(r"[A-Za-z][A-Za-z0-9_]*=", l):
            print "Invalid build config syntax: " + l
            sys.exit(1)
        var, val = l.split("=", 1)
        val = shell_unquote(val)
        config[var] = val
        out.write("%s=%s\n" % (var, pipes.quote(val)))
    out.close()
    return config


def main(config_in, is_base64):
    if is_base64:
        config_in = base64.b64decode(config_in)
    if is_on_ec2():
        BUILD_CONFIG_FILE=BUILD_CONFIG_FILE_EC2
    else:
        BUILD_CONFIG_FILE=BUILD_CONFIG_FILE_VPS
    config = convert_config_to_shell(config_in, BUILD_CONFIG_FILE)
    #try:
    #    validate_config(config, get_slave_type())
    #except BuildConfigMismatchException, e:
    #    print str(e)
    #    sys.exit(1)

if __name__ == "__main__":
    optparser = optparse.OptionParser(usage="%prog")
    optparser.add_option("--base64", action="store_true", help="Process only jobs matching regex pattern")
    options, args = optparser.parse_args(sys.argv[1:])
    if len(args) != 1:
        optparser.error("Wrong number of arguments")
    main(args[0], options.base64)