-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
apps: deployment config stuck in the new state should respect timeoutSeconds #17000
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -127,6 +127,21 @@ func (c *DeploymentController) handle(deployment *v1.ReplicationController, will | |
} | ||
break | ||
} | ||
// In case the deployment is stuck in "new" state because we fail to create | ||
// deployer pod (quota, etc..) we should respect the timeoutSeconds in the | ||
// config strategy and transition the rollout to failed instead of waiting for | ||
// the deployment pod forever. | ||
config, err := deployutil.DecodeDeploymentConfig(deployment, c.codec) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. long term, we want to get rid of this... we should copy the timeoutSecond into annotation so we don't have to decode here... this also apply to other fields we check i guess. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
if err != nil { | ||
return err | ||
} | ||
if deployutil.RolloutExceededTimeoutSeconds(config, deployment) { | ||
nextStatus = deployapi.DeploymentStatusFailed | ||
updatedAnnotations[deployapi.DeploymentStatusReasonAnnotation] = deployapi.DeploymentFailedUnableToCreateDeployerPod | ||
c.emitDeploymentEvent(deployment, v1.EventTypeWarning, "RolloutTimeout", fmt.Sprintf("Rollout for %q failed to create deployer pod (timeoutSeconds: %ds)", deployutil.LabelForDeploymentV1(deployment), deployutil.GetTimeoutSecondsForStrategy(config))) | ||
glog.V(4).Infof("Failing deployment %s/%s as we reached timeout while waiting for the deployer pod to be created", deployment.Namespace, deployment.Name) | ||
break | ||
} | ||
|
||
switch { | ||
case kerrors.IsNotFound(deployerErr): | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -586,3 +586,111 @@ func TestRemoveCondition(t *testing.T) { | |
} | ||
} | ||
} | ||
|
||
func TestRolloutExceededTimeoutSeconds(t *testing.T) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd like to see a test table containing setting different strategies and not specified timeouts mixed with creationTimestamps values There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done. |
||
now := time.Now() | ||
tests := []struct { | ||
name string | ||
config *deployapi.DeploymentConfig | ||
deploymentCreationTime time.Time | ||
expectTimeout bool | ||
}{ | ||
// Recreate strategy with deployment running for 20s (exceeding 10s timeout) | ||
{ | ||
name: "recreate timeout", | ||
config: func(timeoutSeconds int64) *deployapi.DeploymentConfig { | ||
config := deploytest.OkDeploymentConfig(1) | ||
config.Spec.Strategy.RecreateParams.TimeoutSeconds = &timeoutSeconds | ||
return config | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fill in timeout and creationTime |
||
}(int64(10)), | ||
deploymentCreationTime: now.Add(-20 * time.Second), | ||
expectTimeout: true, | ||
}, | ||
// Recreate strategy with no timeout | ||
{ | ||
name: "recreate no timeout", | ||
config: func(timeoutSeconds int64) *deployapi.DeploymentConfig { | ||
config := deploytest.OkDeploymentConfig(1) | ||
config.Spec.Strategy.RecreateParams.TimeoutSeconds = &timeoutSeconds | ||
return config | ||
}(int64(0)), | ||
deploymentCreationTime: now.Add(-700 * time.Second), | ||
expectTimeout: false, | ||
}, | ||
|
||
// Rolling strategy with deployment running for 20s (exceeding 10s timeout) | ||
{ | ||
name: "rolling timeout", | ||
config: func(timeoutSeconds int64) *deployapi.DeploymentConfig { | ||
config := deploytest.OkDeploymentConfig(1) | ||
config.Spec.Strategy = deploytest.OkRollingStrategy() | ||
config.Spec.Strategy.RollingParams.TimeoutSeconds = &timeoutSeconds | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would assign |
||
return config | ||
}(int64(10)), | ||
deploymentCreationTime: now.Add(-20 * time.Second), | ||
expectTimeout: true, | ||
}, | ||
// Rolling strategy with deployment with no timeout specified. | ||
{ | ||
name: "rolling using default timeout", | ||
config: func(timeoutSeconds int64) *deployapi.DeploymentConfig { | ||
config := deploytest.OkDeploymentConfig(1) | ||
config.Spec.Strategy = deploytest.OkRollingStrategy() | ||
config.Spec.Strategy.RollingParams.TimeoutSeconds = nil | ||
return config | ||
}(0), | ||
deploymentCreationTime: now.Add(-20 * time.Second), | ||
expectTimeout: false, | ||
}, | ||
// Recreate strategy with deployment with no timeout specified. | ||
{ | ||
name: "recreate using default timeout", | ||
config: func(timeoutSeconds int64) *deployapi.DeploymentConfig { | ||
config := deploytest.OkDeploymentConfig(1) | ||
config.Spec.Strategy.RecreateParams.TimeoutSeconds = nil | ||
return config | ||
}(0), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. don't take it as you have to fix it because I told you, you don't have to but check how the argument is pointless here :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🤷♂️ |
||
deploymentCreationTime: now.Add(-20 * time.Second), | ||
expectTimeout: false, | ||
}, | ||
// Custom strategy with deployment with no timeout specified. | ||
{ | ||
name: "custom using default timeout", | ||
config: func(timeoutSeconds int64) *deployapi.DeploymentConfig { | ||
config := deploytest.OkDeploymentConfig(1) | ||
config.Spec.Strategy = deploytest.OkCustomStrategy() | ||
return config | ||
}(0), | ||
deploymentCreationTime: now.Add(-20 * time.Second), | ||
expectTimeout: false, | ||
}, | ||
// Custom strategy use default timeout exceeding it. | ||
{ | ||
name: "custom using default timeout timing out", | ||
config: func(timeoutSeconds int64) *deployapi.DeploymentConfig { | ||
config := deploytest.OkDeploymentConfig(1) | ||
config.Spec.Strategy = deploytest.OkCustomStrategy() | ||
return config | ||
}(0), | ||
deploymentCreationTime: now.Add(-700 * time.Second), | ||
expectTimeout: true, | ||
}, | ||
} | ||
|
||
for _, tc := range tests { | ||
config := tc.config | ||
deployment, err := MakeDeploymentV1(config, kapi.Codecs.LegacyCodec(deployv1.SchemeGroupVersion)) | ||
if err != nil { | ||
t.Fatalf("unexpected error: %v", err) | ||
} | ||
deployment.ObjectMeta.CreationTimestamp = metav1.Time{Time: tc.deploymentCreationTime} | ||
gotTimeout := RolloutExceededTimeoutSeconds(config, deployment) | ||
if tc.expectTimeout && !gotTimeout { | ||
t.Errorf("[%s]: expected timeout, but got no timeout", tc.name) | ||
} | ||
if !tc.expectTimeout && gotTimeout { | ||
t.Errorf("[%s]: expected no timeout, but got timeout", tc.name) | ||
} | ||
|
||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this looks nice in
oc status
: