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
3 changes: 2 additions & 1 deletion app/actions/stack_create.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ def create(message)
stack = VCAP::CloudController::Stack.create(
name: message.name,
description: message.description,
state: message.state
state: message.state,
state_reason: message.state_reason
)

MetadataUpdate.update(stack, message)
Expand Down
6 changes: 5 additions & 1 deletion app/actions/stack_update.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ def initialize(user_audit_info)

def update(stack, message)
stack.db.transaction do
stack.update(state: message.state) if message.requested?(:state)
stack_updates = {}
stack_updates[:state] = message.state if message.requested?(:state)
stack_updates[:state_reason] = message.state_reason if message.requested?(:state_reason)
stack.update(stack_updates) if stack_updates.any?

MetadataUpdate.update(stack, message)
Repositories::StackEventRepository.new.record_stack_update(stack, @user_audit_info, message.audit_hash)
end
Expand Down
3 changes: 2 additions & 1 deletion app/messages/stack_create_message.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@

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

validates :name, presence: true, length: { maximum: 250 }
validates :description, length: { maximum: 250 }
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

def state_requested?
requested?(:state)
Expand Down
7 changes: 6 additions & 1 deletion app/messages/stack_update_message.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@

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

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

def state_requested?
requested?(:state)
end

def state_reason_requested?
requested?(:state_reason)
end
end
end
1 change: 1 addition & 0 deletions app/presenters/v3/stack_presenter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ def to_hash
name: stack.name,
description: stack.description,
state: stack.state,
state_reason: stack.state_reason,
run_rootfs_image: stack.run_rootfs_image,
build_rootfs_image: stack.build_rootfs_image,
default: stack.default?,
Expand Down
13 changes: 13 additions & 0 deletions db/migrations/20260202105042_add_state_reason_to_stacks.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Sequel.migration do
up do
alter_table :stacks do
add_column :state_reason, String, null: true, size: 5000 unless @db.schema(:stacks).map(&:first).include?(:state_reason)
end
end

down do
alter_table :stacks do
drop_column :state_reason if @db.schema(:stacks).map(&:first).include?(:state_reason)
end
end
end
4 changes: 4 additions & 0 deletions docs/v3/source/includes/api_resources/_stacks.erb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"name": "my-stack",
"description": "Here is my stack!",
"state": "ACTIVE",
"state_reason": null,
"build_rootfs_image": "my-stack",
"run_rootfs_image": "my-stack",
"default": true,
Expand Down Expand Up @@ -47,6 +48,7 @@
"run_rootfs_image": "my-stack-1-run",
"description": "This is my first stack!",
"state": "ACTIVE",
"state_reason": null,
"default": true,
"metadata": {
"labels": {},
Expand All @@ -67,6 +69,7 @@
"build_rootfs_image": "my-stack-2-build",
"run_rootfs_image": "my-stack-2-run",
"state": "DEPRECATED",
"state_reason": "Stack deprecated and will be removed in future release",
"default": false,
"metadata": {
"labels": {},
Expand All @@ -91,6 +94,7 @@
"name": "my-stack",
"description": "Here is my stack!",
"state": "DISABLED",
"state_reason": "Stack disabled and cannot be used for staging new application",
"build_rootfs_image": "my-stack",
"run_rootfs_image": "my-stack",
"default": true,
Expand Down
2 changes: 2 additions & 0 deletions docs/v3/source/includes/resources/stacks/_create.md.erb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ curl "https://api.example.org/v3/stacks" \
"name": "my-stack",
"description": "Here is my stack!",
"state": "ACTIVE",
"state_reason": "",
}'
```

Expand Down Expand Up @@ -44,6 +45,7 @@ Name | Type | Description | Default
**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`
**state_reason** | string | Optional plain text describing the stack state change

#### Permitted roles
|
Expand Down
1 change: 1 addition & 0 deletions docs/v3/source/includes/resources/stacks/_object.md.erb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Name | Type | Description
**name** | _string_ | The name of the stack
**description** | _string_ | The description of the stack
**state** | string | The state of the stack; valid states are: `ACTIVE`, `RESTRICTED`, `DEPRECATED`, `DISABLED`
**state_reason** | string | Optional plain text describing the stack state change
**build_rootfs_image** | _string | The name of the stack image associated with staging/building Apps. If a stack does not have unique images, this will be the same as the stack name.
**run_rootfs_image** | _string | The name of the stack image associated with running Apps + Tasks. If a stack does not have unique images, this will be the same as the stack name.
**default** | _boolean_ | Whether the stack is configured to be the default stack for new applications.
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"}'
-d '{ "metadata": { "labels": { "key": "value" }, "annotations": {"note": "detailed information"}},"state":"ACTIVE", "state_reason": "Optional plain text describing the stack state change" }'

```

Expand All @@ -34,6 +34,7 @@ Name | Type | Description
**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`
**state_reason** | string | Optional plain text describing the stack state change

#### Permitted roles
|
Expand Down
8 changes: 6 additions & 2 deletions lib/cloud_controller/stack_state_validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,15 @@ def self.validate_for_restaging!(stack)
end

def self.build_stack_error(stack, state)
"ERROR: Staging failed. The stack '#{stack.name}' is '#{state}' and cannot be used for staging."
message = "ERROR: Staging failed. The stack '#{stack.name}' is '#{state}' and cannot be used for staging."
message += " #{stack.state_reason}" if stack.state_reason.present?
message
end

def self.build_stack_warning(stack, state)
"WARNING: The stack '#{stack.name}' is '#{state}' and will be removed in the future."
message = "WARNING: The stack '#{stack.name}' is '#{state}' and will be removed in the future."
message += " #{stack.state_reason}" if stack.state_reason.present?
message
end
end
end
11 changes: 11 additions & 0 deletions spec/request/stacks_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
'build_rootfs_image' => stack1.build_rootfs_image,
'guid' => stack1.guid,
'state' => 'ACTIVE',
'state_reason' => nil,
'default' => false,
'metadata' => { 'labels' => {}, 'annotations' => {} },
'created_at' => iso8601,
Expand All @@ -44,6 +45,7 @@
'build_rootfs_image' => stack2.build_rootfs_image,
'guid' => stack2.guid,
'state' => 'ACTIVE',
'state_reason' => nil,
'default' => true,
'metadata' => { 'labels' => {}, 'annotations' => {} },
'created_at' => iso8601,
Expand Down Expand Up @@ -125,6 +127,7 @@
'build_rootfs_image' => stack1.build_rootfs_image,
'guid' => stack1.guid,
'state' => 'ACTIVE',
'state_reason' => nil,
'default' => false,
'metadata' => { 'labels' => {}, 'annotations' => {} },
'created_at' => iso8601,
Expand All @@ -142,6 +145,7 @@
'build_rootfs_image' => stack2.build_rootfs_image,
'guid' => stack2.guid,
'state' => 'ACTIVE',
'state_reason' => nil,
'default' => true,
'metadata' => { 'labels' => {}, 'annotations' => {} },
'created_at' => iso8601,
Expand Down Expand Up @@ -182,6 +186,7 @@
'build_rootfs_image' => stack1.build_rootfs_image,
'guid' => stack1.guid,
'state' => 'ACTIVE',
'state_reason' => nil,
'default' => false,
'metadata' => { 'labels' => {}, 'annotations' => {} },
'created_at' => iso8601,
Expand All @@ -199,6 +204,7 @@
'build_rootfs_image' => stack3.build_rootfs_image,
'guid' => stack3.guid,
'state' => 'ACTIVE',
'state_reason' => nil,
'default' => false,
'metadata' => { 'labels' => {}, 'annotations' => {} },
'created_at' => iso8601,
Expand Down Expand Up @@ -239,6 +245,7 @@
'build_rootfs_image' => stack2.build_rootfs_image,
'guid' => stack2.guid,
'state' => 'ACTIVE',
'state_reason' => nil,
'default' => true,
'metadata' => { 'labels' => {}, 'annotations' => {} },
'created_at' => iso8601,
Expand Down Expand Up @@ -295,6 +302,7 @@
'build_rootfs_image' => stack1.build_rootfs_image,
'guid' => stack1.guid,
'state' => 'ACTIVE',
'state_reason' => nil,
'default' => false,
'metadata' => {
'labels' => {
Expand Down Expand Up @@ -332,6 +340,7 @@
'build_rootfs_image' => stack.build_rootfs_image,
'guid' => stack.guid,
'state' => 'ACTIVE',
'state_reason' => nil,
'default' => false,
'metadata' => { 'labels' => {}, 'annotations' => {} },
'created_at' => iso8601,
Expand Down Expand Up @@ -680,6 +689,7 @@
},
'guid' => created_stack.guid,
'state' => 'ACTIVE',
'state_reason' => nil,
'created_at' => iso8601,
'updated_at' => iso8601,
'links' => {
Expand Down Expand Up @@ -745,6 +755,7 @@
},
'guid' => stack.guid,
'state' => 'ACTIVE',
'state_reason' => nil,
'created_at' => iso8601,
'updated_at' => iso8601,
'links' => {
Expand Down
Loading