ChefEc2::createServer()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 8
dl 0
loc 33
rs 9.392
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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