Completed
Pull Request — master (#12)
by Chad
02:24 queued 01:06
created

ChefEc2   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 150
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 0
Metric Value
wmc 8
lcom 1
cbo 0
dl 0
loc 150
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
B createServer() 0 33 2
A updateServers() 0 18 2
A awsCredentialParameters() 0 7 1
A chefClientParameters() 0 8 1
A ec2SshParameters() 0 7 1
1
<?php
2
3
namespace TraderInteractive\Chef;
4
5
class ChefEc2
6
{
7
    /**
8
     * @var string The base command for knife.
9
     */
10
    private $baseKnifeCommand;
11
12
    /**
13
     * @var string The url for the chef API.
14
     */
15
    private $chefServerUrl;
16
17
    /**
18
     * @var array The credentials needed to interact with knife-ec2.
19
     */
20
    private $credentials;
21
22
    /**
23
     * Initialize the wrapper around knife-ec2.
24
     *
25
     * @param string $baseKnifeCommand The base command for knife.  could be 'knife' if knife is already in the path.
26
     *                                 If using bundler to install knife-ec2, you could do something
27
     *                                 like 'BUNDLE_GEMFILE=/path/to/Gemfile bundle exec knife'.
28
     * @param string $chefServerUrl    The url for the chef API.
29
     * @param array  $credentials      The credentials needed to interact with knife-ec2.  Includes awsAccessKeyId and
30
     *                                 awsSecretAccessKey.
31
     */
32
    public function __construct($baseKnifeCommand, $chefServerUrl, array $credentials)
33
    {
34
        $this->baseKnifeCommand = $baseKnifeCommand;
35
        $this->chefServerUrl = $chefServerUrl;
36
        $this->credentials = $credentials;
37
    }
38
39
    /**
40
     * Instantiate a new server.
41
     *
42
     * @param string $region The AWS region the server is in.
43
     * @param string $ami The region-specific AMI to use.
44
     * @param string $flavor The flavor of server to create, e.g. t1.micro.
45
     * @param array $runList The roles/recipes for the chef run list.
46
     * @param string $progressFile A file path to store the server output in.
47
     * @param array $options Additional options for knife-ec2.  For example: ['-groups' => 'foo']
48
     * @param array $tags Tags to set for the server.
49
     * @param string $chefVersion The chef version to use to bootstrap the server.
50
     *
51
     * @return void
52
     */
53
    public function createServer(
54
        $region,
55
        $ami,
56
        $flavor,
57
        array $runList,
58
        $progressFile,
59
        array $options = [],
60
        array $tags = [],
61
        $chefVersion = '11.8.0'
62
    ) {
63
64
        $tagList = [];
65
        foreach ($tags as $key => $value) {
66
            $tagList[] = "{$key}={$value}";
67
        }
68
69
        $fullOptions = [
70
            '--region' => $region,
71
            '--image' => $ami,
72
            '--flavor' => $flavor,
73
            '--run-list' => implode(',', $runList),
74
            '--tags' => implode(',', $tagList),
75
            '--bootstrap-version' => $chefVersion,
76
        ];
77
78
        $fullOptions += $options;
79
        $fullOptions += $this->awsCredentialParameters();
80
        $fullOptions += $this->chefClientParameters();
81
        $fullOptions += $this->ec2SshParameters();
82
83
        $command = \Hiatus\addArguments("{$this->baseKnifeCommand} ec2 server create", $fullOptions);
84
        \Hiatus\execX("{$command} >" . escapeshellarg($progressFile) . ' 2>&1 &');
85
    }
86
87
    /**
88
     * Runs chef client on the servers that match the query storing command output in the given file.
89
     *
90
     * @param string $query The chef query to specify what servers to update.
91
     * @param string $progressFile The filename to send the knife output to.
92
     * @param array $options Additional options for knife ssh.  For example: ['-groups' => 'foo']
93
     * @param array $chefOptions Additional options for chef client. For example: ['--override-runlist' => 'role[foo]']
94
     * @return void
95
     */
96
    public function updateServers($query, $progressFile = null, array $options = [], array $chefOptions = [])
97
    {
98
        $instanceIdUrl = 'http://169.254.169.254/latest/meta-data/instance-id';
99
        $chefOptions = array_merge($chefOptions, ['--json-attributes' => '/etc/chef/first-boot.json']);
100
        $chefCommand = \Hiatus\addArguments("sudo chef-client -N `curl {$instanceIdUrl}`", $chefOptions);
101
        $options = array_merge(
102
            $options,
103
            $this->chefClientParameters(),
104
            $this->ec2SshParameters(),
105
            [$query, $chefCommand]
106
        );
107
        $command = \Hiatus\addArguments("{$this->baseKnifeCommand} ssh", $options);
108
        if ($progressFile !== null) {
109
            \Hiatus\execX("{$command} >" . escapeshellarg($progressFile) . ' 2>&1 &');
110
        } else {
111
            passthru($command);
112
        }
113
    }
114
115
    /**
116
     * Get the knife-ec2 parameters for basic AWS API credentials.
117
     *
118
     * @return array The parameters to access AWS via knife-ec2.
119
     */
120
    private function awsCredentialParameters()
121
    {
122
        return [
123
            '--aws-access-key-id' => $this->credentials['awsAccessKeyId'],
124
            '--aws-secret-access-key' => $this->credentials['awsSecretAccessKey'],
125
        ];
126
    }
127
128
    /**
129
     * Get the chef client parameters.
130
     *
131
     * @return array The parameters to access the chef API via knife.
132
     */
133
    private function chefClientParameters()
134
    {
135
        return [
136
            '--server-url' => $this->chefServerUrl,
137
            '--user' => $this->credentials['chefClientName'],
138
            '--key' => $this->credentials['chefClientKey'],
139
        ];
140
    }
141
142
    /**
143
     * Get the EC2 SSH parameters.
144
     *
145
     * @return array The parameters to access the EC2 ssh servers
146
     */
147
    private function ec2SshParameters()
148
    {
149
        return [
150
            '--ssh-user' => $this->credentials['ec2SshUser'],
151
            '--identity-file' => $this->credentials['ec2SshKey'],
152
        ];
153
    }
154
}
155