GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — develop ( 264bc7...d8ccfa )
by Stuart
07:51
created

DsbuildProvisioner::writeDsbuildParamsYamlFile()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 5

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 14
rs 9.4286
cc 1
eloc 5
nc 1
nop 1
1
<?php
2
3
/**
4
 * Copyright (c) 2011-present Mediasift Ltd
5
 * All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 *
11
 *   * Redistributions of source code must retain the above copyright
12
 *     notice, this list of conditions and the following disclaimer.
13
 *
14
 *   * Redistributions in binary form must reproduce the above copyright
15
 *     notice, this list of conditions and the following disclaimer in
16
 *     the documentation and/or other materials provided with the
17
 *     distribution.
18
 *
19
 *   * Neither the names of the copyright holders nor the names of his
20
 *     contributors may be used to endorse or promote products derived
21
 *     from this software without specific prior written permission.
22
 *
23
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34
 * POSSIBILITY OF SUCH DAMAGE.
35
 *
36
 * @category  Libraries
37
 * @package   Storyplayer/ProvisioningLib
38
 * @author    Stuart Herbert <[email protected]>
39
 * @author    Nicola Asuni <[email protected]>
40
 * @copyright 2011-present Mediasift Ltd www.datasift.com
41
 * @license   http://www.opensource.org/licenses/bsd-license.php  BSD License
42
 * @link      http://datasift.github.io/storyplayer
43
 */
44
45
namespace DataSift\Storyplayer\ProvisioningLib\Provisioners;
46
47
use DataSift\Stone\ObjectLib\BaseObject;
48
use DataSift\Storyplayer\CommandLib\CommandResult;
49
use DataSift\Storyplayer\CommandLib\CommandRunner;
50
use DataSift\Storyplayer\PlayerLib\StoryTeller;
51
use DataSift\Storyplayer\ProvisioningLib\ProvisioningDefinition;
52
use Storyplayer\SPv2\Modules\Exceptions;
53
use Storyplayer\SPv2\Modules\Host;
54
use Storyplayer\SPv2\Modules\Log;
55
use Storyplayer\SPv2\Modules\Shell;
56
57
/**
58
 * support for provisioning via dsbuild
59
 *
60
 * @category  Libraries
61
 * @package   Storyplayer/ProvisioningLib
62
 * @author    Stuart Herbert <[email protected]>
63
 * @copyright 2011-present Mediasift Ltd www.datasift.com
64
 * @license   http://www.opensource.org/licenses/bsd-license.php  BSD License
65
 * @link      http://datasift.github.io/storyplayer
66
 */
67
class DsbuildProvisioner extends Provisioner
68
{
69
    public function __construct(StoryTeller $st)
70
    {
71
        // remember for the future
72
        $this->st = $st;
73
    }
74
75 View Code Duplication
    public function buildDefinitionFor($env)
76
    {
77
        // our return value
78
        $provDef = new ProvisioningDefinition;
79
80
        // what are we doing?
81
        $log = Log::usingLog()->startAction("build dsbuild provisioning definition");
82
83
        // add in each machine in the environment
84
        foreach ($env->details->machines as $hostId => $machine) {
85
            usingProvisioningDefinition($provDef)->addHost($hostId);
86
87
            foreach ($machine->roles as $role) {
88
                usingProvisioningDefinition($provDef)->addRole($role)->toHost($hostId);
89
            }
90
91
            if (isset($machine->params)) {
92
                $params = [];
93
                foreach ($machine->params as $paramName => $paramValue) {
94
                    $params[$paramName]  = fromConfig()->get('hosts.' . $hostId . '.params.'.$paramName);
95
                }
96
                if (count($params)) {
97
                    usingProvisioningDefinition($provDef)->addParams($params)->toHost($hostId);
98
                }
99
            }
100
        }
101
102
        // all done
103
        $log->endAction($provDef);
104
        return $provDef;
105
    }
106
107
    public function provisionHosts(ProvisioningDefinition $hosts, $provConfig)
108
    {
109
        // what are we doing?
110
        $log = Log::usingLog()->startAction("use dsbuild to provision host(s)");
111
112
        // the params file that we are going to output
113
        $dsbuildParams = new BaseObject;
114
115
        // build up the list of settings to write out
116
        foreach($hosts as $hostId => $hostProps) {
117
            // what is the host's IP address?
118
            $ipAddress = Host::fromHost($hostId)->getIpAddress();
119
120
            $propName = $hostId . '_ipv4Address';
121
            $dsbuildParams->$propName = $ipAddress;
122
            if (isset($hostProps->params)) {
123
                $dsbuildParams->mergeFrom($hostProps->params);
124
            }
125
        }
126
127
        // add in all the config settings that we know about
128
        $dsbuildParams->storyplayer_ipv4Address = fromConfig()->get('storyplayer.ipAddress');
129
        $dsbuildParams->mergeFrom($this->flattenData($this->st->getActiveConfig()->getData('')));
130
131
        // write them out
132
        $this->writeDsbuildParamsShellFile((array)$dsbuildParams);
133
        $this->writeDsbuildParamsYamlFile((array)$dsbuildParams);
134
135
        // at this point, we are ready to attempt provisioning
136
        //
137
        // provision each host in the order that they're listed
138
        foreach($hosts as $hostId => $hostProps) {
139
            // which dsbuildfile are we going to run?
140
            $hostDir = Host::fromHost($hostId)->getLocalFolder();
141
            $dsbuildFilename = $this->getDsbuildFilename($hostDir, $provConfig, $hostId);
142
            if ($dsbuildFilename === null) {
143
                // there is no dsbuildfile at all to run
144
                $log->endAction("cannot find dsbuildfile to run :(");
145
                throw Exceptions::newActionFailedException(__METHOD__, "no dsbuildfile to run");
146
            }
147
148
            // at this point, we are ready to provision
149
            $commandRunner = new CommandRunner();
150
151
            // copy the dsbuildparams files to the target machine using scp
152
            // NOTE: the "vagrant rsync" command seems not working with some Vagrant provisioners (e.g. OpenStack)
153
            $command = 'scp'
154
                .' '.$dsbuildParams->{'hosts_'.$hostId.'_scpOptions_0'}
155
                .' '.$dsbuildParams->{'hosts_'.$hostId.'_scpOptions_1'}
156
                .' dsbuildparams.*'
157
                .' '.$dsbuildParams->{'hosts_'.$hostId.'_sshUsername'}
158
                .'@'.$dsbuildParams->{'hosts_'.$hostId.'_ipAddress'}
159
                .':/vagrant/';
160
            $result = $commandRunner->runSilently($command);
161
162
            if (!$result->didCommandSucceed()) {
163
                // try to rsync folders in case of scp fail
164
                $command = 'vagrant rsync ' . $hostId;
165
                $commandRunner->runSilently($command);
166
            }
167
168
            // provision
169
            $command = 'sudo bash /vagrant/' . $dsbuildFilename;
170
            $result = Shell::onHost($hostId)->runCommand($command);
171
172
            // what happened?
173
            if (!$result->didCommandSucceed()) {
174
                throw Exceptions::newActionFailedException(__METHOD__, "provisioning failed");
175
            }
176
        }
177
178
        // all done
179
        $log->endAction();
180
    }
181
182
    /**
183
     * @param array $vars
184
     */
185
    protected function writeDsbuildParamsYamlFile($vars)
186
    {
187
        // what are we doing?
188
        $log = Log::usingLog()->startAction("write dsbuildparams.yml");
189
190
        // what is the path to the file?
191
        $filename = "dsbuildparams.yml";
192
193
        // write the data
194
        usingYamlFile($filename)->writeDataToFile($vars);
195
196
        // all done
197
        $log->endAction();
198
    }
199
200
    /**
201
     * @param array $vars
202
     */
203
    protected function writeDsbuildParamsShellFile($vars)
204
    {
205
        // what are we doing?
206
        $log = Log::usingLog()->startAction("write dsbuildparams.sh");
207
208
        // what is the path to the file?
209
        $filename = "dsbuildparams.sh";
210
211
        // build the data to write
212
        $output = "";
213
        foreach ($vars as $name => $value) {
214
            $name = str_replace("-", "_", $name);
215
            $output .= strtoupper($name) . "='" . $value . "';" . PHP_EOL;
216
        }
217
218
        // write the data
219
        file_put_contents($filename, $output);
220
221
        // all done
222
        $log->endAction();
223
    }
224
225
    /**
226
     * converts a tree of data into underscore_notation
227
     *
228
     * @param  mixed $inputData
229
     *         the data to flatten
230
     * @param  string $prefix
231
     *         the path to the parent of the inputData
232
     * @return array
233
     *         the flattened data
234
     */
235
    protected function flattenData($inputData, $prefix="")
236
    {
237
        $retval = [];
238
239
        foreach ($inputData as $name => $dataToFlatten)
240
        {
241
            if (is_object($dataToFlatten) || is_array($dataToFlatten)) {
242
                $retval = array_merge($retval, $this->flattenData($dataToFlatten, $prefix . $name . "_"));
243
            }
244
            else {
245
                $retval[$prefix . $name] = $dataToFlatten;
246
            }
247
        }
248
249
        return $retval;
250
    }
251
252
    /**
253
     * find the provisioning script to run for a given hostId
254
     *
255
     * @param  string $baseFolder
256
     *         the folder we should look in
257
     * @param  BaseObject $provConfig
258
     *         the "provisioning" section from the test environment config
259
     * @param  string $hostId
260
     *         the ID of the host that we are provisioning
261
     * @return string|null
262
     *         path to the file to execute
263
     */
264
    protected function getDsbuildFilename($baseFolder, $provConfig, $hostId)
265
    {
266
        if (isset($provConfig->execute)) {
267
            $basename = dirname($provConfig->execute) . "/" . basename($provConfig->execute, '.sh');
268
        }
269
        else {
270
            $basename = "dsbuildfile";
271
        }
272
273
        $candidateFilenames = [
274
            $basename . "-" . $hostId . '.sh',
275
            $basename . "-" . $hostId,
276
            $basename . ".sh",
277
            $basename,
278
        ];
279
280
        foreach ($candidateFilenames as $candidateFilename) {
281
            if (file_exists($baseFolder . '/' . $candidateFilename)) {
282
                return $candidateFilename;
283
            }
284
        }
285
286
        // no file found
287
        return null;
288
    }
289
}
290