ChefEc2   A
last analyzed

Complexity

Total Complexity 8

Size/Duplication

Total Lines 154
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

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

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A createServer() 0 33 2
A updateServers() 0 22 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(string $baseKnifeCommand, string $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
        string $region,
55
        string $ami,
56
        string $flavor,
57
        array $runList,
58
        string $progressFile,
59
        array $options = [],
60
        array $tags = [],
61
        string $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(
97
        string $query,
98
        string $progressFile = null,
99
        array $options = [],
100
        array $chefOptions = []
101
    ) {
102
        $instanceIdUrl = 'http://169.254.169.254/latest/meta-data/instance-id';
103
        $chefOptions = array_merge($chefOptions, ['--json-attributes' => '/etc/chef/first-boot.json']);
104
        $chefCommand = \Hiatus\addArguments("sudo chef-client -N `curl {$instanceIdUrl}`", $chefOptions);
105
        $options = array_merge(
106
            $options,
107
            $this->chefClientParameters(),
108
            $this->ec2SshParameters(),
109
            [$query, $chefCommand]
110
        );
111
        $command = \Hiatus\addArguments("{$this->baseKnifeCommand} ssh", $options);
112
        if ($progressFile !== null) {
113
            \Hiatus\execX("{$command} >" . escapeshellarg($progressFile) . ' 2>&1 &');
114
        } else {
115
            passthru($command);
116
        }
117
    }
118
119
    /**
120
     * Get the knife-ec2 parameters for basic AWS API credentials.
121
     *
122
     * @return array The parameters to access AWS via knife-ec2.
123
     */
124
    private function awsCredentialParameters() : array
125
    {
126
        return [
127
            '--aws-access-key-id' => $this->credentials['awsAccessKeyId'],
128
            '--aws-secret-access-key' => $this->credentials['awsSecretAccessKey'],
129
        ];
130
    }
131
132
    /**
133
     * Get the chef client parameters.
134
     *
135
     * @return array The parameters to access the chef API via knife.
136
     */
137
    private function chefClientParameters() : array
138
    {
139
        return [
140
            '--server-url' => $this->chefServerUrl,
141
            '--user' => $this->credentials['chefClientName'],
142
            '--key' => $this->credentials['chefClientKey'],
143
        ];
144
    }
145
146
    /**
147
     * Get the EC2 SSH parameters.
148
     *
149
     * @return array The parameters to access the EC2 ssh servers
150
     */
151
    private function ec2SshParameters() : array
152
    {
153
        return [
154
            '--ssh-user' => $this->credentials['ec2SshUser'],
155
            '--identity-file' => $this->credentials['ec2SshKey'],
156
        ];
157
    }
158
}
159