mirror of
https://github.com/czhu12/canine.git
synced 2025-12-16 16:35:10 -06:00
create pod yaml overrides
This commit is contained in:
@@ -137,6 +137,7 @@ rails console
|
||||
4. **Kubernetes Resources**: Update templates in `resources/k8/` for deployment changes
|
||||
5. **Migrations**: Use strong migrations practices for zero-downtime deployments
|
||||
6. **Linting**: Always run `rubocop -A` at the end of every development cycle
|
||||
7. **Testing**: If you are going to create a spec, make sure to run it at the end of the development cycle. Don't write specs for validations or associations. Don't create many specs, keep them short and test multiple things in a single spec if it is conveniant
|
||||
|
||||
## Important Patterns
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
# healthcheck_url :string
|
||||
# last_health_checked_at :datetime
|
||||
# name :string not null
|
||||
# pod_yaml :jsonb
|
||||
# replicas :integer default(1)
|
||||
# service_type :integer not null
|
||||
# status :integer default("pending")
|
||||
@@ -67,7 +68,7 @@ class Service < ApplicationRecord
|
||||
end
|
||||
|
||||
def self.permitted_params(params)
|
||||
params.require(:service).permit(
|
||||
permitted = params.require(:service).permit(
|
||||
:service_type,
|
||||
:command,
|
||||
:name,
|
||||
@@ -75,7 +76,20 @@ class Service < ApplicationRecord
|
||||
:healthcheck_url,
|
||||
:replicas,
|
||||
:description,
|
||||
:allow_public_networking
|
||||
:allow_public_networking,
|
||||
:pod_yaml
|
||||
)
|
||||
|
||||
# Convert YAML text to JSON if pod_yaml is present
|
||||
if permitted[:pod_yaml].present?
|
||||
begin
|
||||
permitted[:pod_yaml] = YAML.safe_load(permitted[:pod_yaml])
|
||||
rescue Psych::SyntaxError => e
|
||||
# If YAML parsing fails, keep the original value so validation can catch it
|
||||
Rails.logger.error("Failed to parse pod_yaml: #{e.message}")
|
||||
end
|
||||
end
|
||||
|
||||
permitted
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,4 +2,59 @@
|
||||
<h2 class="text-xl font-bold">Resource Constraints</h2>
|
||||
<hr class="mt-3 mb-4 border-t border-base-300" />
|
||||
<%= render "projects/services/resource_constraints/show", service: @service, resource_constraint: @service.resource_constraint %>
|
||||
</div>
|
||||
|
||||
<div class="mt-8" data-controller="content-toggle">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h2 class="text-xl font-bold">Pod Template Configuration</h2>
|
||||
|
||||
<button type="button"
|
||||
class="btn btn-sm btn-outline"
|
||||
data-action="click->content-toggle#toggleEdit"
|
||||
data-content-toggle-target="editButton">
|
||||
<iconify-icon icon="lucide:pen" height="16"></iconify-icon>
|
||||
Edit
|
||||
</button>
|
||||
</div>
|
||||
<hr class="mt-3 mb-4 border-t border-base-300" />
|
||||
|
||||
<div data-content-toggle-target="placeholder" class="p-4 bg-base-200 rounded-lg">
|
||||
<% if @service.pod_yaml.present? %>
|
||||
<p class="text-sm text-gray-500">Custom pod template is configured. Click edit to view and modify.</p>
|
||||
<% else %>
|
||||
<p class="text-sm text-gray-500">No custom pod template configured. Click edit to add custom configuration.</p>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div data-content-toggle-target="editorContainer" class="hidden">
|
||||
<p class="my-2 text-sm text-gray-300">
|
||||
Enter custom YAML configuration for the pod template spec. This will be merged with the default pod template in your <code>deployment.yaml</code> and <code>cron_job.yaml</code> files.
|
||||
Only the pod template spec fields are supported (<code>containers</code>, <code>volumes</code>, <code>serviceAccountName</code>, etc.).
|
||||
</p>
|
||||
|
||||
<%= form_with(model: @service, url: project_service_path(@service.project, @service), method: :put) do |form| %>
|
||||
<div class="form-control" data-controller="yaml-editor">
|
||||
<%= form.label :pod_yaml, "Pod Template YAML", class: "label" %>
|
||||
<%= form.text_area :pod_yaml,
|
||||
rows: 15,
|
||||
placeholder: "# Example:\ncontainers:\n - name: sidecar\n image: nginx:latest\nvolumes:\n - name: cache\n emptyDir: {}",
|
||||
class: "textarea textarea-bordered font-mono text-sm w-full",
|
||||
data: { yaml_editor_target: "textarea" },
|
||||
value: @service.pod_yaml.present? ? @service.pod_yaml.to_yaml : "" %>
|
||||
<div data-yaml-editor-target="editor"></div>
|
||||
<label class="label">
|
||||
<span class="label-text-alt">Enter valid YAML for pod template spec fields</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-footer mt-6 flex gap-2">
|
||||
<%= form.submit @service.pod_yaml.present? ? "Update Pod Template" : "Save Pod Template", class: "btn btn-primary" %>
|
||||
<button type="button"
|
||||
class="btn btn-outline"
|
||||
data-action="click->content-toggle#cancelEdit">
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
5
db/migrate/20251116091324_add_pod_yaml_to_services.rb
Normal file
5
db/migrate/20251116091324_add_pod_yaml_to_services.rb
Normal file
@@ -0,0 +1,5 @@
|
||||
class AddPodYamlToServices < ActiveRecord::Migration[7.2]
|
||||
def change
|
||||
add_column :services, :pod_yaml, :jsonb
|
||||
end
|
||||
end
|
||||
3
db/schema.rb
generated
3
db/schema.rb
generated
@@ -10,7 +10,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[7.2].define(version: 2025_11_16_041928) do
|
||||
ActiveRecord::Schema[7.2].define(version: 2025_11_16_091324) do
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
||||
@@ -473,6 +473,7 @@ ActiveRecord::Schema[7.2].define(version: 2025_11_16_041928) do
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.text "description"
|
||||
t.jsonb "pod_yaml"
|
||||
t.index ["project_id"], name: "index_services_on_project_id"
|
||||
end
|
||||
|
||||
|
||||
@@ -74,3 +74,6 @@ spec:
|
||||
# Add your volume specifications here (e.g., persistentVolumeClaim, configMap, etc.)
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% if service.pod_yaml.present? %>
|
||||
<%= service.pod_yaml %>
|
||||
<% end %>
|
||||
|
||||
@@ -94,3 +94,6 @@ spec:
|
||||
claimName: <%= volume.name %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% if service.pod_yaml.present? %>
|
||||
<%= service.pod_yaml %>
|
||||
<% end %>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
# healthcheck_url :string
|
||||
# last_health_checked_at :datetime
|
||||
# name :string not null
|
||||
# pod_yaml :jsonb
|
||||
# replicas :integer default(1)
|
||||
# service_type :integer not null
|
||||
# status :integer default("pending")
|
||||
|
||||
52
spec/models/service_spec.rb
Normal file
52
spec/models/service_spec.rb
Normal file
@@ -0,0 +1,52 @@
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: services
|
||||
#
|
||||
# id :bigint not null, primary key
|
||||
# allow_public_networking :boolean default(FALSE)
|
||||
# command :string
|
||||
# container_port :integer default(3000)
|
||||
# description :text
|
||||
# healthcheck_url :string
|
||||
# last_health_checked_at :datetime
|
||||
# name :string not null
|
||||
# pod_yaml :jsonb
|
||||
# replicas :integer default(1)
|
||||
# service_type :integer not null
|
||||
# status :integer default("pending")
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# project_id :bigint not null
|
||||
#
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Service, type: :model do
|
||||
describe '.permitted_params' do
|
||||
it 'converts YAML text to JSON for pod_yaml' do
|
||||
yaml_text = "containers:\n - name: sidecar\n image: nginx:latest"
|
||||
params = ActionController::Parameters.new(
|
||||
service: { name: 'test-service', pod_yaml: yaml_text }
|
||||
)
|
||||
|
||||
permitted = Service.permitted_params(params)
|
||||
|
||||
expect(permitted[:pod_yaml]).to be_present
|
||||
expect(permitted[:pod_yaml]['containers']).to be_an(Array)
|
||||
expect(permitted[:pod_yaml]['containers'].first['name']).to eq('sidecar')
|
||||
expect(permitted[:pod_yaml]['containers'].first['image']).to eq('nginx:latest')
|
||||
end
|
||||
|
||||
it 'handles invalid YAML gracefully' do
|
||||
invalid_yaml = "containers:\n - invalid: ["
|
||||
params = ActionController::Parameters.new(
|
||||
service: { name: 'test-service', pod_yaml: invalid_yaml }
|
||||
)
|
||||
|
||||
allow(Rails.logger).to receive(:error)
|
||||
permitted = Service.permitted_params(params)
|
||||
|
||||
expect(Rails.logger).to have_received(:error).with(/Failed to parse pod_yaml/)
|
||||
expect(permitted[:pod_yaml]).to eq(invalid_yaml)
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user