-
Notifications
You must be signed in to change notification settings - Fork 13
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
PWX-29108 : Handle nil pointer dereference in cloudops #140
base: master
Are you sure you want to change the base?
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 |
---|---|---|
|
@@ -29,11 +29,11 @@ import ( | |
) | ||
|
||
const ( | ||
awsDevicePrefix = "/dev/sd" | ||
awsDevicePrefixWithX = "/dev/xvd" | ||
awsDevicePrefixWithH = "/dev/hd" | ||
awsDevicePrefixNvme = "/dev/nvme" | ||
contextTimeout = 30 * time.Second | ||
awsDevicePrefix = "/dev/sd" | ||
awsDevicePrefixWithX = "/dev/xvd" | ||
awsDevicePrefixWithH = "/dev/hd" | ||
awsDevicePrefixNvme = "/dev/nvme" | ||
contextTimeout = 30 * time.Second | ||
awsErrorModificationNotFound = "InvalidVolumeModification.NotFound" | ||
) | ||
|
||
|
@@ -72,7 +72,9 @@ func NewClient() (cloudops.Ops, error) { | |
return nil, err | ||
} | ||
} | ||
|
||
if len(zone) == 0 { | ||
return nil, fmt.Errorf("env does not have information about zone") | ||
} | ||
region := zone[:len(zone)-1] | ||
awsCreds, err := awscredentials.NewAWSCredentials("", "", "", runningOnEc2) | ||
if err != nil { | ||
|
@@ -215,6 +217,9 @@ func (s *awsOps) waitAttachmentStatus( | |
|
||
var actual string | ||
vol := awsVols.Volumes[0] | ||
if vol == nil { | ||
return nil, false, fmt.Errorf("nil volume for %s", volumeID) | ||
} | ||
awsAttachment := vol.Attachments | ||
if awsAttachment == nil || len(awsAttachment) == 0 { | ||
// We have encountered scenarios where AWS returns a nil attachment state | ||
|
@@ -298,6 +303,10 @@ func (s *awsOps) InspectInstanceGroupForInstance(instanceID string) (*cloudops.I | |
} | ||
|
||
group := result.AutoScalingGroups[0] | ||
if group == nil { | ||
return nil, fmt.Errorf("nil AutoScalingGroups group") | ||
} | ||
|
||
zones := make([]string, 0) | ||
for _, z := range group.AvailabilityZones { | ||
zones = append(zones, *z) | ||
|
@@ -759,6 +768,9 @@ func (s *awsOps) Enumerate( | |
|
||
// Volume sets are identified by volumes with the same setIdentifer. | ||
for _, vol := range awsVols.Volumes { | ||
if vol == nil { | ||
continue | ||
} | ||
if s.deleted(vol) { | ||
continue | ||
} | ||
|
@@ -796,7 +808,18 @@ func (s *awsOps) Create( | |
return nil, cloudops.NewStorageError(cloudops.ErrVolInval, | ||
"Drive type not specified in the storage spec", "") | ||
} | ||
|
||
if vol.AvailabilityZone == nil { | ||
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. According to CreateVolumeInput documentation
|
||
return nil, cloudops.NewStorageError(cloudops.ErrVolInval, | ||
"AvailabilityZone not specified in the storage spec", "") | ||
} | ||
if vol.Size == nil { | ||
return nil, cloudops.NewStorageError(cloudops.ErrVolInval, | ||
"Size not specified in the storage spec", "") | ||
} | ||
if vol.SnapshotId == nil { | ||
return nil, cloudops.NewStorageError(cloudops.ErrVolInval, | ||
"SnapshotId not specified in the storage spec", "") | ||
} | ||
req := &ec2.CreateVolumeInput{ | ||
AvailabilityZone: vol.AvailabilityZone, | ||
Encrypted: vol.Encrypted, | ||
|
@@ -965,7 +988,9 @@ func (s *awsOps) AreVolumesReadyToExpand(volumeIDs []*string) (bool, error) { | |
} | ||
} | ||
states := describeOutput.VolumesModifications | ||
|
||
if states == nil { | ||
return false, fmt.Errorf("information about the volume modifications is nil") | ||
} | ||
var state string | ||
for i := 0; i < len(states); i++ { | ||
if states[i] == nil || states[i].ModificationState == nil { | ||
|
@@ -977,7 +1002,7 @@ func (s *awsOps) AreVolumesReadyToExpand(volumeIDs []*string) (bool, error) { | |
logrus.Infof("retrived volume modification state: %s for volume id: %s", state, *volumeIDs[i]) | ||
if state == ec2.VolumeModificationStateModifying || | ||
state == ec2.VolumeModificationStateOptimizing { | ||
return false, fmt.Errorf("aws has not fully completed the last modification: " + | ||
return false, fmt.Errorf("aws has not fully completed the last modification: "+ | ||
"volume %s is in %s state. please retry later", *volumeIDs[i], state) | ||
} | ||
} | ||
|
@@ -993,6 +1018,14 @@ func (s *awsOps) Expand( | |
if err != nil { | ||
return 0, err | ||
} | ||
if vol.Size == nil { | ||
return 0, cloudops.NewStorageError(cloudops.ErrVolInval, | ||
"Size not specified in the storage spec", "") | ||
} | ||
if vol.VolumeId == nil { | ||
return 0, cloudops.NewStorageError(cloudops.ErrVolInval, | ||
"VolumeId not specified in the storage spec", "") | ||
} | ||
currentSizeInGiB := uint64(*vol.Size) | ||
if currentSizeInGiB >= newSizeInGiB { | ||
return currentSizeInGiB, cloudops.NewStorageError(cloudops.ErrDiskGreaterOrEqualToExpandSize, | ||
|
@@ -1011,7 +1044,17 @@ func (s *awsOps) Expand( | |
return currentSizeInGiB, fmt.Errorf("failed to modify AWS volume for %v: %v", volumeID, err) | ||
} | ||
|
||
if output.VolumeModification == nil { | ||
return currentSizeInGiB, fmt.Errorf("failed to modify AWS volume for %v: %v", volumeID, "VolumeModification is nil") | ||
} | ||
if output.VolumeModification.ModificationState == nil { | ||
return currentSizeInGiB, fmt.Errorf("failed to modify AWS volume for %v: %v", volumeID, "ModificationState is nil") | ||
} | ||
|
||
if string(*output.VolumeModification.ModificationState) == ec2.VolumeModificationStateCompleted { | ||
if output.VolumeModification.TargetSize == nil { | ||
return currentSizeInGiB, fmt.Errorf("failed to modify AWS volume for %v: %v", volumeID, "TargetSize is nil") | ||
} | ||
return uint64(*output.VolumeModification.TargetSize), nil | ||
} | ||
|
||
|
@@ -1180,6 +1223,9 @@ func DescribeInstanceByID(service *ec2.EC2, id string) (*ec2.Instance, error) { | |
if err != nil { | ||
return nil, err | ||
} | ||
if out.Reservations == nil { | ||
return nil, fmt.Errorf("DescribeInstances(%v) returned nil Reservations", id) | ||
} | ||
if len(out.Reservations) != 1 { | ||
return nil, fmt.Errorf("DescribeInstances(%v) returned %v reservations, expect 1", | ||
id, len(out.Reservations)) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -371,14 +371,20 @@ func (a *azureOps) Create( | |
options map[string]string, | ||
) (interface{}, error) { | ||
d, ok := template.(*compute.Disk) | ||
if !ok || d.DiskProperties == nil || d.DiskProperties.DiskSizeGB == nil { | ||
if !ok || d.DiskProperties == nil { | ||
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. According to the documentation of Azure - If creationData.createOption is Empty, this field is mandatory and it indicates the size of the disk to create. Also, this parameter caused panic before - https://portworx.atlassian.net/browse/PWX-29069 |
||
return nil, cloudops.NewStorageError( | ||
cloudops.ErrVolInval, | ||
"Invalid volume template given", | ||
a.instance, | ||
) | ||
} | ||
|
||
if d.DiskProperties.DiskSizeGB == nil { | ||
return nil, cloudops.NewStorageError( | ||
cloudops.ErrVolInval, | ||
"DiskSizeGB not specified in the storage spec", | ||
a.instance, | ||
) | ||
} | ||
// Check if the disk already exists; return err if it does | ||
_, err := a.disksClient.Get( | ||
context.Background(), | ||
|
@@ -707,6 +713,13 @@ func (a *azureOps) DeviceMappings() (map[string]string, error) { | |
|
||
devMap := make(map[string]string) | ||
for _, d := range dataDisks { | ||
if d.Lun == nil { | ||
return nil, cloudops.NewStorageError( | ||
cloudops.ErrInvalidDevicePath, | ||
"lun is nil for disk", | ||
a.instance, | ||
) | ||
} | ||
devPath, err := lunToBlockDevPath(*d.Lun) | ||
if err != nil { | ||
return nil, cloudops.NewStorageError( | ||
|
@@ -715,6 +728,9 @@ func (a *azureOps) DeviceMappings() (map[string]string, error) { | |
a.instance, | ||
) | ||
} | ||
if d.Name == nil { | ||
continue | ||
} | ||
devMap[devPath] = *d.Name | ||
} | ||
|
||
|
@@ -809,9 +825,19 @@ func (a *azureOps) devicePath(diskName string) (string, error) { | |
} | ||
|
||
for _, d := range dataDisks { | ||
if d.Name == nil { | ||
continue | ||
} | ||
if *d.Name == diskName { | ||
// Retry to get the block dev path as it may take few seconds for the path | ||
// to be created even after the disk shows attached. | ||
if d.Lun == nil { | ||
return "", cloudops.NewStorageError( | ||
cloudops.ErrInvalidDevicePath, | ||
"Lun is nil for disk", | ||
a.instance, | ||
) | ||
} | ||
devPath, err := lunToBlockDevPathWithRetry(*d.Lun) | ||
if err == nil { | ||
return devPath, nil | ||
|
@@ -1046,6 +1072,9 @@ func (a *azureOps) waitForDetach(diskName, instance string) error { | |
} | ||
|
||
for _, d := range dataDisks { | ||
if d.Name != nil { | ||
continue | ||
} | ||
if *d.Name == diskName { | ||
return nil, true, | ||
fmt.Errorf("disk %s is still attached to instance %s", | ||
|
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.
It is not mandatory but being dereference below
if *vol.VolumeType == opsworks.VolumeTypeIo1 || *vol.VolumeType == "gp3" {