Commit b0c0b307 authored by vaikas-google's avatar vaikas-google

Merge pull request #147 from bmelville/144

Deployment now has top-level error for deployment-level failures
parents b2187ade 55ec0747
......@@ -37,13 +37,24 @@ type Deployment struct {
DeployedAt time.Time `json:"deployedAt,omitempty"`
ModifiedAt time.Time `json:"modifiedAt,omitempty"`
DeletedAt time.Time `json:"deletedAt,omitempty"`
Status DeploymentStatus `json:"status,omitempty"`
State *DeploymentState `json:"state,omitempty"`
LatestManifest string `json:"latestManifest,omitEmpty"`
}
// NewDeployment creates a new deployment.
func NewDeployment(name string) *Deployment {
return &Deployment{Name: name, CreatedAt: time.Now(), Status: CreatedStatus}
return &Deployment{
Name: name,
CreatedAt: time.Now(),
State: &DeploymentState{Status: CreatedStatus},
}
}
// DeploymentState describes the state of a resource. It is set to the terminal
// state depending on the outcome of an operation on the deployment.
type DeploymentState struct {
Status DeploymentStatus `json:"status,omitempty"`
Errors []string `json:"errors,omitempty"`
}
// DeploymentStatus is an enumeration type for the status of a deployment.
......
......@@ -7,9 +7,6 @@ resources:
external_service: true
replicas: 3
image: gcr.io/google_containers/example-guestbook-php-redis:v3
env:
- name: redis-master
value: $(ref.redis-master.name)
- name: redis
type: github.com/kubernetes/application-dm-templates/storage/redis:v1
properties: null
......@@ -102,13 +102,13 @@ func (m *manager) CreateDeployment(t *common.Template) (*common.Deployment, erro
manifest, err := m.createManifest(t)
if err != nil {
log.Printf("Manifest creation failed: %v", err)
m.repository.SetDeploymentStatus(t.Name, common.FailedStatus)
m.repository.SetDeploymentState(t.Name, failState(err))
return nil, err
}
if err := m.repository.AddManifest(t.Name, manifest); err != nil {
log.Printf("AddManifest failed %v", err)
m.repository.SetDeploymentStatus(t.Name, common.FailedStatus)
m.repository.SetDeploymentState(t.Name, failState(err))
return nil, err
}
......@@ -116,7 +116,8 @@ func (m *manager) CreateDeployment(t *common.Template) (*common.Deployment, erro
if err != nil {
// Deployment failed, mark as failed
log.Printf("CreateConfiguration failed: %v", err)
m.repository.SetDeploymentStatus(t.Name, common.FailedStatus)
m.repository.SetDeploymentState(t.Name, failState(err))
// If we failed before being able to create some of the resources, then
// return the failure as such. Otherwise, we're going to add the manifest
// and hence resource specific errors down below.
......@@ -124,14 +125,14 @@ func (m *manager) CreateDeployment(t *common.Template) (*common.Deployment, erro
return nil, err
}
} else {
m.repository.SetDeploymentStatus(t.Name, common.DeployedStatus)
m.repository.SetDeploymentState(t.Name, &common.DeploymentState{Status: common.DeployedStatus})
}
// Update the manifest with the actual state of the reified resources
manifest.ExpandedConfig = actualConfig
if err := m.repository.SetManifest(t.Name, manifest); err != nil {
log.Printf("SetManifest failed %v", err)
m.repository.SetDeploymentStatus(t.Name, common.FailedStatus)
m.repository.SetDeploymentState(t.Name, failState(err))
return nil, err
}
......@@ -198,6 +199,7 @@ func (m *manager) DeleteDeployment(name string, forget bool) (*common.Deployment
// If there's a latest manifest, delete the underlying resources.
latest, err := m.repository.GetLatestManifest(name)
if err != nil {
m.repository.SetDeploymentState(name, failState(err))
return nil, err
}
......@@ -210,6 +212,7 @@ func (m *manager) DeleteDeployment(name string, forget bool) (*common.Deployment
if _, err := m.deployer.DeleteConfiguration(latest.ExpandedConfig); err != nil {
log.Printf("Failed to delete resources from the latest manifest: %v", err)
m.repository.SetDeploymentState(name, failState(err))
return nil, err
}
......@@ -217,6 +220,7 @@ func (m *manager) DeleteDeployment(name string, forget bool) (*common.Deployment
err = m.repository.AddManifest(name, &common.Manifest{Deployment: name, Name: generateManifestName()})
if err != nil {
log.Printf("Failed to add empty manifest")
m.repository.SetDeploymentState(name, failState(err))
return nil, err
}
}
......@@ -243,20 +247,20 @@ func (m *manager) PutDeployment(name string, t *common.Template) (*common.Deploy
manifest, err := m.createManifest(t)
if err != nil {
log.Printf("Manifest creation failed: %v", err)
m.repository.SetDeploymentStatus(name, common.FailedStatus)
m.repository.SetDeploymentState(name, failState(err))
return nil, err
}
actualConfig, err := m.deployer.PutConfiguration(manifest.ExpandedConfig)
if err != nil {
m.repository.SetDeploymentStatus(name, common.FailedStatus)
m.repository.SetDeploymentState(name, failState(err))
return nil, err
}
manifest.ExpandedConfig = actualConfig
err = m.repository.AddManifest(t.Name, manifest)
if err != nil {
m.repository.SetDeploymentStatus(name, common.FailedStatus)
m.repository.SetDeploymentState(name, failState(err))
return nil, err
}
......@@ -290,3 +294,10 @@ func (m *manager) ListInstances(typeName string) []*common.TypeInstance {
func generateManifestName() string {
return fmt.Sprintf("manifest-%d", time.Now().UTC().UnixNano())
}
func failState(e error) *common.DeploymentState {
return &common.DeploymentState{
Status: common.FailedStatus,
Errors: []string{e.Error()},
}
}
......@@ -134,7 +134,7 @@ type repositoryStub struct {
TypeInstancesCleared bool
GetTypeInstancesCalled bool
ListTypesCalled bool
DeploymentStatuses []common.DeploymentStatus
DeploymentStates []*common.DeploymentState
}
func (repository *repositoryStub) reset() {
......@@ -148,7 +148,7 @@ func (repository *repositoryStub) reset() {
repository.TypeInstancesCleared = false
repository.GetTypeInstancesCalled = false
repository.ListTypesCalled = false
repository.DeploymentStatuses = make([]common.DeploymentStatus, 0)
repository.DeploymentStates = []*common.DeploymentState{}
}
func newRepositoryStub() *repositoryStub {
......@@ -176,8 +176,8 @@ func (repository *repositoryStub) GetValidDeployment(d string) (*common.Deployme
return &deployment, nil
}
func (repository *repositoryStub) SetDeploymentStatus(name string, status common.DeploymentStatus) error {
repository.DeploymentStatuses = append(repository.DeploymentStatuses, status)
func (repository *repositoryStub) SetDeploymentState(name string, state *common.DeploymentState) error {
repository.DeploymentStates = append(repository.DeploymentStates, state)
return nil
}
......@@ -340,7 +340,7 @@ func TestCreateDeployment(t *testing.T) {
testDeployer.Created[0], configuration)
}
if testRepository.DeploymentStatuses[0] != common.DeployedStatus {
if testRepository.DeploymentStates[0].Status != common.DeployedStatus {
t.Fatal("CreateDeployment success did not mark deployment as deployed")
}
......@@ -369,7 +369,7 @@ func TestCreateDeploymentCreationFailure(t *testing.T) {
testRepository.Created[0])
}
if testRepository.DeploymentStatuses[0] != common.FailedStatus {
if testRepository.DeploymentStates[0].Status != common.FailedStatus {
t.Fatal("CreateDeployment failure did not mark deployment as failed")
}
......@@ -399,7 +399,7 @@ func TestCreateDeploymentCreationResourceFailure(t *testing.T) {
testRepository.Created[0])
}
if testRepository.DeploymentStatuses[0] != common.FailedStatus {
if testRepository.DeploymentStates[0].Status != common.FailedStatus {
t.Fatal("CreateDeployment failure did not mark deployment as failed")
}
......@@ -455,6 +455,10 @@ func TestDeleteDeploymentForget(t *testing.T) {
if err != nil {
t.Fatalf("DeleteDeployment failed with %v", err)
}
if d.State.Status != common.DeletedStatus {
t.Fatalf("Expected DeletedStatus on deleted deployment")
}
// Make sure the resources were deleted through deployer.
if len(testDeployer.Deleted) > 0 {
c := testDeployer.Deleted[0]
......
......@@ -34,7 +34,7 @@ type Repository interface {
GetValidDeployment(name string) (*common.Deployment, error)
CreateDeployment(name string) (*common.Deployment, error)
DeleteDeployment(name string, forget bool) (*common.Deployment, error)
SetDeploymentStatus(name string, status common.DeploymentStatus) error
SetDeploymentState(name string, state *common.DeploymentState) error
// Manifests.
AddManifest(deploymentName string, manifest *common.Manifest) error
......@@ -103,15 +103,15 @@ func (r *mapBasedRepository) GetValidDeployment(name string) (*common.Deployment
return nil, err
}
if d.Status == common.DeletedStatus {
if d.State.Status == common.DeletedStatus {
return nil, fmt.Errorf("deployment %s is deleted", name)
}
return d, nil
}
// SetDeploymentStatus sets the DeploymentStatus of the deployment and updates ModifiedAt
func (r *mapBasedRepository) SetDeploymentStatus(name string, status common.DeploymentStatus) error {
// SetDeploymentState sets the DeploymentState of the deployment and updates ModifiedAt
func (r *mapBasedRepository) SetDeploymentState(name string, state *common.DeploymentState) error {
return func() error {
r.Lock()
defer r.Unlock()
......@@ -121,7 +121,7 @@ func (r *mapBasedRepository) SetDeploymentStatus(name string, status common.Depl
return err
}
d.Status = status
d.State = state
d.ModifiedAt = time.Now()
r.deployments[name] = *d
return nil
......@@ -140,7 +140,6 @@ func (r *mapBasedRepository) CreateDeployment(name string) (*common.Deployment,
}
d := common.NewDeployment(name)
d.Status = common.CreatedStatus
d.DeployedAt = time.Now()
r.deployments[name] = *d
return d, nil
......@@ -214,7 +213,7 @@ func (r *mapBasedRepository) DeleteDeployment(name string, forget bool) (*common
if !forget {
d.DeletedAt = time.Now()
d.Status = common.DeletedStatus
d.State = &common.DeploymentState{Status: common.DeletedStatus}
r.deployments[name] = *d
} else {
delete(r.deployments, name)
......
......@@ -140,7 +140,7 @@ func TestRepositoryDeleteWorksWithNoLatestManifest(t *testing.T) {
if err != nil {
t.Fatalf("DeleteDeployment failed: %v", err)
}
if dDeleted.Status != common.DeletedStatus {
if dDeleted.State.Status != common.DeletedStatus {
t.Fatalf("Deployment Status is not deleted")
}
if _, err := r.ListManifests(deploymentName); err == nil {
......@@ -165,7 +165,7 @@ func TestRepositoryDeleteDeploymentWorksNoForget(t *testing.T) {
if err != nil {
t.Fatalf("DeleteDeployment failed: %v", err)
}
if dDeleted.Status != common.DeletedStatus {
if dDeleted.State.Status != common.DeletedStatus {
t.Fatalf("Deployment Status is not deleted")
}
}
......@@ -187,7 +187,7 @@ func TestRepositoryDeleteDeploymentWorksForget(t *testing.T) {
if err != nil {
t.Fatalf("DeleteDeployment failed: %v", err)
}
if dDeleted.Status != common.CreatedStatus {
if dDeleted.State.Status != common.CreatedStatus {
t.Fatalf("Deployment Status is not created")
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment