summaryrefslogtreecommitdiffstats
path: root/node-admin/scripts/app.sh
blob: 8375441350838f683228cc2b1f79896c3f343478 (plain) (blame)
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#!/bin/bash
# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

set -e

source "${0%/*}"/common.sh

declare SCRIPTS_DIR="${0%/*}"

declare -r APP_DIR_NAME_UNDER_SHARED=app

function Usage {
    UsageHelper "$@" <<EOF
Usage: $SCRIPT_NAME <command> [<app-dir>]
Deploy (or undeploy) application rooted at <app-dir> on localhost Config Server.

The local zone must be up and running. <app-dir> should point to
e.g. vespa/basic-search-on-docker/target/application.
EOF
}

function RunOnConfigServer {
    docker exec config-server "$@"
}

function VerifyApp {
    local app_dir="$1"

    # Sanity-check app_dir
    if ! [ -d "$app_dir" ]
    then
        Fail "<app-dir> '$app_dir' is not a directory"
    fi

    local services_xml="$app_dir"/services.xml
    if ! [ -f "$services_xml" ]
    then
        Fail "Failed to find services.xml in <app-dir> '$app_dir'"
    fi

    # Verify there's no <admin> element.
    if grep -qE '<admin[ >]' "$services_xml"
    then
        Fail "services.xml cannot contain an <admin> element in hosted Vespa"
    fi

    # Verify <nodes> seems to be correctly specified (warning: this test is
    # incomplete).
    if grep -qE "<nodes>" "$services_xml" ||
            ! grep -qE "<nodes (.* )?docker-image=" "$services_xml" ||
            ! grep -qE "<nodes (.* )?flavor=[\"']docker[\"']" "$services_xml"
    then
        Fail "You must specify the <nodes> element in the following form" \
             "in hosted Vespa w/Docker:" \
             "  <nodes count=\"2\" flavor=\"docker\" docker-image=\"IMAGE\" />" \
             "where IMAGE is e.g. vespa-local:latest."
    fi
}

# Copies the application rooted at $1 to a directory tree shared with the
# Config Server.
function CopyToSharedDir {
    local app_dir="$1"

    local shared_dir_on_localhost="$APPLICATION_STORAGE_ROOT/$CONFIG_SERVER_CONTAINER_NAME/$ROOT_DIR_SHARED_WITH_HOST"
    if ! [ -d "$shared_dir_on_localhost" ]
    then
        Fail "Failed to find the Config Server's shared directory on" \
             "localhost '$shared_dir_on_localhost', has the" \
             "$CONFIG_SERVER_CONTAINER_NAME container been started?"
    fi


    local shared_app_dir_on_localhost="$shared_dir_on_localhost/$APP_DIR_NAME_UNDER_SHARED"
    if [ "$shared_app_dir_on_localhost" != /home/docker/container-storage/config-server/shared/app ]
    then
        # This duplication of code is a safety-guard against 'rm -rf' unknown
        # directories.
        Fail "We're about to remove '$shared_app_dir_on_localhost', but it's" \
             "pointing to something unexpected, refusing to proceed..."
    fi

    echo -n "Copying application to '$shared_app_dir_on_localhost'... "
    rm -rf "$shared_app_dir_on_localhost"
    cp -r "$app_dir" "$shared_app_dir_on_localhost"
    echo done
}

function DeployApp {
    if (($# != 1))
    then
        Usage
    fi

    local app_dir="$1"

    VerifyApp "$app_dir"

    CopyToSharedDir "$app_dir"

    # Create tenant
    echo -n "Creating tenant... "
    local create_tenant_response
    if create_tenant_response=$(curl --silent --show-error -X PUT "http://$CONFIG_SERVER_HOSTNAME:$CONFIG_SERVER_PORT/application/v2/tenant/$TENANT_NAME" 2>&1)
    then
        if ! [[ "$create_tenant_response" =~ "Tenant $TENANT_NAME created" ]] &&
                ! [[ "$create_tenant_response" =~ "already exists" ]]
        then
            echo
            Fail "May have failed to create the tenant: '$create_tenant_response'"
        fi
    else
        echo
        Fail "Failed to create the tenant: $?: '$create_tenant_response'"
    fi
    echo done

    # Deploy app
    local app_dir_on_config_server="/$ROOT_DIR_SHARED_WITH_HOST/$APP_DIR_NAME_UNDER_SHARED"
    RunOnConfigServer $VESPA_HOME/bin/deploy -e "$TENANT_NAME" prepare "$app_dir_on_config_server"
    echo "Activating application"
    RunOnConfigServer $VESPA_HOME/bin/deploy -e "$TENANT_NAME" activate
}

function UndeployApp {
    if (($# != 0))
    then
        Usage "undeploy takes no arguments"
    fi

    local app_name=default
    local output
    echo -n "Removing application $TENANT_NAME:$app_name... "
    if ! output=$(curl --silent --show-error -X DELETE "http://$CONFIG_SERVER_HOSTNAME:$CONFIG_SERVER_PORT/application/v2/tenant/$TENANT_NAME/application/$app_name")
    then
        echo
        Fail "Failed to remove application: $output"
    fi

    echo done
}

function Main {
    if (($# == 0))
    then
        Usage "Missing command"
    fi
    local command="$1"
    shift

    case "$command" in
        deploy) DeployApp "$@" ;;
        undeploy) UndeployApp "$@" ;;
        *) Usage "Unknown command '$command'" ;;
    esac
}

Main "$@"