1package disk
2
3import (
4	"reflect"
5
6	bicloud "github.com/cloudfoundry/bosh-cli/cloud"
7	biconfig "github.com/cloudfoundry/bosh-cli/config"
8	bosherr "github.com/cloudfoundry/bosh-utils/errors"
9	biproperty "github.com/cloudfoundry/bosh-utils/property"
10)
11
12type Disk interface {
13	CID() string
14	NeedsMigration(newSize int, newCloudProperties biproperty.Map) bool
15	Delete() error
16}
17
18type disk struct {
19	cid             string
20	size            int
21	cloudProperties biproperty.Map
22
23	cloud bicloud.Cloud
24	repo  biconfig.DiskRepo
25}
26
27func NewDisk(
28	diskRecord biconfig.DiskRecord,
29	cloud bicloud.Cloud,
30	repo biconfig.DiskRepo,
31) Disk {
32	return &disk{
33		cid:             diskRecord.CID,
34		size:            diskRecord.Size,
35		cloudProperties: diskRecord.CloudProperties,
36		cloud:           cloud,
37		repo:            repo,
38	}
39}
40
41func (d *disk) CID() string {
42	return d.cid
43}
44
45func (d *disk) NeedsMigration(newSize int, newCloudProperties biproperty.Map) bool {
46	return d.size != newSize || !reflect.DeepEqual(d.cloudProperties, newCloudProperties)
47}
48
49func (d *disk) Delete() error {
50	deleteErr := d.cloud.DeleteDisk(d.cid)
51	if deleteErr != nil {
52		// allow DiskNotFoundError for idempotency
53		cloudErr, ok := deleteErr.(bicloud.Error)
54		if !ok || cloudErr.Type() != bicloud.DiskNotFoundError {
55			return bosherr.WrapError(deleteErr, "Deleting disk in the cloud")
56		}
57	}
58
59	diskRecord, found, err := d.repo.Find(d.cid)
60	if err != nil {
61		return bosherr.WrapErrorf(err, "Finding disk record (cid=%s)", d.cid)
62	}
63
64	if !found {
65		return nil
66	}
67
68	err = d.repo.Delete(diskRecord)
69	if err != nil {
70		return bosherr.WrapError(err, "Deleting disk record")
71	}
72
73	// returns bicloud.Error only if it is a DiskNotFoundError
74	return deleteErr
75}
76