• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

karellen / kubernator / 12968276086

25 Jan 2025 08:41PM UTC coverage: 74.504%. First build
12968276086

Pull #69

github

web-flow
Merge fcddfa8d6 into 2921fcad4
Pull Request #69: Support istio 1.24+

578 of 933 branches covered (61.95%)

Branch coverage included in aggregate %.

81 of 85 new or added lines in 2 files covered. (95.29%)

2315 of 2950 relevant lines covered (78.47%)

3.14 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.98
/src/main/python/kubernator/plugins/minikube.py
1
# -*- coding: utf-8 -*-
2
#
3
#   Copyright 2020 Express Systems USA, Inc
4
#   Copyright 2023 Karellen, Inc.
5
#
6
#   Licensed under the Apache License, Version 2.0 (the "License");
7
#   you may not use this file except in compliance with the License.
8
#   You may obtain a copy of the License at
9
#
10
#       http://www.apache.org/licenses/LICENSE-2.0
11
#
12
#   Unless required by applicable law or agreed to in writing, software
13
#   distributed under the License is distributed on an "AS IS" BASIS,
14
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
#   See the License for the specific language governing permissions and
16
#   limitations under the License.
17
#
18

19
import logging
4✔
20
import os
4✔
21
import tempfile
4✔
22
from pathlib import Path
4✔
23

24
from kubernator.api import (KubernatorPlugin,
4✔
25
                            StripNL,
26
                            get_golang_os,
27
                            get_golang_machine,
28
                            prepend_os_path,
29
                            get_cache_dir,
30
                            CalledProcessError
31
                            )
32

33
logger = logging.getLogger("kubernator.minikube")
4✔
34
proc_logger = logger.getChild("proc")
4✔
35
stdout_logger = StripNL(proc_logger.info)
4✔
36
stderr_logger = StripNL(proc_logger.warning)
4✔
37

38

39
class MinikubePlugin(KubernatorPlugin):
4✔
40
    logger = logger
4✔
41

42
    _name = "minikube"
4✔
43

44
    def __init__(self):
4✔
45
        self.context = None
4✔
46
        self.minikube_dir = None
4✔
47
        self.minikube_home_dir = None
4✔
48
        self.kubeconfig_dir = None
4✔
49

50
        super().__init__()
4✔
51

52
    def set_context(self, context):
4✔
53
        self.context = context
4✔
54

55
    def get_latest_minikube_version(self):
4✔
56
        context = self.context
4✔
57
        versions = context.app.run_capturing_out(["git", "ls-remote", "-t", "--refs",
4✔
58
                                                  "https://github.com/kubernetes/minikube", "v*"],
59
                                                 stderr_logger)
60

61
        # 06e3b0cf7999f74fc52af362b42fb21076ade64a        refs/tags/v1.9.1
62
        # "refs/tags/v1.9.1"
63
        # "1.9.1"
64
        # ("1","9","1")
65
        # (1, 9, 1)
66
        # sort and get latest, which is the last/highest
67
        # "v1.9.1"
68
        return (".".join(map(str, sorted(list(map(lambda v: tuple(map(int, v)),
4✔
69
                                                  filter(lambda v: len(v) == 3,
70
                                                         map(lambda line: line.split()[1][11:].split("."),
71
                                                             versions.splitlines(False))))))[-1])))
72

73
    def cmd(self, *extra_args):
4✔
74
        stanza, env = self._stanza(list(extra_args))
4✔
75
        return self.context.app.run(stanza, stdout_logger, stderr_logger, env=env).wait()
4✔
76

77
    def cmd_out(self, *extra_args):
4✔
78
        stanza, env = self._stanza(list(extra_args))
4✔
79
        return self.context.app.run_capturing_out(stanza, stderr_logger, env=env)
4✔
80

81
    def _stanza(self, extra_args):
4✔
82
        context = self.context
4✔
83
        minikube = context.minikube
4✔
84
        stanza = [context.minikube.minikube_file, "-p", minikube.profile] + extra_args
4✔
85
        env = dict(os.environ)
4✔
86
        env["MINIKUBE_HOME"] = str(self.minikube_home_dir)
4✔
87
        env["KUBECONFIG"] = str(minikube.kubeconfig)
4✔
88
        return stanza, env
4✔
89

90
    def register(self, minikube_version=None, profile="default", k8s_version=None,
4✔
91
                 keep_running=False, start_fresh=False,
92
                 nodes=1, driver=None, cpus="no-limit", extra_args=None):
93
        context = self.context
4✔
94

95
        context.app.register_plugin("kubeconfig")
4✔
96

97
        if not k8s_version:
4!
98
            msg = "No Kubernetes version is specified for Minikube"
×
99
            logger.critical(msg)
×
100
            raise RuntimeError(msg)
×
101

102
        if not minikube_version:
4!
103
            minikube_version = self.get_latest_minikube_version()
4✔
104
            logger.info("No minikube version is specified, latest is %s", minikube_version)
4✔
105

106
        minikube_dl_file, _ = context.app.download_remote_file(logger,
4✔
107
                                                               f"https://github.com/kubernetes/minikube/releases"
108
                                                               f"/download/v{minikube_version}/"
109
                                                               f"minikube-{get_golang_os()}-{get_golang_machine()}",
110
                                                               "bin")
111

112
        os.chmod(minikube_dl_file, 0o500)
4✔
113
        self.minikube_dir = tempfile.TemporaryDirectory()
4✔
114
        context.app.register_cleanup(self.minikube_dir)
4✔
115

116
        minikube_file = Path(self.minikube_dir.name) / "minikube"
4✔
117
        minikube_file.symlink_to(minikube_dl_file)
4✔
118
        prepend_os_path(self.minikube_dir.name)
4✔
119
        version_out: str = self.context.app.run_capturing_out([str(minikube_file), "version", "--short"],
4✔
120
                                                              stderr_logger).strip()
121
        version = version_out[1:]
4✔
122
        logger.info("Found minikube %s in %s", version, minikube_file)
4✔
123

124
        profile_dir = get_cache_dir("minikube")
4✔
125
        self.minikube_home_dir = profile_dir
4✔
126
        self.minikube_home_dir.mkdir(parents=True, exist_ok=True)
4✔
127
        self.kubeconfig_dir = profile_dir / ".kube" / profile
4✔
128
        self.kubeconfig_dir.mkdir(parents=True, exist_ok=True)
4✔
129

130
        if not driver:
4!
131
            driver = "docker"
4✔
132
            if get_golang_os() == "darwin":
4!
133
                logger.debug("Auto-detecting Minikube driver on MacOS...")
×
134
                cmd_debug_logger = StripNL(proc_logger.debug)
×
135
                try:
×
136
                    context.app.run(["docker", "info"], cmd_debug_logger, cmd_debug_logger).wait()
×
137
                    logger.info("Docker is functional, selecting 'docker' as the driver for Minikube")
×
138
                except (FileNotFoundError, CalledProcessError) as e:
×
139
                    logger.trace("Docker is NOT functional", exc_info=e)
×
140
                    driver = "hyperkit"
×
141
                    try:
×
142
                        context.app.run(["hyperkit", "-v"], cmd_debug_logger, cmd_debug_logger).wait()
×
143
                        logger.info("Hyperkit is functional, selecting 'hyperkit' as the driver for Minikube")
×
144
                    except (FileNotFoundError, CalledProcessError) as e:
×
145
                        logger.trace("Hyperkit is NOT functional", exc_info=e)
×
146
                        driver = "podman"
×
147
                        try:
×
148
                            context.app.run(["podman", "info"], cmd_debug_logger, cmd_debug_logger).wait()
×
149
                            logger.info("Podman is functional, selecting 'podman' as the driver for Minikube")
×
150
                        except (FileNotFoundError, CalledProcessError) as e:
×
151
                            logger.trace("Podman is NOT functional", exc_info=e)
×
152
                            raise RuntimeError("No Minikube driver is functional on MacOS. "
×
153
                                               "Tried 'docker', 'hyperkit' and 'podman'!")
154

155
        context.globals.minikube = dict(version=version,
4✔
156
                                        minikube_file=str(minikube_file),
157
                                        profile=profile,
158
                                        k8s_version=k8s_version,
159
                                        start_fresh=start_fresh,
160
                                        keep_running=keep_running,
161
                                        nodes=nodes,
162
                                        driver=driver,
163
                                        cpus=cpus,
164
                                        extra_args=extra_args or [],
165
                                        kubeconfig=str(self.kubeconfig_dir / "config"),
166
                                        cmd=self.cmd,
167
                                        cmd_out=self.cmd_out
168
                                        )
169
        context.kubeconfig.kubeconfig = context.minikube.kubeconfig
4✔
170

171
        logger.info("Minikube Home is %s", self.minikube_home_dir)
4✔
172
        logger.info("Minikube Kubeconfig is %s", context.minikube.kubeconfig)
4✔
173

174
    def minikube_is_running(self):
4✔
175
        try:
4✔
176
            out = self.cmd_out("status", "-o", "json")
4✔
177
            logger.info("Minikube profile %r is running: %s", self.context.minikube.profile,
4✔
178
                        out.strip())
179
            return True
4✔
180
        except CalledProcessError as e:
4✔
181
            logger.info("Minikube profile %r is not running: %s", self.context.minikube.profile,
4✔
182
                        e.output.strip())
183
            return False
4✔
184

185
    def minikube_start(self):
4✔
186
        minikube = self.context.minikube
4✔
187
        if not self.minikube_is_running():
4✔
188
            logger.info("Starting minikube profile %r...", minikube.profile)
4✔
189
            args = ["start",
4✔
190
                    "--driver", str(minikube.driver),
191
                    "--kubernetes-version", str(minikube.k8s_version),
192
                    "--wait", "apiserver",
193
                    "--nodes", str(minikube.nodes)]
194

195
            if minikube.driver == "docker":
4!
196
                args.extend(["--cpus", str(minikube.cpus)])
4✔
197

198
            self.cmd(*args)
4✔
199
        else:
200
            logger.warning("Minikube profile %r is already running!", minikube.profile)
4✔
201

202
        logger.info("Updating minikube profile %r context", minikube.profile)
4✔
203
        self.cmd("update-context")
4✔
204

205
    def minikube_stop(self):
4✔
206
        minikube = self.context.minikube
4✔
207
        if self.minikube_is_running():
4✔
208
            logger.info("Shutting down minikube profile %r...", minikube.profile)
4✔
209
            try:
4✔
210
                self.cmd("stop", "-o", "json")
4✔
NEW
211
            except CalledProcessError as e:
×
212
                # Workaround for minikube 1.35.0 https://github.com/kubernetes/minikube/issues/20302
NEW
213
                if e.returncode != 82:
×
NEW
214
                    raise
×
215

216
    def minikube_delete(self):
4✔
217
        minikube = self.context.minikube
4✔
218
        self.minikube_stop()
4✔
219
        logger.warning("Deleting minikube profile %r!", minikube.profile)
4✔
220
        self.cmd("delete")
4✔
221

222
    def handle_start(self):
4✔
223
        minikube = self.context.minikube
4✔
224
        if minikube.start_fresh:
4✔
225
            self.minikube_delete()
4✔
226

227
        self.minikube_start()
4✔
228

229
    def handle_shutdown(self):
4✔
230
        minikube = self.context.minikube
4✔
231
        if not minikube.keep_running:
4✔
232
            self.minikube_stop()
4✔
233
        else:
234
            logger.warning("Will keep minikube profile %s running!", minikube.profile)
4✔
235

236
    def __repr__(self):
4✔
237
        return "Minikube Plugin"
4✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc