Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions app/actions/stack_update.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ def update(stack, message)
stack_updates = {}
stack_updates[:state] = message.state if message.requested?(:state)
stack_updates[:state_reason] = message.state_reason if message.state_reason_requested?
stack_updates[:description] = message.description if message.requested?(:description)
stack.update(stack_updates) if stack_updates.any?

MetadataUpdate.update(stack, message)
Expand Down
3 changes: 2 additions & 1 deletion app/messages/stack_update_message.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@

module VCAP::CloudController
class StackUpdateMessage < MetadataBaseMessage
register_allowed_keys %i[state state_reason]
register_allowed_keys %i[state state_reason description]

validates_with NoAdditionalKeysValidator
validates :state, inclusion: { in: StackStates::VALID_STATES, message: "must be one of #{StackStates::VALID_STATES.join(', ')}" }, allow_nil: false, if: :state_requested?
validates :state_reason, length: { maximum: 5000 }, allow_nil: true
validates :description, length: { maximum: 250 }, allow_nil: true

def state_requested?
requested?(:state)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ content:
maxLength: 250
description:
type: [string, "null"]
description: Description of the stack; must no longer than 250 characters
description: Description of the stack; must be no longer than 250 characters
maxLength: 250
metadata:
$ref: '../schemas/Metadata.yaml'
Expand Down
5 changes: 5 additions & 0 deletions docs/openapi/apis/cf/latest/paths/Stacks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@
application/json:
schema:
properties:
description:
type: string
description: Description of the stack; must be no longer than 250 characters
maxLength: 250
metadata:
$ref: ../components/schemas/Metadata.yaml
examples:
Expand All @@ -164,6 +168,7 @@
key: value
annotations:
note: detailed information
description: Example stack description
state: ACTIVE
state_reason: Optional plain text describing the stack state change
responses:
Expand Down
2 changes: 1 addition & 1 deletion docs/v3/source/includes/resources/stacks/_create.md.erb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Name | Type | Description

Name | Type | Description | Default
---- | ---- | ----------- | -------
**description** | _string_ | Description of the stack; must no longer than 250 characters | `null`
**description** | _string_ | Description of the stack; must be no longer than 250 characters | `null`
**metadata.labels** | [_label object_](#labels) | Labels applied to the stack
**metadata.annotations** | [_annotation object_](#annotations) | Annotations applied to the stack
**state** | string | The state of the stack; valid states are: `ACTIVE`, `RESTRICTED`, `DEPRECATED`, `DISABLED`
Expand Down
3 changes: 2 additions & 1 deletion docs/v3/source/includes/resources/stacks/_update.md.erb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ curl "https://api.example.org/v3/stacks/[guid]" \
-X PATCH \
-H "Authorization: bearer [token]" \
-H "Content-Type: application/json" \
-d '{ "metadata": { "labels": { "key": "value" }, "annotations": {"note": "detailed information"}},"state":"ACTIVE", "state_reason": "Optional plain text describing the stack state change" }'
-d '{ "metadata": { "labels": { "key": "value" }, "annotations": {"note": "detailed information"}},"description": "Example stack description", "state":"ACTIVE", "state_reason": "Optional plain text describing the stack state change" }'

```

Expand All @@ -31,6 +31,7 @@ Content-Type: application/json

Name | Type | Description
---- | ---- | -----------
**description** | _string_ | Description of the stack; must be no longer than 250 characters
**metadata.labels** | [_label object_](#labels) | Labels applied to the stack
**metadata.annotations** | [_annotation object_](#annotations) | Annotations applied to the stack
**state** | string | The state of the stack; valid states are: `ACTIVE`, `RESTRICTED`, `DEPRECATED`, `DISABLED`
Expand Down
17 changes: 17 additions & 0 deletions spec/request/stacks_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,23 @@
}
)
end

it 'updates the description of a stack' do
patch "/v3/stacks/#{stack.guid}", { description: 'Preview stack, do not use in production' }.to_json, headers

expect(last_response.status).to eq(200)
expect(parsed_response['description']).to eq('Preview stack, do not use in production')

stack.reload
expect(stack.description).to eq('Preview stack, do not use in production')
end

it 'returns 422 when description exceeds the maximum length' do
patch "/v3/stacks/#{stack.guid}", { description: 'A' * 251 }.to_json, headers

expect(last_response.status).to eq(422)
expect(last_response).to have_error_message('Description is too long (maximum is 250 characters)')
end
end

describe 'DELETE /v3/stacks/:guid' do
Expand Down
22 changes: 22 additions & 0 deletions spec/unit/actions/stack_update_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,5 +95,27 @@ module VCAP::CloudController
expect(stack.state_reason).to eq('Existing reason')
end
end

context 'when updating description' do
let(:stack) { create(:stack, description: 'Original description') }

it 'updates description when provided' do
message = StackUpdateMessage.new({ description: 'Preview stack' })

stack_update.update(stack, message)
stack.reload

expect(stack.description).to eq('Preview stack')
end

it 'preserves description when not requested' do
message = StackUpdateMessage.new({ state: 'RESTRICTED' })

stack_update.update(stack, message)
stack.reload

expect(stack.description).to eq('Original description')
end
end
end
end
8 changes: 8 additions & 0 deletions spec/unit/messages/stack_create_message_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@
end

describe 'description' do
context 'when it is not provided' do
let(:params) { valid_params }

it 'is valid' do
expect(subject).to be_valid
end
end

context 'when it is just long enough' do
let(:params) { valid_params.merge({ description: 'A' * MAX_DESCRIPTION_LENGTH }) }

Expand Down
54 changes: 54 additions & 0 deletions spec/unit/messages/stack_update_message_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -120,5 +120,59 @@
end
end
end

describe 'description' do
MAX_DESCRIPTION_LENGTH = 250

context 'when it is not provided' do
let(:params) { valid_params }

it 'is valid' do
expect(subject).to be_valid
end
end

context 'when it is provided' do
let(:params) { valid_params.merge({ description: 'Preview stack, do not use in production' }) }

it 'is valid' do
expect(subject).to be_valid
expect(subject.description).to eq('Preview stack, do not use in production')
end
end

context 'when it is at maximum length' do
let(:params) { valid_params.merge({ description: 'A' * MAX_DESCRIPTION_LENGTH }) }

it 'is valid' do
expect(subject).to be_valid
end
end

context 'when it exceeds maximum length' do
let(:params) { valid_params.merge({ description: 'A' * (MAX_DESCRIPTION_LENGTH + 1) }) }

it 'returns an error' do
expect(subject).not_to be_valid
expect(subject.errors[:description]).to eq ["is too long (maximum is #{MAX_DESCRIPTION_LENGTH} characters)"]
end
end

context 'when it is an empty string' do
let(:params) { valid_params.merge({ description: '' }) }

it 'is valid' do
expect(subject).to be_valid
end
end

context 'when it is explicitly null' do
let(:params) { valid_params.merge({ description: nil }) }

it 'is valid' do
expect(subject).to be_valid
end
end
end
end
end
Loading