← Browse

@chef/knife-vcenter

GitHub Copilot Instructions — knife-vcenter

instructionscopilot

Install

agr install @chef/knife-vcenter --target copilot

Writes 1 file into .github/copilot-instructions.md, pinned to git-a5b18305.

  • .github/copilot-instructions.md

Document

GitHub Copilot Instructions — knife-vcenter

Audience: GitHub Copilot CLI and Copilot coding agents working in this repository. Follow every section of these instructions precisely. When in doubt, ask the user for clarification before proceeding.


Table of Contents

  1. Project Overview
  2. Repository Structure
  3. Technology Stack
  4. File Modification Guidelines
  5. Development Workflow — Prompt-Based Protocol
  6. Jira Integration
  7. Phase 1: Initial Setup & Analysis
  8. Phase 2: Implementation
  9. Phase 3: Testing (CRITICAL)
  10. Phase 4: Pull Request Creation
  11. DCO Compliance
  12. Build System — Rake
  13. Expeditor CI/CD Integration
  14. GitHub Actions & SonarQube
  15. Label Management System
  16. Code Style & Quality Standards
  17. Ruby-Specific Guidelines
  18. Security & Compliance
  19. Code Ownership & Review Process
  20. Local Development Setup
  21. Troubleshooting
  22. Example Workflow Execution

1. Project Overview

knife-vcenter is a Chef Knife plugin that enables provisioning, management, and lifecycle operations of virtual machines on VMware vCenter directly from the command line. It is part of the Chef ecosystem and bridges Chef's knife-cloud framework with VMware's vSphere Automation SDK and RbVmomi.

PropertyValue
Gem nameknife-vcenter
Current version5.0.7
LanguageRuby >= 3.1
LicenseApache 2.0
GitHub repochef/knife-vcenter
Published toRubyGems.org
Slack notifications#sustaining-notify

Knife commands provided by this plugin:

CommandPurpose
knife vcenter vm listList all VMs in vCenter
knife vcenter vm createCreate a new VM
knife vcenter vm cloneClone a VM from a template
knife vcenter vm deleteDelete a VM
knife vcenter vm showShow details of a VM
knife vcenter cluster listList all clusters
knife vcenter datacenter listList all datacenters
knife vcenter host listList all hosts

2. Repository Structure

knife-vcenter/
├── .expeditor/                         # Chef Expeditor CI/CD automation
│   ├── config.yml                      # Expeditor pipeline configuration
│   ├── verify.pipeline.yml             # Buildkite test pipeline (Ruby 3.1/3.4, Linux/Windows)
│   ├── run_linux_tests.sh              # Linux bundle + rake runner script
│   └── update_version.sh              # Version update hook (post-merge)
│
├── .github/                            # GitHub-specific configuration
│   ├── CODEOWNERS                      # Code review ownership assignments
│   ├── copilot-instructions.md         # This file — Copilot guidelines
│   ├── dependabot.yml                  # Automated Bundler dependency updates (daily)
│   ├── ISSUE_TEMPLATE/                 # GitHub issue templates
│   └── workflows/
│       └── build.yml                   # GitHub Actions — SonarQube static analysis
│
├── lib/
│   ├── chef/knife/
│   │   ├── cloud/
│   │   │   ├── vcenter_service.rb      # Core VMware API service (vSphere REST + RbVmomi)
│   │   │   ├── vcenter_service_helpers.rb  # Mixin: service factory, SSL, validation
│   │   │   └── vcenter_service_options.rb  # Mixin: CLI option definitions
│   │   ├── vcenter_cluster_list.rb     # `knife vcenter cluster list`
│   │   ├── vcenter_datacenter_list.rb  # `knife vcenter datacenter list`
│   │   ├── vcenter_host_list.rb        # `knife vcenter host list`
│   │   ├── vcenter_vm_clone.rb         # `knife vcenter vm clone`
│   │   ├── vcenter_vm_create.rb        # `knife vcenter vm create`
│   │   ├── vcenter_vm_delete.rb        # `knife vcenter vm delete`
│   │   ├── vcenter_vm_list.rb          # `knife vcenter vm list`
│   │   └── vcenter_vm_show.rb          # `knife vcenter vm show`
│   ├── knife-vcenter/
│   │   └── version.rb                  # ⛔ AUTO-MANAGED — never edit manually
│   └── support/
│       └── clone_vm.rb                 # RbVmomi VM clone helper (low-level vSphere)
│
├── spec/
│   ├── spec_helper.rb                  # RSpec configuration and global setup
│   ├── support/
│   │   ├── shared_examples_for_command.rb              # Shared: command lifecycle
│   │   ├── shared_examples_for_command_bootstrap.rb    # Shared: bootstrap command
│   │   ├── shared_examples_for_servercreatecommand.rb  # Shared: server create
│   │   ├── shared_examples_for_serverdeletecommand.rb  # Shared: server delete
│   │   └── shared_examples_for_service.rb              # Shared: service layer
│   └── unit/
│       └── vcenter_vm_list_spec.rb     # Unit tests for VcenterVmList
│
├── CHANGELOG.md                        # ⛔ AUTO-MANAGED by Expeditor — never edit manually
├── VERSION                             # ⛔ AUTO-MANAGED by Expeditor — never edit manually
├── Gemfile                             # Gem dependency groups (test, docs, debug)
├── Gemfile.lock                        # Locked dependency versions
├── Rakefile                            # Build tasks: spec, style, docs
├── knife-vcenter.gemspec              # Gem specification and runtime dependencies
├── sonar-project.properties           # SonarQube project key config
├── LICENSE                            # Apache 2.0
├── README.md                          # User-facing documentation
├── CONTRIBUTING.md                    # Points to chef/chef contributing guide
├── CODE_OF_CONDUCT.md                 # Community standards
└── SECURITY.md                        # Security policy

3. Technology Stack

CategoryTechnologyDetails
LanguageRuby>= 3.1 required; tested on 3.1 and 3.4
Plugin frameworkknife-cloud>= 4.0 — base classes for knife plugins
Chef integrationchef gem>= 18.0
VMware REST APIvsphere-automation-sdk~> 0.4 (vSphere Automation REST API)
VMware low-levelrbvmomi>= 1.11, < 4.0 (SOAP-based vSphere API, used for cloning)
TestingRSpec~> 3.7
LintingChefstyle~> 1.0 (RuboCop-based, Chef-specific rules)
Style addonrubocop-rspec~> 2.0
Build toolRake>= 10.0
DocumentationYARDAPI documentation generator
CI/CDExpeditorChef's internal pipeline automation (Buildkite-based)
Static analysisSonarQubeVia GitHub Actions build.yml
Dependency updatesDependabotDaily Bundler updates

4. File Modification Guidelines

✅ Safe to Modify

File/DirectoryNotes
lib/chef/knife/*.rbAll knife command implementations
lib/chef/knife/cloud/*.rbService, helpers, options modules
lib/support/clone_vm.rbRbVmomi clone support
spec/**/*_spec.rbUnit test files
spec/support/*.rbShared test examples
spec/spec_helper.rbRSpec configuration
README.mdUser-facing documentation
GemfileDependency group additions (not gemspec deps)
knife-vcenter.gemspecGem metadata and runtime dependency versions
RakefileBuild task additions

⛔ Never Modify Manually

FileReason
VERSIONAuto-managed by Expeditor built_in:bump_version
lib/knife-vcenter/version.rbAuto-updated by .expeditor/update_version.sh
CHANGELOG.mdAuto-managed by Expeditor built_in:update_changelog
Gemfile.lockUpdated by Bundler — run bundle update to refresh
.github/workflows/build.ymlManaged by infrastructure team — contact @chef/build-engineering-systems-team
.expeditor/config.ymlManaged by @chef/build-engineering-systems-team
.expeditor/verify.pipeline.ymlManaged by @chef/build-engineering-systems-team
sonar-project.propertiesManaged by infrastructure team

⚠️ Restricted — Coordinate with Teams

File/DirectoryOwner
.expeditor/@chef/build-engineering-systems-team (review required)
*.md files@chef/docs-team (review required)
All other files@chef/chef-workstation-owners / @chef/chef-workstation-approvers (review required)

5. Development Workflow — Prompt-Based Protocol

All work MUST follow a prompt-based, approval-gated workflow. After every major phase:

  1. Summarize what was completed
  2. 📋 State what the next step will be
  3. Ask: "Do you want me to continue with the next step?"
  4. 📌 List remaining steps
  5. ⏸️ Wait for explicit user approval before proceeding

Never skip ahead. Each phase requires user confirmation before starting the next.


6. Jira Integration

This project uses the mcp-atlassian MCP server (configured as JiraMCP) to interact with Jira at https://progresssoftware.atlassian.net.

When a Jira ID is Provided

When the user supplies a Jira ticket ID (e.g., CHEF-32138), always:

  1. Fetch the ticket using the JiraMCP tool
  2. Read the full issue: summary, description, acceptance criteria, story points, labels, linked issues
  3. Identify the issue type (Bug, Story, Task, Sub-task)
  4. Extract implementation requirements from the description
  5. Confirm your understanding with the user before writing any code

Example prompt to user after fetching Jira ticket:

I've read CHEF-32138. Here's my understanding:
- **Summary**: [ticket summary]
- **Type**: [Bug/Story/Task]
- **Acceptance Criteria**: [list from ticket]
- **Implementation Plan**: [what I propose to do]

Does this match your expectations? Should I proceed to Phase 1?

7. Phase 1: Initial Setup & Analysis

Goal: Understand the scope of work before writing any code.

Steps

  1. Fetch Jira ticket (if ID provided) — read full description and acceptance criteria
  2. Analyze affected files — identify which lib/ files need changes
  3. Check existing tests — review spec/unit/ and spec/support/ for coverage patterns
  4. Review shared examples — understand which shared examples apply
  5. Plan implementation — list exact files to create/modify
  6. Plan test coverage — list exact spec files to create/modify

Phase 1 Completion Summary Template

✅ Phase 1 Complete — Analysis Summary

**Jira Ticket**: [ID] — [Summary]
**Files to modify**:
  - lib/chef/knife/[file].rb
  - lib/chef/knife/cloud/[file].rb

**Tests to create/update**:
  - spec/unit/[file]_spec.rb

**Implementation approach**: [brief description]

**Next step**: Phase 2 — Implementation
Do you want me to proceed with implementation?

8. Phase 2: Implementation

Goal: Write clean, well-structured Ruby code following project conventions.

Implementation Rules

  • All Ruby files MUST start with # frozen_string_literal: true
  • All Ruby files MUST include the Apache 2.0 license header:
# frozen_string_literal: true
#
# Author:: Chef Partner Engineering (<partnereng@chef.io>)
# Copyright:: Copyright (c) Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
  • New knife commands MUST include VcenterServiceOptions and implement deps for lazy loading
  • New service methods in VcenterService MUST use VSphereAutomation::VCenter::* APIs
  • Error handling MUST use raise format("message: %s", value) pattern (not string interpolation in raise)
  • All public methods MUST have YARD-style doc comments:
# Brief description of what this method does
#
# @param [Type] param_name Description of the parameter
# @return [Type] Description of the return value
def my_method(param_name)

Phase 2 Completion Summary Template

✅ Phase 2 Complete — Implementation Summary

**Files modified**:
  - lib/chef/knife/[file].rb — [what changed]
  - lib/chef/knife/cloud/vcenter_service.rb — [what changed]

**Key changes**:
  - [change 1]
  - [change 2]

**Next step**: Phase 3 — Testing (>80% coverage required)
Do you want me to proceed with test creation?

9. Phase 3: Testing (CRITICAL)

⚠️ CRITICAL HARD REQUIREMENT: >80% test coverage is non-negotiable. All implementations MUST be accompanied by comprehensive RSpec unit tests. PRs without adequate test coverage will be rejected.

Testing Framework

ToolVersionPurpose
RSpec~> 3.7Unit testing framework
Chefstyle~> 1.0Linting (must pass with no offenses)
rubocop-rspec~> 2.0RSpec-specific style rules

Test File Naming & Location

lib/chef/knife/vcenter_vm_list.rb
  → spec/unit/vcenter_vm_list_spec.rb

lib/chef/knife/cloud/vcenter_service.rb
  → spec/unit/vcenter_service_spec.rb  (create if missing)

lib/support/clone_vm.rb
  → spec/unit/clone_vm_spec.rb  (create if missing)

Required Test Coverage

Every implementation MUST test:

  • Happy path — normal successful execution
  • Error conditions — API failures, missing resources, nil values
  • Edge cases — empty arrays, nil options, boundary values
  • Input validation — missing required config values
  • All branches — every if/when/case branch must be covered
  • Mock all external dependencies — VMware APIs, network calls, filesystem

RSpec Test Structure Pattern

# frozen_string_literal: true
#
# Author:: Chef Partner Engineering (<partnereng@chef.io>)
# Copyright:: Copyright (c) Chef Software Inc.
# License:: Apache License, Version 2.0
# [... full Apache 2.0 header ...]

require "spec_helper"
require "chef/knife/vcenter_vm_example"
require "support/shared_examples_for_command"

describe Chef::Knife::Cloud::VcenterVmExample do
  # Always include the shared command lifecycle example
  it_behaves_like Chef::Knife::Cloud::Command, Chef::Knife::Cloud::VcenterVmExample.new

  subject { described_class.new }

  # Mock vCenter service to avoid real API calls
  let(:service) { instance_double(Chef::Knife::Cloud::VcenterService) }

  before do
    allow(subject).to receive(:create_service_instance).and_return(service)
  end

  describe "#method_name" do
    context "when condition is met (happy path)" do
      it "does the expected thing" do
        # Arrange
        allow(service).to receive(:list_servers).and_return([...])
        # Act & Assert
        expect(subject.method_name).to eq(expected_value)
      end
    end

    context "when an error occurs" do
      it "raises an appropriate error" do
        allow(service).to receive(:list_servers).and_raise(StandardError, "API error")
        expect { subject.method_name }.to raise_error(StandardError, /API error/)
      end
    end

    context "when input is nil" do
      it "handles nil gracefully" do
        expect(subject.method_name(nil)).to be_nil  # or raise, depending on contract
      end
    end

    context "when result is empty" do
      it "returns empty collection" do
        allow(service).to receive(:list_servers).and_return([])
        expect(subject.method_name).to eq([])
      end
    end
  end
end

Shared Examples Usage

Always reuse existing shared examples where applicable:

# Test the standard knife command lifecycle (set_default_config, validate!, etc.)
it_behaves_like Chef::Knife::Cloud::Command, Chef::Knife::Cloud::YourCommand.new

# For commands that create servers
it_behaves_like "a server create command"

# For commands that delete servers
it_behaves_like "a server delete command"

Mocking VMware SDK Objects

# Mock VSphereAutomation API responses
let(:vm_api) { instance_double(VSphereAutomation::VCenter::VMApi) }
let(:vm_summary) do
  instance_double(
    VSphereAutomation::VCenter::VcenterVMSummary,
    vm: "vm-123",
    name: "test-vm",
    power_state: "POWERED_ON",
    cpu_count: 2,
    memory_size_MiB: 4096
  )
end

before do
  allow(VSphereAutomation::VCenter::VMApi).to receive(:new).and_return(vm_api)
  allow(vm_api).to receive(:list).and_return(double(value: [vm_summary]))
end

Running Tests

# Run all tests (specs + style) — this is the CI equivalent
bundle exec rake

# Run only RSpec unit tests
bundle exec rake spec

# Run only Chefstyle linting (must have zero offenses)
bundle exec rake style

# Run a specific spec file
bundle exec rspec spec/unit/vcenter_vm_list_spec.rb

# Run with verbose output
bundle exec rspec spec/unit/vcenter_vm_list_spec.rb --format documentation

# Run tests matching a description pattern
bundle exec rspec spec/ -e "format_power_status"

# Run with coverage report (add simplecov if needed)
bundle exec rspec spec/ --format progress

⚠️ >80% test coverage is a HARD REQUIREMENT. Run all tests before submitting a PR. Both bundle exec rake spec AND bundle exec rake style must pass with zero errors or failures.

Phase 3 Completion Summary Template

✅ Phase 3 Complete — Testing Summary

**Test files created/modified**:
  - spec/unit/[file]_spec.rb — [N] examples added

**Test results**:
  - bundle exec rake spec: ✅ [N] examples, 0 failures
  - bundle exec rake style: ✅ 0 offenses

**Coverage**: [N]% (meets >80% requirement ✅)

**Scenarios covered**:
  - ✅ Happy path
  - ✅ Error conditions ([list])
  - ✅ Edge cases ([list])
  - ✅ All branches covered

**Next step**: Phase 4 — Pull Request Creation
Do you want me to proceed with creating the PR?

10. Phase 4: Pull Request Creation

Branch Naming

Use the Jira ID as the branch name:

git checkout -b CHEF-32138

Commit with DCO Signoff (REQUIRED)

ALL commits MUST include --signoff. Builds WILL FAIL without it. See DCO Compliance.

# Stage all changes
git add .

# Commit with DCO signoff and descriptive message
git commit --signoff -m "CHEF-32138: Brief description of the change"

# Push branch to remote
git push origin CHEF-32138

Create PR with GH CLI

gh pr create \
  --title "CHEF-32138: Brief description of the change" \
  --body "$(cat <<'EOF'
<h2>Summary</h2>
<p>Brief description of what this PR does and why.</p>

<h2>Jira Ticket</h2>
<p><a href="https://progresssoftware.atlassian.net/browse/CHEF-32138">CHEF-32138</a> — [Ticket Summary]</p>

<h2>Changes Made</h2>
<ul>
  <li>Added <code>method_name</code> to <code>VcenterService</code> for [purpose]</li>
  <li>Implemented <code>knife vcenter [command]</code> command</li>
  <li>Added unit tests for all new functionality</li>
</ul>

<h2>Files Modified</h2>
<ul>
  <li><code>lib/chef/knife/vcenter_example.rb</code> — [what changed]</li>
  <li><code>lib/chef/knife/cloud/vcenter_service.rb</code> — [what changed]</li>
  <li><code>spec/unit/vcenter_example_spec.rb</code> — [N] new test examples</li>
</ul>

<h2>Testing</h2>
<ul>
  <li>✅ <code>bundle exec rake spec</code> — [N] examples, 0 failures</li>
  <li>✅ <code>bundle exec rake style</code> — 0 offenses</li>
  <li>✅ Coverage: [N]% (exceeds 80% requirement)</li>
</ul>

<h2>Test Scenarios Covered</h2>
<ul>
  <li>Happy path: [description]</li>
  <li>Error handling: [description]</li>
  <li>Edge cases: [description]</li>
</ul>
EOF
)" \
  --label "Type: Enhancement" \
  --label "Aspect: Testing"

Label Selection for PRs

See Label Management System for the complete decision matrix.

Phase 4 Completion Summary Template

✅ Phase 4 Complete — Pull Request Created

**Branch**: CHEF-32138
**PR URL**: https://github.com/chef/knife-vcenter/pull/[N]
**Title**: "CHEF-32138: [description]"
**Labels applied**: [list]

**All checks**:
  - ✅ DCO signoff on all commits
  - ✅ Tests passing (>80% coverage)
  - ✅ Chefstyle: 0 offenses
  - ✅ PR description in HTML format
  - ✅ Jira ticket linked

🎉 Task complete!

11. DCO Compliance

CRITICAL: Every single commit MUST be signed off. CI pipelines will fail without it.

The Developer Certificate of Origin (DCO) certifies that you wrote the code and have the right to submit it.

Signing Off Commits

# Standard commit with signoff
git commit --signoff -m "CHEF-32138: Add feature X"

# Short form equivalent
git commit -s -m "CHEF-32138: Add feature X"

This adds a Signed-off-by: Your Name <your@email.com> trailer to every commit.

Fix Commits Without Signoff

# Amend the most recent commit to add signoff
git commit --amend --signoff --no-edit

# Force push (only on feature branches, never main)
git push origin CHEF-32138 --force-with-lease

Fix Multiple Commits Without Signoff

# Interactive rebase to fix multiple commits
git rebase --signoff HEAD~N  # Replace N with number of commits

# Or exec across all commits
git rebase HEAD~N --exec 'git commit --amend --no-edit --signoff'

Verify Signoff

git log --oneline -5
# Each commit should show: CHEF-32138: description
# git show HEAD should contain: Signed-off-by: ...

12. Build System — Rake

The default Rake task runs both specs and style checks — this is what CI runs.

Available Rake Tasks

CommandDescription
bundle exec rakeDefault: runs spec + style (equivalent to CI)
bundle exec rake specRun all RSpec unit tests
bundle exec rake styleRun Chefstyle (RuboCop) linting — must have 0 offenses
bundle exec rake docsGenerate YARD documentation
bundle exec rake buildBuild the gem (from Bundler gem tasks)
bundle exec rake releaseRelease the gem (Expeditor handles this automatically)

Running in CI Mode (Linux equivalent)

# Install dependencies (mirrors .expeditor/run_linux_tests.sh)
bundle config --local path vendor/bundle
bundle install --jobs=7 --retry=3

# Run full test suite
bundle exec rake

Dependency Installation

# Install all gem groups
bundle install

# Install without development tools (mirrors Windows CI)
bundle config set --local without docs debug
bundle install --jobs=7 --retry=3

13. Expeditor CI/CD Integration

Expeditor is Chef's internal pipeline automation tool that runs on Buildkite. It triggers on PR merges and manages the release process.

Verify Pipeline

The verify pipeline (.expeditor/verify.pipeline.yml) runs on every PR with:

StepPlatformRuby Version
run-lint-and-specs-ruby-3.1Linux (Docker: ruby:3.1-buster)3.1
run-lint-and-specs-ruby-3.4Linux (Docker: ruby:3.4-buster)3.4
run-specs-windowsWindows (rubydistros/windows-2019:3.1)3.1
run-specs-windows-3.4Windows (rubydistros/windows-2019:3.4)3.4

All steps run bundle exec rake (spec + style).

Post-Merge Automation

When a PR merges to the release branch, Expeditor automatically:

  1. Bumps the version (built_in:bump_version) → updates VERSION and lib/knife-vcenter/version.rb
  2. Updates CHANGELOG (built_in:update_changelog) → adds PR title to CHANGELOG.md
  3. Builds the gem (built_in:build_gem) → creates .gem artifact
  4. On promotion: publishes to RubyGems (built_in:publish_rubygems)

Expeditor Skip Labels

Use these labels on PRs to control which Expeditor actions run:

LabelEffectWhen to Use
Expeditor: Skip AllSkips ALL merge actionsInfrastructure/config-only changes with no release needed
Expeditor: Skip Version BumpSkips built_in:bump_versionDocumentation-only changes, typo fixes
Expeditor: Skip ChangelogSkips built_in:update_changelogInternal changes not worth a changelog entry
Expeditor: Skip HabitatSkips Habitat package buildChanges not affecting Habitat packaging
Expeditor: Skip OmnibusSkips Omnibus build triggerChanges not affecting Omnibus packaging
Expeditor: Bump Version MinorBumps minor version (X.Y+1.0)New features, non-breaking enhancements
Expeditor: Bump Version MajorBumps major version (X+1.0.0)Breaking changes, major API changes

Default behavior (no skip labels): patch version bump + changelog update + gem build.

Expeditor Skip Label Decision Matrix

Change type                          → Recommended labels
─────────────────────────────────────────────────────────
Documentation only (README, *.md)   → Expeditor: Skip Version Bump, Expeditor: Skip Changelog
                                       (or Expeditor: Skip All if purely cosmetic)

Bug fix                              → (no skip labels) — patch bump, changelog entry

New feature / enhancement           → Expeditor: Bump Version Minor

Breaking change / major API change  → Expeditor: Bump Version Major

Test-only changes                   → Expeditor: Skip Version Bump (tests don't warrant a release)
                                       (keep changelog entry)

CI/build config only                → Expeditor: Skip All

Dependency update (Dependabot PR)   → (no skip labels usually — let Dependabot handle)

Chore / tech debt (no user impact)  → Expeditor: Skip Version Bump, Expeditor: Skip Changelog

Slack Notifications

Build failures are posted to the #sustaining-notify Slack channel.


14. GitHub Actions & SonarQube

The .github/workflows/build.yml workflow runs on:

  • Push to main, develop, or release/** branches
  • Pull request opened, synchronized, or reopened

It performs SonarQube static analysis using secrets SONAR_TOKEN and SONAR_HOST_URL. The project key is chef_knife-vcenter_AYckW3CSJ4YHsO5MtJTz (see sonar-project.properties).

Note: Do not modify build.yml without consulting @chef/build-engineering-systems-team.


15. Label Management System

Type Labels (What kind of change)

LabelWhen to Use
Type: BugFixes something that doesn't work as expected
Type: EnhancementAdds new functionality
Type: RegressionFixes something that used to work
Type: Breaking ChangeChanges existing behavior in a user-visible way
Type: ChoreNon-critical maintenance (dependency updates, minor refactors)
Type: DeprecationMarks features for removal
Type: Tech DebtRefactoring without behavior change
Type: Design ProposalCommunity discussion of a proposed approach

Aspect Labels (What area is affected)

LabelWhen to Use
Aspect: IntegrationChanges to vCenter API interaction
Aspect: SecuritySecurity-related changes
Aspect: TestingTest-only changes or testing improvements
Aspect: DocumentationDocumentation changes
Aspect: PerformancePerformance improvements
Aspect: PortabilityCross-platform compatibility fixes
Aspect: PackagingGem packaging changes
Aspect: StabilityReliability improvements
Aspect: UICLI output/formatting changes
Aspect: UXUser experience improvements

Platform Labels

LabelWhen to Use
Platform: VMwarevCenter/vSphere-specific behavior
Platform: WindowsWindows-specific fixes
Platform: LinuxLinux-specific fixes
Platform: macOSmacOS-specific fixes

Priority Labels

LabelWhen to Use
Priority: CriticalBlocks users, security issue, data loss
Priority: MediumSignificant impact, workaround exists
Priority: LowMinor issue, cosmetic

Status Labels

LabelMeaning
Status: AdoptedPR is being actively worked on
Status: IncompletePR not ready to merge
Status: Waiting on ContributorPending author action
Status: Good First IssueSuitable for new contributors
Status: Help WantedNeeds community help
Status: Sustaining BacklogQueued for sustaining engineering
Status: UntriagedNot yet reviewed

PR Label Decision Matrix

Scenario                              → Type label         + Aspect label(s)
──────────────────────────────────────────────────────────────────────────────
New knife command                     → Type: Enhancement  + Aspect: Integration
Bug fix in API interaction            → Type: Bug          + Aspect: Integration
Fix Windows-specific crash            → Type: Bug          + Platform: Windows
Add/improve unit tests only          → Type: Chore        + Aspect: Testing
Update README                         → Type: Chore        + Aspect: Documentation
Performance improvement               → Type: Enhancement  + Aspect: Performance
Dependency version update             → Type: Chore        + dependencies
Breaking API change                   → Type: Breaking Change + Aspect: Integration
Security vulnerability fix            → Type: Bug          + Aspect: Security + Priority: Critical
Remove deprecated feature             → Type: Deprecation  + Aspect: Integration

16. Code Style & Quality Standards

Chefstyle (RuboCop)

This project uses Chefstyle (~> 1.0), a Chef-specific RuboCop configuration. It must produce zero offenses before a PR is merged.

# Check style
bundle exec rake style

# Auto-fix safe offenses
bundle exec rubocop --auto-correct

# Check a specific file
bundle exec rubocop lib/chef/knife/vcenter_vm_list.rb

Key Style Rules

  • # frozen_string_literal: true at top of every Ruby file
  • Use format("string: %s", value) instead of "string: #{value}" in error messages
  • Use raise not fail
  • Two-space indentation
  • No trailing whitespace
  • do...end for multi-line blocks, { } for single-line blocks
  • Avoid unless with else — use if
  • Use attr_reader, attr_writer, attr_accessor appropriately
  • private methods at the bottom of the class

YARD Documentation

All public methods must have YARD doc comments:

# Gets the datastore by name from vCenter
#
# @param [String] name The name of the datastore to find
# @return [String] The datastore ID
# @raise [RuntimeError] If the datastore cannot be found
def get_datastore(name)

17. Ruby-Specific Guidelines

Class Structure Pattern

New knife commands follow this pattern:

# frozen_string_literal: true
# [Apache 2.0 header]

require "chef/knife"
require "chef/knife/cloud/server/list_command"   # or appropriate base class
require_relative "cloud/vcenter_service_options"

class Chef
  class Knife
    class Cloud
      class VcenterVmExample < Chef::Knife::Cloud::ServerListCommand
        include VcenterServiceOptions

        banner "knife vcenter vm example"

        # Lazy-load VMware deps — only loaded when command runs
        deps do
          require_relative "cloud/vcenter_service"
          include VcenterServiceHelpers
        end

        # @param [Object] options override options
        def before_exec_command
          @columns_with_info = [
            { label: "ID", key: "vm" },
            # ...
          ]
          @sort_by_field = "name"
        end
      end
    end
  end
end

Error Handling Pattern

# Use format() for error messages — not string interpolation
raise format("Unable to find resource: %s", name)

# Use ui.error for user-facing errors before exit
ui.error(format("Missing required parameters: %s", missing.join(", ")))
exit(1)

VMware SDK Usage Patterns

# REST API pattern (vsphere-automation-sdk)
vm_api = VSphereAutomation::VCenter::VMApi.new(api_client)
result = vm_api.list.value                          # Returns array
result = vm_api.list({ filter_names: name }).value  # Filtered

# RbVmomi pattern (SOAP API, used in clone_vm.rb)
vim = RbVmomi::VIM.connect(conn_opts)
dc = vim.serviceInstance.find_datacenter(datacenter_name)
vm = dc.find_vm(vm_name)

Bundler & Gem Management

# Install dependencies
bundle install

# Add a new runtime dependency (edit gemspec, then:)
bundle install

# Update a specific gem
bundle update gem-name

# Check outdated gems
bundle outdated

18. Security & Compliance

Apache 2.0 License Header

Every Ruby source file MUST include the full Apache 2.0 license header (see Phase 2: Implementation for the exact text). This is enforced by Chefstyle.

SSL Verification

  • SSL verification is enabled by default — never disable it in code without explicit user opt-in
  • The --vcenter-disable-ssl-verify flag is provided for development environments only
  • Log a warning when SSL is disabled: Base.log.warn("SSL Verification is turned OFF")

Credentials Handling

  • Never hardcode credentials (usernames, passwords, API tokens) in source files
  • Credentials are passed via CLI options (--vcenter-username, --vcenter-password)
  • No credentials should appear in test fixtures — use mocks

CVE Awareness

  • Monitor RubyGems advisories for runtime dependencies: rbvmomi, vsphere-automation-sdk, knife-cloud, chef
  • Dependabot is configured to open daily PRs for Bundler updates — review and merge promptly
  • Security-related PRs should be labeled Aspect: Security and Priority: Critical

SonarQube

SonarQube scans run on every PR and push to main/develop/release branches. Address any security hotspots or vulnerabilities flagged before merging.


19. Code Ownership & Review Process

CODEOWNERS

*                  @chef/chef-workstation-owners @chef/chef-workstation-approvers @chef/chef-workstation-reviewers
.expeditor/        @chef/build-engineering-systems-team
*.md               @chef/docs-team

Note: Last matching pattern takes precedence (as noted in CODEOWNERS).

Review Requirements

Change areaRequired reviewers
lib/**/*.rb@chef/chef-workstation-owners or @chef/chef-workstation-approvers (1 approval)
spec/**/*.rb@chef/chef-workstation-owners or @chef/chef-workstation-approvers (1 approval)
.expeditor/**@chef/build-engineering-systems-team (required)
*.md, README.md@chef/docs-team (required)
knife-vcenter.gemspec@chef/chef-workstation-owners or @chef/chef-workstation-approvers (1 approval)
Security changes@chef/chef-workstation-owners + Priority: Critical label

Review Checklist

Before requesting review, verify:

  • All tests pass: bundle exec rake
  • Chefstyle: 0 offenses: bundle exec rake style
  • All commits have DCO signoff
  • PR description is HTML-formatted with Jira link
  • Appropriate labels applied
  • Expeditor skip labels applied where appropriate
  • Coverage > 80%

20. Local Development Setup

Prerequisites

  • Ruby >= 3.1 (use rbenv or rvm to manage Ruby versions)
  • Bundler >= 2.0
  • Git
  • GH CLI (gh) for PR operations

Setup Steps

# 1. Clone the repository
git clone https://github.com/chef/knife-vcenter.git
cd knife-vcenter

# 2. Install dependencies
bundle install

# 3. Verify setup — run full test suite
bundle exec rake

# 4. You should see: [N] examples, 0 failures, 0 offenses

Ruby Version Management

# Check current Ruby version (must be >= 3.1)
ruby --version

# With rbenv
rbenv install 3.4.0
rbenv local 3.4.0

# With rvm
rvm install 3.4.0
rvm use 3.4.0

Environment Variables (for manual testing against real vCenter)

export VCENTER_HOST="your-vcenter-host.example.com"
export VCENTER_USERNAME="administrator@vsphere.local"
export VCENTER_PASSWORD="your-password"

IDE Configuration

For VS Code, recommended extensions:

  • Shopify.ruby-lsp — Ruby LSP for code intelligence
  • misogi.ruby-rubocop — RuboCop integration
  • castwide.solargraph — Ruby language server

21. Troubleshooting

Common Issues

bundle install fails with native extension errors

# On macOS, ensure Xcode command line tools are installed
xcode-select --install

# For rbvmomi, you may need
brew install libxml2

rake style reports offenses

# View detailed offense info
bundle exec rubocop --display-cop-names lib/

# Auto-fix safe offenses
bundle exec rubocop --auto-correct lib/

# If `frozen_string_literal` is missing from new files, add it manually

RSpec tests failing with LoadError

# Ensure all dependencies are installed
bundle install

# Check if chef/knife is available
bundle exec ruby -e "require 'chef/knife'; puts 'OK'"

Chef::Config.reset errors in specs

Ensure spec_helper.rb is required at the top of every spec file:

require "spec_helper"

DCO check failing on PR

# Fix with amend (single commit)
git commit --amend --signoff --no-edit
git push origin CHEF-XXXXX --force-with-lease

# Fix multiple commits
git rebase HEAD~N --exec 'git commit --amend --no-edit --signoff'
git push origin CHEF-XXXXX --force-with-lease

SSL verification errors in development

Use --vcenter-disable-ssl-verify flag for self-signed certs in dev environments only.


22. Example Workflow Execution

Complete Example: Adding a New Knife Command

Here is a full example showing the interaction pattern for adding knife vcenter vm snapshot list:


User: Implement CHEF-99999 — add knife vcenter vm snapshot list command

Copilot (Phase 1):

I'll fetch the Jira ticket now...

✅ Phase 1 Complete — Analysis Summary

Jira Ticket: CHEF-99999 — Add knife vcenter vm snapshot list command Files to create:

  • lib/chef/knife/vcenter_vm_snapshot_list.rb
  • spec/unit/vcenter_vm_snapshot_list_spec.rb

Files to modify:

  • lib/chef/knife/cloud/vcenter_service.rb — add list_snapshots(vm_name) method

Implementation approach: Use VSphereAutomation::VCenter::VmSnapshotApi to list snapshots for a given VM, following the same pattern as vcenter_vm_list.rb.

Next step: Phase 2 — Implementation Do you want me to proceed with implementation?


User: Yes, proceed.

Copilot (Phase 2):

[implements files]

✅ Phase 2 Complete — Implementation Summary

Files created/modified: [list]

Next step: Phase 3 — Testing (>80% coverage required) Do you want me to proceed with test creation?


User: Yes.

Copilot (Phase 3):

[writes comprehensive RSpec tests]

✅ Phase 3 Complete — Testing Summary

  • bundle exec rake spec: ✅ 18 examples, 0 failures
  • bundle exec rake style: ✅ 0 offenses
  • Coverage: 94% ✅

Next step: Phase 4 — Pull Request Creation Do you want me to create the PR?


User: Yes.

Copilot (Phase 4):

git checkout -b CHEF-99999
git add .
git commit --signoff -m "CHEF-99999: Add knife vcenter vm snapshot list command"
git push origin CHEF-99999
gh pr create --title "CHEF-99999: Add knife vcenter vm snapshot list command" \
  --body "[HTML body with Jira link, changes, test results]" \
  --label "Type: Enhancement" \
  --label "Aspect: Integration"

✅ Phase 4 Complete — PR Created

PR: https://github.com/chef/knife-vcenter/pull/NNN

🎉 Task complete!


These instructions are maintained by @chef/chef-workstation-owners. For questions, reach out in #sustaining-notify.

Trust

Not scanned yet. Artifacts are graded after they are crawled, so a recently discovered one may have no result for a while.

Versions

  • git-a5b18305a2d02026-08-04