Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: quit minikube service when there is no available pods #15079

Merged
merged 5 commits into from
Jun 12, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cmd/minikube/cmd/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@ You may select another namespace by using 'minikube service {{.service}} -n <nam
out.String(fmt.Sprintf("%s\n", serviceURLs))
}
}
// check whether all pods of this service is crashed
ComradeProgrammer marked this conversation as resolved.
Show resolved Hide resolved
if err := service.CheckServicePods(cname, svc.Name, namespace); err != nil {
exit.Error(reason.SvcUnreachable, "service not available", err)
}
}

if driver.NeedsPortForward(co.Config.Driver) && services != nil {
Expand Down
2 changes: 2 additions & 0 deletions pkg/minikube/reason/reason.go
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,8 @@ var (
SvcCheckTimeout = Kind{ID: "SVC_CHECK_TIMEOUT", ExitCode: ExSvcTimeout}
// minikube was unable to access a service
SvcTimeout = Kind{ID: "SVC_TIMEOUT", ExitCode: ExSvcTimeout}
// minikube finds that the service has not available pods
ComradeProgrammer marked this conversation as resolved.
Show resolved Hide resolved
SvcUnreachable = Kind{ID: "SVC_UNREACHABLE", ExitCode: ExSvcNotFound}
// minikube failed to list services for the specified namespace
SvcList = Kind{ID: "SVC_LIST", ExitCode: ExSvcError}
// minikube failed to start a tunnel
Expand Down
33 changes: 33 additions & 0 deletions pkg/minikube/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -373,3 +373,36 @@ func DeleteSecret(cname string, namespace, name string) error {

return nil
}

// check whether there are running pods for a service
func CheckServicePods(cname, svcName, namespace string) error {
clientset, err := K8s.GetCoreClient(cname)
if err != nil {
return errors.Wrap(err, "failed to get k8s client")
}

svc, err := clientset.Services(namespace).Get(context.Background(), svcName, meta.GetOptions{})
if err != nil {
return errors.Wrap(err, "Get service")
}
// There are four types of service in k8s: NodePort, ClusterIp, LoadBalancer and ExternalName
// However, NodePort means that this service will not be exposed outside the cluster
// while ExternalName means that this service is not provided by this k8s cluster
// So we only check when service type is NodePort or LoadBalancer
if svc.Spec.Type != core.ServiceTypeNodePort && svc.Spec.Type != core.ServiceTypeLoadBalancer {
ComradeProgrammer marked this conversation as resolved.
Show resolved Hide resolved
return nil
}
pods, err := clientset.Pods(namespace).List(context.Background(), meta.ListOptions{
LabelSelector: labels.Set(svc.Spec.Selector).AsSelector().String(),
})
if err != nil {
ComradeProgrammer marked this conversation as resolved.
Show resolved Hide resolved
return errors.Wrap(err, "List Pods")
}

for _, pod := range pods.Items {
if pod.Status.Phase == core.PodRunning {
return nil
}
}
return fmt.Errorf("no running pod for service %s found", svcName)
}
3 changes: 3 additions & 0 deletions site/content/en/docs/contrib/tests.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,9 @@ verifies that minikube pause works
## TestInsufficientStorage
makes sure minikube status displays the correct info if there is insufficient disk space on the machine

## TestInvalidService
makes sure minikube will not start a tunnel for a unavailable service who has no running pods

## TestRunningBinaryUpgrade
upgrades a running legacy cluster to minikube at HEAD

Expand Down
25 changes: 25 additions & 0 deletions test/integration/functional_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ func TestFunctional(t *testing.T) {
{"ComponentHealth", validateComponentHealth},
{"LogsCmd", validateLogsCmd},
{"LogsFileCmd", validateLogsFileCmd},
{"InvalidService", validateInvalidService},
}
for _, tc := range tests {
tc := tc
Expand Down Expand Up @@ -2308,3 +2309,27 @@ func validateLicenseCmd(ctx context.Context, t *testing.T, _ string) {
t.Errorf("expected license file to contain %q, but was not found", expectedString)
}
}

// validateInvalidService makes sure minikube will not start a tunnel for an unavailable service that has no running pods
func validateInvalidService(ctx context.Context, t *testing.T, profile string) {

// try to start an invalid service. This service is linked to a pod whose image name is invalid, so this pod will never become running
rrApply, err := Run(t, exec.CommandContext(ctx, "kubectl", "--context", profile, "apply", "-f", filepath.Join(*testdataDir, "invalidsvc.yaml")))
defer func() {
// Cleanup test configurations in advance of future tests
rr, err := Run(t, exec.CommandContext(ctx, "kubectl", "--context", profile, "delete", "-f", filepath.Join(*testdataDir, "invalidsvc.yaml")))
if err != nil {
t.Fatalf("clean up %s failed: %v", rr.Command(), err)
}
}()
if err != nil {
t.Fatalf("%s failed: %v", rrApply.Command(), err)
}
ComradeProgrammer marked this conversation as resolved.
Show resolved Hide resolved
time.Sleep(3 * time.Second)

// try to expose a service, this action is supposed to fail
rrService, err := Run(t, exec.CommandContext(context.TODO(), Target(), "service", "invalid-svc", "-p", profile))
ComradeProgrammer marked this conversation as resolved.
Show resolved Hide resolved
if err == nil || rrService.ExitCode == 0 {
t.Fatalf("%s should have failed: ", rrService.Command())
}
}
31 changes: 31 additions & 0 deletions test/integration/testdata/invalidsvc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
apiVersion: v1
kind: Pod
metadata:
labels:
run: invalid-svc
name: invalid-svc
namespace: default
spec:
containers:
- name: nginx
image: nonexistingimage:latest
ports:
- containerPort: 80
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
labels:
run: invalid-svc
name: invalid-svc
namespace: default
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
run: invalid-svc
sessionAffinity: None
type: NodePort
1 change: 1 addition & 0 deletions translations/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -953,6 +953,7 @@
"dry-run mode. Validates configuration, but does not mutate system state": "dry-run Modus. Validiert die Konfiguration, aber ändert den System Zustand nicht",
"dry-run validation complete!": "dry-run Validierung komplett!",
"enable failed": "aktivieren fehlgeschlagen",
"error checking service": "",
"error creating clientset": "Fehler beim Anlegen des Clientsets",
"error creating urls": "",
"error getting defaults: {{.error}}": "",
Expand Down
1 change: 1 addition & 0 deletions translations/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,7 @@
"dry-run mode. Validates configuration, but does not mutate system state": "",
"dry-run validation complete!": "",
"enable failed": "",
"error checking service": "",
"error creating clientset": "",
"error creating urls": "",
"error getting defaults: {{.error}}": "",
Expand Down
1 change: 1 addition & 0 deletions translations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -934,6 +934,7 @@
"dry-run mode. Validates configuration, but does not mutate system state": "mode simulation. Valide la configuration, mais ne modifie pas l'état du système",
"dry-run validation complete!": "validation de la simulation terminée !",
"enable failed": "échec de l'activation",
"error checking service": "",
"error creating clientset": "erreur lors de la création de l'ensemble de clients",
"error creating urls": "erreur lors de la création d'urls",
"error getting defaults: {{.error}}": "erreur lors de l'obtention des valeurs par défaut : {{.error}}",
Expand Down
1 change: 1 addition & 0 deletions translations/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,7 @@
"dry-run mode. Validates configuration, but does not mutate system state": "dry-run モード。設定は検証しますが、システムの状態は変更しません",
"dry-run validation complete!": "dry-run の検証が終了しました!",
"enable failed": "有効化に失敗しました",
"error checking service": "",
"error creating clientset": "clientset 作成中にエラー",
"error creating urls": "URL 作成でエラー",
"error getting defaults: {{.error}}": "デフォルト取得中にエラー: {{.error}}",
Expand Down
1 change: 1 addition & 0 deletions translations/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -953,6 +953,7 @@
"dry-run mode. Validates configuration, but does not mutate system state": "",
"dry-run validation complete!": "dry-run 검증 완료!",
"enable failed": "활성화가 실패하였습니다",
"error checking service": "",
"error creating clientset": "clientset 생성 오류",
"error creating machine client": "머신 client 생성 오류",
"error creating urls": "",
Expand Down
1 change: 1 addition & 0 deletions translations/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -963,6 +963,7 @@
"dry-run mode. Validates configuration, but does not mutate system state": "",
"dry-run validation complete!": "",
"enable failed": "",
"error checking service": "",
"error creating clientset": "",
"error creating urls": "",
"error getting defaults: {{.error}}": "",
Expand Down
1 change: 1 addition & 0 deletions translations/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -883,6 +883,7 @@
"dry-run mode. Validates configuration, but does not mutate system state": "",
"dry-run validation complete!": "",
"enable failed": "",
"error checking service": "",
"error creating clientset": "",
"error creating urls": "",
"error getting defaults: {{.error}}": "",
Expand Down
1 change: 1 addition & 0 deletions translations/strings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -883,6 +883,7 @@
"dry-run mode. Validates configuration, but does not mutate system state": "",
"dry-run validation complete!": "",
"enable failed": "",
"error checking service": "",
"error creating clientset": "",
"error creating urls": "",
"error getting defaults: {{.error}}": "",
Expand Down
1 change: 1 addition & 0 deletions translations/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -1071,6 +1071,7 @@
"dry-run mode. Validates configuration, but does not mutate system state": "",
"dry-run validation complete!": "",
"enable failed": "开启失败",
"error checking service": "",
"error creating clientset": "",
"error creating urls": "",
"error getting defaults: {{.error}}": "",
Expand Down