diff --git a/.kiro/specs/applescript-calendar-sync/design.md b/.kiro/specs/applescript-calendar-sync/design.md new file mode 100644 index 0000000..c302a2f --- /dev/null +++ b/.kiro/specs/applescript-calendar-sync/design.md @@ -0,0 +1,209 @@ +# Design Document + +## Overview + +The AppleScript Calendar Sync system is designed as a standalone AppleScript application that synchronizes calendar events between two calendar accounts for the current day only. The system uses macOS Calendar app's AppleScript interface to read events from a source calendar and mirror them to a destination calendar, including removal of events that no longer exist in the source. + +## Architecture + +The system follows a simple pipeline architecture: + +``` +[Source Calendar] → [Event Reader] → [Event Processor] → [Destination Calendar] + ↓ + [Duplicate Detector] + ↓ + [Cleanup Manager] +``` + +### Core Components + +1. **Calendar Manager**: Handles calendar account and calendar selection/validation +2. **Event Reader**: Retrieves events from source calendar for current day +3. **Event Processor**: Processes and transforms events for destination calendar +4. **Sync Engine**: Coordinates the synchronization process including cleanup +5. **Logger**: Provides user feedback and error reporting + +## Components and Interfaces + +### Calendar Manager +```applescript +-- Validates and retrieves calendar references +on getCalendar(accountName, calendarName) +on validateCalendarAccess(calendar) +on listAvailableCalendars() +``` + +**Responsibilities:** +- Validate calendar account and calendar names exist +- Return calendar object references for AppleScript operations +- Handle calendar access permissions and errors + +### Event Reader +```applescript +-- Reads events from source calendar for current day +on getEventsForToday(sourceCalendar) +on parseEventProperties(event) +``` + +**Responsibilities:** +- Query source calendar for events occurring on current date +- Extract event properties (title, start time, end time, description, etc.) +- Handle different event types (all-day, timed, recurring) + +### Event Processor +```applescript +-- Processes events for destination calendar +on createEventInDestination(eventData, destinationCalendar) +on updateExistingEvent(existingEvent, newEventData) +on compareEvents(event1, event2) +``` + +**Responsibilities:** +- Create new events in destination calendar +- Update modified events +- Compare events for duplicate detection + +### Sync Engine +```applescript +-- Main synchronization coordinator +on performSync(sourceCalendar, destinationCalendar) +on cleanupRemovedEvents(sourceEvents, destinationEvents, destinationCalendar) +on generateSyncReport(results) +``` + +**Responsibilities:** +- Coordinate the entire sync process +- Manage event cleanup (removal of events not in source) +- Generate sync reports and statistics + +### Logger +```applescript +-- Logging and user feedback +on logMessage(message, level) +on displayProgress(current, total) +on showSyncSummary(summary) +``` + +**Responsibilities:** +- Display progress information to user +- Log errors and warnings +- Show final sync summary + +## Data Models + +### Event Data Structure +```applescript +record EventData + title: string + startDate: date + endDate: date + isAllDay: boolean + description: string + location: string + uid: string (for duplicate detection) +end record +``` + +### Sync Result Structure +```applescript +record SyncResult + eventsCreated: integer + eventsUpdated: integer + eventsRemoved: integer + eventsSkipped: integer + errors: list of strings +end record +``` + +## Error Handling + +### Error Categories +1. **Calendar Access Errors**: Invalid calendar names, permission issues +2. **Event Processing Errors**: Malformed events, property access failures +3. **Sync Operation Errors**: Network issues, calendar service unavailable + +### Error Handling Strategy +- Graceful degradation: Continue processing other events when individual events fail +- Detailed error logging with specific error messages +- User-friendly error reporting with suggested solutions +- Rollback capability for critical failures + +### Error Recovery +```applescript +on handleCalendarError(errorMessage) + -- Log error details + -- Provide user-friendly error message + -- Suggest corrective actions +end handleCalendarError +``` + +## Testing Strategy + +### Unit Testing Approach +Since AppleScript has limited testing frameworks, testing will focus on: + +1. **Manual Testing Scenarios**: + - Test with empty source calendar + - Test with events spanning multiple days + - Test with all-day events + - Test with recurring events + - Test calendar access errors + +2. **Integration Testing**: + - Test full sync workflow with real calendar data + - Test cleanup functionality (event removal) + - Test duplicate detection accuracy + - Test error handling with invalid inputs + +3. **Edge Case Testing**: + - Very long event titles and descriptions + - Events with special characters + - Overlapping events + - Events created/modified during sync + +### Test Data Requirements +- Test calendars with known event sets +- Events with various properties (all-day, timed, recurring) +- Events with special characters and long descriptions +- Calendar accounts with different permission levels + +## Implementation Considerations + +### AppleScript Calendar Integration +- Use `Calendar` application's AppleScript dictionary +- Handle calendar app launch and focus management +- Manage calendar selection and event creation timing + +### Performance Optimization +- Batch event operations where possible +- Minimize calendar app UI interactions +- Cache calendar references to avoid repeated lookups + +### User Experience +- Provide clear progress indicators +- Show meaningful error messages +- Allow user to cancel long-running operations +- Display comprehensive sync results + +### Security and Privacy +- Request calendar access permissions appropriately +- Handle sensitive calendar data securely +- Provide clear information about what data is accessed + +## Configuration Management + +### User Configuration +```applescript +-- Configuration properties +property sourceAccountName : "Work Account" +property sourceCalendarName : "Main Calendar" +property destinationAccountName : "Personal Account" +property destinationCalendarName : "Synced Events" +property enableLogging : true +``` + +### Runtime Configuration +- Allow users to modify calendar names without editing script +- Provide configuration validation before sync starts +- Save user preferences for repeated use \ No newline at end of file diff --git a/.kiro/specs/applescript-calendar-sync/requirements.md b/.kiro/specs/applescript-calendar-sync/requirements.md new file mode 100644 index 0000000..cdd3a65 --- /dev/null +++ b/.kiro/specs/applescript-calendar-sync/requirements.md @@ -0,0 +1,73 @@ +# Requirements Document + +## Introduction + +This feature enables automatic synchronization of calendar entries between two different calendar accounts using AppleScript. The system will copy events from a source calendar account to a destination calendar account, maintaining event details while avoiding duplicates and providing configurable sync options. + +## Requirements + +### Requirement 1 + +**User Story:** As a user with multiple calendar accounts, I want to sync events from one account to another, so that I can maintain consistent scheduling across different calendar systems. + +#### Acceptance Criteria + +1. WHEN the sync script is executed THEN the system SHALL read all events from the specified source calendar +2. WHEN events are found in the source calendar THEN the system SHALL copy them to the specified destination calendar +3. WHEN copying events THEN the system SHALL preserve event title, date, time, duration, and description +4. IF an event already exists in the destination calendar THEN the system SHALL skip creating a duplicate + +### Requirement 2 + +**User Story:** As a user, I want to configure which calendars to sync between, so that I can control the data flow between my accounts. + +#### Acceptance Criteria + +1. WHEN configuring the sync THEN the system SHALL allow selection of source calendar account and specific calendar +2. WHEN configuring the sync THEN the system SHALL allow selection of destination calendar account and specific calendar +3. WHEN invalid calendar names are provided THEN the system SHALL display an error message and exit gracefully +4. WHEN calendar accounts are not accessible THEN the system SHALL provide clear error messaging + +### Requirement 3 + +**User Story:** As a user, I want the sync to focus on today's events only, so that I maintain current day synchronization without overwhelming the destination calendar. + +#### Acceptance Criteria + +1. WHEN the sync runs THEN the system SHALL only process events occurring on the current day +2. WHEN determining current day THEN the system SHALL use the local system date +3. WHEN events span multiple days THEN the system SHALL include events that start or occur on the current day +4. WHEN no events exist for the current day THEN the system SHALL complete successfully with appropriate messaging + +### Requirement 4 + +**User Story:** As a user, I want the destination calendar to mirror the source calendar for the current day, so that removed events are also cleaned up automatically. + +#### Acceptance Criteria + +1. WHEN checking for duplicates THEN the system SHALL compare event title, start date, and start time +2. WHEN a matching event is found in the destination THEN the system SHALL skip creating the duplicate +3. WHEN an event exists in the destination but not in the source for the current day THEN the system SHALL remove it from the destination +4. WHEN an event has been modified in the source THEN the system SHALL update the corresponding event in the destination + +### Requirement 5 + +**User Story:** As a user, I want to see progress and results of the sync operation, so that I can verify the synchronization was successful. + +#### Acceptance Criteria + +1. WHEN the sync starts THEN the system SHALL display the source and destination calendar information +2. WHEN processing events THEN the system SHALL show progress indicators for each event processed +3. WHEN the sync completes THEN the system SHALL display a summary of events copied, skipped, and any errors +4. WHEN errors occur THEN the system SHALL log detailed error information for troubleshooting + +### Requirement 6 + +**User Story:** As a user, I want the sync to handle different event types and properties, so that all my calendar data is accurately transferred. + +#### Acceptance Criteria + +1. WHEN syncing events THEN the system SHALL handle all-day events correctly +2. WHEN syncing events THEN the system SHALL preserve recurring event patterns when possible +3. WHEN syncing events THEN the system SHALL handle events with attendees and meeting details +4. WHEN event properties cannot be transferred THEN the system SHALL log which properties were skipped \ No newline at end of file diff --git a/.kiro/specs/applescript-calendar-sync/tasks.md b/.kiro/specs/applescript-calendar-sync/tasks.md new file mode 100644 index 0000000..8fc43ef --- /dev/null +++ b/.kiro/specs/applescript-calendar-sync/tasks.md @@ -0,0 +1,125 @@ +# Implementation Plan + +- [x] 1. Set up project structure and configuration + - Create main AppleScript file with basic structure and configuration properties + - Define configuration properties for source and destination calendars + - Set up logging and error handling framework + - _Requirements: 2.1, 2.2, 5.1_ + +- [ ] 2. Implement Calendar Manager component + - [ ] 2.1 Create calendar validation and access functions + - Write functions to validate calendar account and calendar names exist + - Implement calendar object retrieval with error handling + - Create function to list available calendars for debugging + - _Requirements: 2.1, 2.2, 2.3, 2.4_ + + - [ ]* 2.2 Write unit tests for calendar access + - Create test scenarios for invalid calendar names + - Test calendar access permission handling + - _Requirements: 2.3, 2.4_ + +- [ ] 3. Implement Event Reader component + - [ ] 3.1 Create current day event retrieval function + - Write function to get today's date and create date range + - Implement event query for current day from source calendar + - Handle different event types (all-day, timed events) + - _Requirements: 1.1, 3.1, 3.2, 3.3_ + + - [ ] 3.2 Implement event property extraction + - Create function to extract event title, dates, description, location + - Handle event property access errors gracefully + - Parse recurring events for current day occurrences + - _Requirements: 1.3, 6.1, 6.2, 6.3_ + + - [ ]* 3.3 Write tests for event reading functionality + - Test event retrieval with various event types + - Test property extraction accuracy + - _Requirements: 1.1, 1.3_ + +- [ ] 4. Implement Event Processor component + - [ ] 4.1 Create event comparison and duplicate detection + - Write function to compare events by title, start date, and start time + - Implement duplicate detection logic for existing events + - Handle event matching edge cases + - _Requirements: 4.1, 4.2_ + + - [ ] 4.2 Implement event creation and update functions + - Create function to add new events to destination calendar + - Implement event update functionality for modified events + - Handle event creation errors and property limitations + - _Requirements: 1.2, 1.3, 4.4, 6.4_ + + - [ ]* 4.3 Write tests for event processing + - Test duplicate detection accuracy + - Test event creation with various properties + - _Requirements: 4.1, 4.2, 4.4_ + +- [ ] 5. Implement Sync Engine component + - [ ] 5.1 Create main synchronization workflow + - Implement the main sync function that coordinates all components + - Add progress tracking and user feedback during sync + - Handle sync workflow errors and recovery + - _Requirements: 1.1, 1.2, 5.2, 5.3_ + + - [ ] 5.2 Implement cleanup functionality for removed events + - Create function to identify events in destination not in source + - Implement event removal from destination calendar + - Add safety checks to prevent accidental deletions + - _Requirements: 4.3_ + + - [ ] 5.3 Create sync reporting and statistics + - Implement sync result tracking (created, updated, removed, skipped) + - Create summary display function with detailed results + - Add error reporting and logging + - _Requirements: 5.3, 5.4_ + + - [ ]* 5.4 Write integration tests for sync engine + - Test complete sync workflow with test data + - Test cleanup functionality accuracy + - Test error handling and recovery + - _Requirements: 4.3, 5.3_ + +- [ ] 6. Implement Logger component + - [ ] 6.1 Create logging and progress display functions + - Implement message logging with different severity levels + - Create progress indicator for sync operations + - Add user-friendly error message formatting + - _Requirements: 5.1, 5.2, 5.4_ + + - [ ] 6.2 Implement sync summary display + - Create formatted summary of sync results + - Display statistics for events processed + - Show any errors or warnings encountered + - _Requirements: 5.3, 5.4_ + +- [ ] 7. Integrate all components and create main script + - [ ] 7.1 Wire together all components in main execution flow + - Create main script entry point that calls all components + - Implement proper error handling and user feedback flow + - Add configuration validation before sync starts + - _Requirements: 2.3, 2.4, 5.1_ + + - [ ] 7.2 Add user interaction and configuration management + - Implement user prompts for calendar selection if needed + - Add configuration validation and error messaging + - Create user-friendly script execution experience + - _Requirements: 2.1, 2.2, 2.3, 2.4_ + + - [ ]* 7.3 Create comprehensive end-to-end tests + - Test complete sync workflow with real calendar data + - Test all error scenarios and edge cases + - Validate sync accuracy and cleanup functionality + - _Requirements: 1.1, 1.2, 4.3, 5.3_ + +- [ ] 8. Finalize and optimize the script + - [ ] 8.1 Add performance optimizations and error recovery + - Optimize calendar access and event processing performance + - Add robust error recovery and rollback capabilities + - Implement proper resource cleanup and calendar app management + - _Requirements: 5.4_ + + - [ ] 8.2 Create user documentation and usage instructions + - Write clear instructions for script configuration and usage + - Document calendar permission requirements + - Create troubleshooting guide for common issues + - _Requirements: 2.3, 2.4, 5.4_ \ No newline at end of file diff --git a/.kiro/specs/fastpass-additional-control-plane/design.md b/.kiro/specs/fastpass-additional-control-plane/design.md new file mode 100644 index 0000000..5aaa6b9 --- /dev/null +++ b/.kiro/specs/fastpass-additional-control-plane/design.md @@ -0,0 +1,165 @@ +# Design Document + +## Overview + +The `fastpass-additional-control-plane` Ansible role will enable the deployment of additional control plane nodes to an existing FastPass Kubernetes cluster. This role follows the established patterns from `fastpass-first-control-plane` but focuses on joining nodes to an already initialized cluster rather than initializing a new one. The role ensures high availability by creating redundant master nodes that can handle API requests, scheduling, and cluster management tasks. + +The key difference from the first control plane role is that this role will use `kubeadm join` with control plane flags instead of `kubeadm init`, and it will need to retrieve join tokens and certificate keys from the existing cluster. + +## Architecture + +### Role Structure +The role will follow the standard Ansible role structure: +``` +ansible/playbooks/roles/fastpass-additional-control-plane/ +├── defaults/ +│ └── main.yml +├── tasks/ +│ └── main.yml +├── handlers/ +│ └── main.yml (if needed) +└── meta/ + └── main.yml (if needed) +``` + +### Integration Points +- **DNS Management**: Uses the existing `dns-manager` role for consistent DNS record creation +- **Kubeconfig Management**: Uses the existing `kubeconfig-manager` role for local kubeconfig setup +- **Firewall Configuration**: Reuses firewall service definitions from the first control plane role +- **Cluster Integration**: Coordinates with the first control plane node to obtain join credentials + +### Dependencies +- The first control plane node must be fully initialized and running +- The `dns-manager` role must be available for DNS record creation +- The `kubeconfig-manager` role must be available for kubeconfig setup +- Required Kubernetes prerequisites must be installed on target nodes + +## Components and Interfaces + +### Main Task Flow +1. **Pre-flight Checks**: Verify cluster readiness and node prerequisites +2. **DNS Configuration**: Set up DNS records for the new control plane node +3. **Firewall Configuration**: Open required ports for control plane services +4. **Kubelet Configuration**: Create initial kubelet configuration +5. **Join Token Retrieval**: Get join token and certificate key from first control plane +6. **Cluster Join**: Execute kubeadm join with control plane flags +7. **Service Management**: Ensure kubelet is enabled and running +8. **Kubeconfig Setup**: Configure local kubeconfig access +9. **Verification**: Validate successful cluster join + +### Key Variables +- `cluster_name`: Name of the Kubernetes cluster +- `ip_address`: IP address of the current control plane node +- `first_control_plane_host`: Hostname/IP of the first control plane node +- `kubernetes_services_control_plane`: List of firewall services to open +- `join_token_ttl`: TTL for join tokens (default: 24h) +- `certificate_key_ttl`: TTL for certificate keys (default: 2h) + +### External Role Interfaces +- **dns-manager**: Provides DNS record creation with `host_name` variable +- **kubeconfig-manager**: Handles kubeconfig merging with `cluster_name` variable +- **First Control Plane**: Source for join tokens and certificate keys + +## Data Models + +### Join Credentials Structure +```yaml +join_credentials: + token: "abcdef.1234567890abcdef" + discovery_token_ca_cert_hash: "sha256:..." + certificate_key: "..." + api_server_endpoint: "cluster-name:6443" +``` + +### Firewall Services +```yaml +kubernetes_services_control_plane: + - kubernetes_API # Port 6443 + - etcd # Ports 2379-2380 + - kubelet # Port 10250 + - kube-scheduler # Port 10259 + - kube-controller-manager # Port 10257 +``` + +### Node Status Tracking +```yaml +node_status: + joined: false + kubelet_running: false + dns_configured: false + kubeconfig_ready: false +``` + +## Error Handling + +### Join Token Management +- **Token Expiration**: Automatically generate new tokens if existing ones are expired +- **Certificate Key Rotation**: Handle certificate key expiration gracefully +- **Network Connectivity**: Retry join operations with exponential backoff +- **API Server Availability**: Wait for API server readiness before attempting join + +### Idempotency Checks +- **Already Joined Nodes**: Skip join process if node is already part of the cluster +- **Existing Configuration**: Preserve existing kubelet configuration if valid +- **DNS Records**: Update existing DNS records instead of creating duplicates +- **Service Status**: Only restart services if configuration changes + +### Failure Recovery +- **Partial Join Failures**: Clean up partial configurations and retry +- **Network Issues**: Provide clear error messages for connectivity problems +- **Permission Errors**: Validate sudo/root access before attempting operations +- **Resource Constraints**: Check system resources before proceeding + +## Testing Strategy + +### Unit Testing Approach +- **Task Validation**: Test individual tasks with mock data +- **Variable Validation**: Ensure required variables are properly defined +- **Conditional Logic**: Test all conditional branches in tasks +- **Error Scenarios**: Validate error handling for common failure cases + +### Integration Testing +- **Multi-Node Clusters**: Test with 3 and 5 control plane node configurations +- **Network Scenarios**: Test across different network topologies +- **OS Compatibility**: Validate on supported operating systems (Ubuntu/Debian) +- **Version Compatibility**: Test with different Kubernetes versions + +### Validation Checks +- **Cluster Health**: Verify all control plane nodes are healthy after join +- **API Availability**: Confirm API server is accessible from all nodes +- **Etcd Cluster**: Validate etcd cluster membership and health +- **Scheduling**: Test pod scheduling across all control plane nodes +- **Failover**: Verify cluster continues operating if one control plane fails + +### Test Scenarios +1. **Fresh Join**: Join additional control plane to newly created cluster +2. **Existing Cluster**: Add control plane to cluster with existing workloads +3. **Network Partitions**: Test behavior during temporary network issues +4. **Token Expiration**: Handle expired join tokens gracefully +5. **Retry Operations**: Validate retry logic for transient failures + +## Implementation Considerations + +### Security +- **Token Security**: Ensure join tokens are handled securely and not logged +- **Certificate Management**: Properly manage and rotate certificate keys +- **Network Security**: Validate firewall rules don't expose unnecessary ports +- **Access Control**: Ensure proper RBAC is maintained after node joins + +### Performance +- **Parallel Execution**: Support joining multiple control plane nodes simultaneously +- **Resource Usage**: Monitor CPU and memory usage during join process +- **Network Bandwidth**: Optimize data transfer during cluster join +- **Startup Time**: Minimize time to achieve cluster readiness + +### Monitoring and Observability +- **Join Progress**: Provide clear progress indicators during join process +- **Health Checks**: Implement comprehensive health validation +- **Logging**: Ensure adequate logging for troubleshooting +- **Metrics**: Expose relevant metrics for monitoring cluster growth + +### Compatibility +- **Kubernetes Versions**: Support current and previous Kubernetes versions +- **Operating Systems**: Maintain compatibility with Ubuntu and Debian +- **Container Runtimes**: Work with containerd runtime configuration +- **Network Plugins**: Compatible with Flannel CNI configuration \ No newline at end of file diff --git a/.kiro/specs/fastpass-additional-control-plane/requirements.md b/.kiro/specs/fastpass-additional-control-plane/requirements.md new file mode 100644 index 0000000..6dcfd9f --- /dev/null +++ b/.kiro/specs/fastpass-additional-control-plane/requirements.md @@ -0,0 +1,77 @@ +# Requirements Document + +## Introduction + +This feature involves creating an Ansible role called `fastpass-additional-control-plane` that will deploy additional control plane nodes to an existing FastPass Kubernetes cluster. The role will follow the same pattern as the existing `fastpass-first-control-plane` role but will focus on joining nodes to an already initialized cluster rather than initializing a new cluster. This ensures high availability for the Kubernetes control plane by adding redundant master nodes. + +## Requirements + +### Requirement 1 + +**User Story:** As a DevOps engineer, I want to deploy additional control plane nodes to my FastPass Kubernetes cluster, so that I can achieve high availability and fault tolerance for the cluster control plane. + +#### Acceptance Criteria + +1. WHEN the role is executed on a node THEN the system SHALL join the node to the existing Kubernetes cluster as a control plane node +2. WHEN the role runs THEN the system SHALL configure the necessary firewall rules for control plane services +3. WHEN the role executes THEN the system SHALL ensure the kubelet service is properly configured and running +4. WHEN joining the cluster THEN the system SHALL use the correct join token and certificate key from the first control plane node +5. WHEN the role completes THEN the system SHALL verify the node has successfully joined as a control plane node + +### Requirement 2 + +**User Story:** As a system administrator, I want the additional control plane role to follow the same patterns as the first control plane role, so that the codebase remains consistent and maintainable. + +#### Acceptance Criteria + +1. WHEN the role is created THEN the system SHALL follow the same directory structure as fastpass-first-control-plane +2. WHEN the role is implemented THEN the system SHALL use similar variable naming conventions and task organization +3. WHEN the role runs THEN the system SHALL include proper error handling and idempotency checks +4. WHEN the role executes THEN the system SHALL use the same firewall service definitions as the first control plane role +5. WHEN the role is documented THEN the system SHALL include proper metadata headers with author, version, and description + +### Requirement 3 + +**User Story:** As a cluster operator, I want the additional control plane nodes to have proper DNS configuration, so that they can be reached by their cluster names and participate in load balancing. + +#### Acceptance Criteria + +1. WHEN the role runs THEN the system SHALL configure DNS records for the additional control plane nodes +2. WHEN DNS is configured THEN the system SHALL use the dns-manager role for consistency +3. WHEN the role executes THEN the system SHALL ensure the node can resolve the cluster endpoint +4. WHEN DNS setup completes THEN the system SHALL verify connectivity to the cluster API endpoint + +### Requirement 4 + +**User Story:** As a DevOps engineer, I want the role to handle kubeconfig management for additional control plane nodes, so that I can manage the cluster from any control plane node. + +#### Acceptance Criteria + +1. WHEN the role completes THEN the system SHALL configure kubeconfig for the new control plane node +2. WHEN kubeconfig is set up THEN the system SHALL use the kubeconfig-manager role for consistency +3. WHEN the role runs THEN the system SHALL ensure proper permissions are set on kubeconfig files +4. WHEN kubeconfig is configured THEN the system SHALL verify kubectl access works from the new node + +### Requirement 5 + +**User Story:** As a system administrator, I want the role to be idempotent and handle edge cases, so that I can run it multiple times safely without causing issues. + +#### Acceptance Criteria + +1. WHEN the role is run multiple times THEN the system SHALL not attempt to rejoin an already joined node +2. WHEN a node is already part of the cluster THEN the system SHALL skip the join process gracefully +3. WHEN the role encounters errors THEN the system SHALL provide clear error messages and fail gracefully +4. WHEN prerequisites are missing THEN the system SHALL report what needs to be configured first +5. WHEN the role runs THEN the system SHALL validate that required variables are defined + +### Requirement 6 + +**User Story:** As a cluster administrator, I want the role to integrate seamlessly with the existing FastPass deployment workflow, so that it can be used in the 4-step deployment process. + +#### Acceptance Criteria + +1. WHEN the role is created THEN the system SHALL be compatible with the deploy-fastpass-4step.yml playbook +2. WHEN the role runs THEN the system SHALL work with the fastpass_control_plane[1:] host group +3. WHEN integrated THEN the system SHALL not interfere with the first control plane initialization +4. WHEN the role executes THEN the system SHALL depend on the first control plane node being ready +5. WHEN deployment completes THEN the system SHALL allow worker nodes to join the cluster successfully \ No newline at end of file diff --git a/.kiro/specs/fastpass-additional-control-plane/tasks.md b/.kiro/specs/fastpass-additional-control-plane/tasks.md new file mode 100644 index 0000000..9784429 --- /dev/null +++ b/.kiro/specs/fastpass-additional-control-plane/tasks.md @@ -0,0 +1,118 @@ +# Implementation Plan + +- [ ] 1. Create role directory structure and basic configuration + - Create the fastpass-additional-control-plane role directory structure + - Set up defaults/main.yml with required variables and firewall services + - Create meta/main.yml with role metadata and dependencies + - _Requirements: 2.1, 2.2, 2.4_ + +- [ ] 2. Implement join token and certificate key retrieval + - [ ] 2.1 Create tasks to generate new join tokens from first control plane + - Write Ansible tasks to execute kubeadm token create on first control plane node + - Implement token validation and expiration checking + - Add error handling for token generation failures + - _Requirements: 1.4, 5.4_ + + - [ ] 2.2 Implement certificate key retrieval and management + - Create tasks to upload and retrieve certificate keys from first control plane + - Add certificate key expiration handling and rotation + - Implement secure handling of certificate keys in variables + - _Requirements: 1.4, 5.1_ + + - [ ] 2.3 Create discovery token CA certificate hash retrieval + - Write tasks to extract CA certificate hash from first control plane + - Implement validation of certificate hash format + - Add error handling for certificate retrieval failures + - _Requirements: 1.4, 5.4_ + +- [ ] 3. Implement DNS configuration and firewall setup + - [ ] 3.1 Configure DNS records for additional control plane nodes + - Integrate dns-manager role for consistent DNS record creation + - Pass appropriate host_name variable to dns-manager + - Add DNS propagation wait and validation + - _Requirements: 3.1, 3.2, 3.4_ + + - [ ] 3.2 Set up firewall rules for control plane services + - Reuse kubernetes_services_control_plane from defaults + - Implement UFW firewall rule creation for Debian/Ubuntu systems + - Add conditional logic for different operating systems + - _Requirements: 1.2, 2.4_ + +- [ ] 4. Implement kubelet configuration and cluster join + - [ ] 4.1 Create initial kubelet configuration + - Write kubelet config.yaml with systemd cgroup driver + - Set containerd socket endpoint configuration + - Ensure proper file permissions and ownership + - _Requirements: 1.3, 2.3_ + + - [ ] 4.2 Execute kubeadm join for control plane + - Implement kubeadm join command with control-plane flag + - Use retrieved join token, certificate key, and CA cert hash + - Add proper command argument construction and validation + - Include idempotency checks to prevent duplicate joins + - _Requirements: 1.1, 1.4, 5.1, 5.2_ + + - [ ] 4.3 Ensure kubelet service management + - Enable and start kubelet systemd service + - Add service status validation and error handling + - Implement service restart logic if needed + - _Requirements: 1.3, 1.5_ + +- [ ] 5. Implement kubeconfig management and validation + - [ ] 5.1 Configure kubeconfig for additional control plane nodes + - Integrate kubeconfig-manager role for consistent configuration + - Pass cluster_name variable to kubeconfig-manager + - Ensure proper kubeconfig merging with existing configurations + - _Requirements: 4.1, 4.2, 4.3_ + + - [ ] 5.2 Implement cluster join validation + - Create tasks to verify node successfully joined as control plane + - Add kubectl commands to check node status and roles + - Implement cluster health validation checks + - _Requirements: 1.5, 4.4_ + +- [ ] 6. Add comprehensive error handling and idempotency + - [ ] 6.1 Implement pre-flight validation checks + - Check if node is already joined to cluster + - Validate required variables are defined + - Verify first control plane node accessibility + - Add system resource and prerequisite checks + - _Requirements: 5.1, 5.2, 5.4, 5.5_ + + - [ ] 6.2 Add retry logic and failure recovery + - Implement retry mechanisms for transient failures + - Add exponential backoff for network-related operations + - Create cleanup tasks for partial join failures + - _Requirements: 5.3, 5.4_ + +- [ ] 7. Integration with FastPass deployment workflow + - [ ] 7.1 Ensure compatibility with deploy-fastpass-4step.yml + - Verify role works with fastpass_control_plane[1:] host group + - Test integration with existing playbook structure + - Validate dependency on first control plane completion + - _Requirements: 6.1, 6.2, 6.3, 6.4_ + + - [ ] 7.2 Add proper task documentation and metadata + - Include role header with author, version, and description + - Add inline comments for complex task logic + - Document required variables and their purposes + - _Requirements: 2.2, 2.5_ + +- [ ]* 8. Create comprehensive testing and validation + - [ ]* 8.1 Write unit tests for individual tasks + - Create test cases for token retrieval logic + - Test kubeadm join command construction + - Validate error handling scenarios + - _Requirements: 1.1, 1.4, 5.1_ + + - [ ]* 8.2 Implement integration tests + - Test multi-node control plane deployment + - Validate cluster health after additional nodes join + - Test failover scenarios and cluster resilience + - _Requirements: 1.5, 6.5_ + + - [ ]* 8.3 Add validation scripts and health checks + - Create scripts to verify cluster state after deployment + - Implement automated health validation + - Add performance and resource usage monitoring + - _Requirements: 1.5, 4.4_ \ No newline at end of file diff --git a/.kiro/specs/fastpass-dns-loadbalancer-fix/requirements.md b/.kiro/specs/fastpass-dns-loadbalancer-fix/requirements.md new file mode 100644 index 0000000..7ca1b52 --- /dev/null +++ b/.kiro/specs/fastpass-dns-loadbalancer-fix/requirements.md @@ -0,0 +1,51 @@ +# Requirements Document + +## Introduction + +The FastPass Kubernetes cluster deployment currently has critical DNS and load balancing configuration issues that prevent proper high availability setup. While the cluster endpoint `fastpass.local.mk-labs.cloud` is defined in the group variables, the `cluster_vip` variable required by the DNS manager role is missing, and the Traefik load balancer configuration is commented out. This means the cluster endpoint cannot resolve properly and there's no load balancing for the control plane API. This feature will fix these configuration gaps to enable true HA functionality. + +## Requirements + +### Requirement 1: DNS CNAME Record for Load Balancer + +**User Story:** As a DevOps engineer, I want the DNS manager to create a CNAME record for the cluster endpoint pointing to the load balancer, so that the cluster endpoint resolves through the load balancer rather than directly to node IPs. + +#### Acceptance Criteria + +1. WHEN the dns-manager role is called for a load-balanced cluster THEN the system SHALL create a CNAME record instead of an A record +2. WHEN the CNAME record is created THEN the system SHALL point fastpass.local.mk-labs.cloud to the traefik_server (lightning_lane.local.mk-labs.cloud) +3. WHEN the DNS record type is determined THEN the system SHALL use CNAME for load-balanced endpoints and A records for direct node access +4. WHEN DNS propagation occurs THEN the system SHALL verify that the CNAME resolution works correctly + +### Requirement 2: Complete Traefik Integration + +**User Story:** As a DevOps engineer, I want the Traefik load balancer to be fully integrated with the FastPass deployment, so that the cluster VIP is properly load balanced across all control plane nodes. + +#### Acceptance Criteria + +1. WHEN the traefik-manager role is called THEN the system SHALL use the traefik_server variable (lightning_lane) as the target host +2. WHEN Traefik configuration is generated THEN the system SHALL create proper TCP routing for the cluster endpoint to all control plane nodes +3. WHEN the cluster VIP is accessed THEN the system SHALL distribute requests across space-mountain, big-thunder-mountain, and splash-mountain +4. WHEN Traefik configuration is applied THEN the system SHALL reload the Traefik service to activate the new configuration + +### Requirement 3: High Availability Validation + +**User Story:** As a DevOps engineer, I want to validate that the HA setup is working correctly, so that I can be confident the cluster will survive node failures. + +#### Acceptance Criteria + +1. WHEN the deployment completes THEN the system SHALL test connectivity to the cluster endpoint +2. WHEN connectivity tests run THEN the system SHALL verify that the endpoint resolves through the CNAME to the load balancer +3. WHEN load balancer tests run THEN the system SHALL verify that requests are being distributed across control plane nodes +4. WHEN a control plane node is stopped THEN the system SHALL continue to serve API requests through the remaining nodes + +### Requirement 4: Backward Compatibility + +**User Story:** As a DevOps engineer, I want the DNS fixes to be backward compatible with existing deployments, so that current clusters continue to function during the transition. + +#### Acceptance Criteria + +1. WHEN existing clusters are updated THEN the system SHALL not break existing DNS configurations +2. WHEN new variables are introduced THEN the system SHALL provide sensible defaults for existing deployments +3. WHEN the update is applied THEN the system SHALL preserve existing kubeconfig files and cluster access +4. IF migration issues occur THEN the system SHALL provide rollback procedures and documentation \ No newline at end of file diff --git a/README.md b/README.md index d5775ed..692e92f 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,9 @@ This implementation is built on easily accessible consumer based hardware and wi ## 🎯 Project Goals -- **Multi-cluster OpenShift management** with ACM -- **Hybrid cloud scenarios** (bare metal + virtualized + containerized) -- **Enterprise integration testing** (AD, SQL Server, SIEM) +- **Kubernetes cluster for applications** +- **IAM integration testing** - **GitOps and automation workflows** -- **Red Hat certification preparation** ## 📋 Documentation (Priority Order) @@ -25,18 +23,18 @@ This implementation is built on easily accessible consumer based hardware and wi 6. **[VM Templates & Automation](./docs/13-vm-automation.md)** *(TBD)* - Template creation ### Phase 3: Infrastructure Services -7. **[Recursive DNS](./docs/09-openshift-sno.md)** *(TBD)* - ACM Hub Cluster -8. **[Authoritative DNS](./docs/08-openshift-compact.md)** *(TBD)* - 3 Master/3 Worker node (production-like) -9. **[Identity Management](./docs/10-acm-setup.md)** *(TBD)* - Multi-cluster management -10. **[Matchbox](./docs/10-acm-setup.md)** *(TBD)* - External app cluster +7. **[Recursive DNS] +8. **[Authoritative DNS] +9. **[Identity Management](./docs/10-acm-setup.md)** *(TBD)* +10. **[Matchbox] (Depreciated?) -### Phase 4: OpenShift Clusters +### Phase 4: OpenShift Clusters (Depreciated) 8. **[OpenShift SNO + Worker](./docs/09-openshift-sno.md)** *(TBD)* - ACM Hub Cluster 9. **[OpenShift Cluster](./docs/08-openshift-compact.md)** *(TBD)* - 3 Master/3 Worker node (production-like) 10. **[ACM Configuration](./docs/10-acm-setup.md)** *(TBD)* - Multi-cluster management 11. **[HCP Cluster](./docs/10-acm-setup.md)** *(TBD)* - External app cluster -### Phase 5: Container Platform +### Phase 5: Kubernetes Container Platform 5. **[Container Registry Setup](./docs/05-container-registry.md)** *(TBD)* - Harbor deployment 6. **[Git Repository Setup](./docs/06-git-repository.md)** *(TBD)* - Gitea/GitLab on Synology 7. **[Artifact Repository](./docs/07-artifact-repository.md)** *(TBD)* - Nexus/Artifactory @@ -99,14 +97,13 @@ configurations ## 🔧 Technology Stack ### Infrastructure -- **Networking**: Ubiquiti UDM SE +- **Networking**: Ubiquiti UDM Pro - **Storage**: Synology DS1621+, Ubiquiti UNAS Pro -- **Compute**: 3x Beelink S12 Pro, 5x Lenovo M710q, Dell T640 +- **Compute**: 3x Minisforum TH60, 2x Minisforum MS01, 7x Dell 7050 SFF ### Container Platforms -- **OpenShift 4.14+**: Two clusters (compact + SNO) -- **k0s**: Core services cluster -- **vSphere**: VM workloads +- **k8s**: Core services cluster +- **Proxmox**: VM workloads ### Core Services - **Container Registry**: Harbor diff --git a/ansible/DNS_MANAGEMENT_REFACTOR.md b/ansible/DNS_MANAGEMENT_REFACTOR.md new file mode 100644 index 0000000..c414483 --- /dev/null +++ b/ansible/DNS_MANAGEMENT_REFACTOR.md @@ -0,0 +1,193 @@ +# DNS Management Refactor - Modular & Repeatable + +This document explains the refactoring of DNS management from standalone playbooks to modular, reusable tasks. + +## 🎯 **What Changed** + +### **Before (Monolithic)** +```yaml +# Standalone playbook: add_technitium_dns_entry.yml +- name: Add entry to Technitium DNS + hosts: all + tasks: + - name: Create DNS entry + effectivelywild.technitium_dns.technitium_dns_add_record: + # ... hardcoded parameters +``` + +### **After (Modular)** +```yaml +# Reusable task: tasks/add_technitium_dns_entry.yml +- name: Create DNS entry for {{ dns_record_name }} + effectivelywild.technitium_dns.technitium_dns_add_record: + # ... parameterized with variables +``` + +## 📁 **New Structure** + +``` +ansible/ +├── playbooks/ +│ ├── tasks/ +│ │ └── add_technitium_dns_entry.yml # ✅ Reusable task file +│ ├── add_dns_entry.yml # ✅ New playbook using task +│ ├── add_technitium_dns_entry.yml.backup # 📦 Backed up old version +│ └── roles/ +│ └── dns-manager/ # ✅ Enhanced role +│ ├── tasks/main.yml # Uses task file +│ └── defaults/main.yml # Technitium defaults +└── scripts/ + └── migrate-dns-references.sh # ✅ Migration helper +``` + +## 🚀 **Usage Examples** + +### **1. In Playbooks (Direct Task Include)** +```yaml +- name: Add DNS entry for my server + hosts: my_servers + tasks: + - name: Create DNS entry + ansible.builtin.include_tasks: tasks/add_technitium_dns_entry.yml + vars: + dns_record_name: "{{ inventory_hostname }}" + dns_zone: "{{ base_domain }}" + dns_ip_address: "{{ ansible_default_ipv4.address }}" +``` + +### **2. Using the DNS Manager Role** +```yaml +- name: Setup cluster DNS + hosts: control_plane[0] + roles: + - role: dns-manager + vars: + cluster_endpoint: "my-cluster.local.mk-labs.cloud" + cluster_vip: "10.1.71.100" +``` + +### **3. Using the New Playbook** +```yaml +# Import the new modular playbook +- import_playbook: add_dns_entry.yml +``` + +### **4. In Cluster Network Setup** +```yaml +- name: Setup complete cluster network + ansible.builtin.include_role: + name: cluster-network-setup + vars: + cluster_name: "fastpass" + cluster_endpoint: "fastpass.local.mk-labs.cloud" + cluster_vip: "10.1.71.53" +``` + +## 🔧 **Migration Guide** + +### **Automatic Migration** +```bash +# Run the migration script to find references +./scripts/migrate-dns-references.sh +``` + +### **Manual Updates** + +1. **Replace playbook imports:** + ```yaml + # OLD + - import_playbook: add_technitium_dns_entry.yml + + # NEW + - import_playbook: add_dns_entry.yml + ``` + +2. **Use task includes in roles:** + ```yaml + - ansible.builtin.include_tasks: tasks/add_technitium_dns_entry.yml + vars: + dns_record_name: "my-server" + dns_ip_address: "10.1.71.100" + ``` + +3. **Use the dns-manager role:** + ```yaml + - ansible.builtin.include_role: + name: dns-manager + ``` + +## 📋 **Variable Reference** + +### **Task Variables (`tasks/add_technitium_dns_entry.yml`)** +| Variable | Default | Description | +|----------|---------|-------------| +| `dns_record_name` | `inventory_hostname` | DNS record name | +| `dns_zone` | `base_domain` | DNS zone | +| `dns_ip_address` | `ip_address` | IP address for A record | +| `dns_record_type` | `A` | DNS record type | +| `dns_ttl` | `360` | TTL in seconds | +| `dns_create_ptr` | `true` | Create PTR record | +| `dns_debug` | `true` | Show debug output | + +### **DNS Manager Role Variables** +| Variable | Default | Description | +|----------|---------|-------------| +| `cluster_endpoint` | - | Full cluster FQDN | +| `cluster_vip` | - | Cluster VIP address | +| `dns_management_enabled` | `true` | Enable DNS management | +| `use_hosts_file_fallback` | `true` | Add to /etc/hosts | +| `dns_ttl` | `360` | DNS TTL | +| `create_ptr_record` | `true` | Create PTR record | + +## 🎯 **Benefits** + +### ✅ **Modularity** +- Single task file used across multiple contexts +- Consistent DNS management approach +- Easy to maintain and update + +### ✅ **Flexibility** +- Works in playbooks, roles, and standalone +- Parameterized for different use cases +- Supports multiple DNS providers (extensible) + +### ✅ **Maintainability** +- One place to update DNS logic +- Clear variable interface +- Better error handling and debugging + +### ✅ **Integration** +- Seamlessly integrates with cluster setup +- Works with existing homelab infrastructure +- Compatible with Traefik load balancer setup + +## 🔄 **Integration with Cluster Setup** + +The DNS management now integrates seamlessly with your cluster deployment: + +```yaml +# In fastpass-first-control-plane role +- name: Setup network infrastructure for FastPass cluster + ansible.builtin.include_role: + name: cluster-network-setup + vars: + cluster_name: "{{ cluster_name }}" + cluster_endpoint: "{{ control_plane_endpoint }}" + cluster_vip: "{{ ansible_default_ipv4.address }}" + control_plane_nodes: "{{ groups['fastpass_control_plane'] }}" +``` + +This automatically: +1. ✅ Creates DNS entry for `fastpass.local.mk-labs.cloud` +2. ✅ Configures Traefik load balancer +3. ✅ Tests connectivity +4. ✅ Provides fallback to /etc/hosts + +## 🚀 **Next Steps** + +1. **Test the refactored approach** with your FastPass cluster +2. **Extend to other clusters** (Hub, Internal) using the same pattern +3. **Add support for other DNS providers** if needed +4. **Create monitoring** for DNS health checks + +This modular approach makes your homelab's DNS management much more maintainable and repeatable across all your Kubernetes clusters! \ No newline at end of file diff --git a/ansible/KUBECONFIG_MANAGEMENT.md b/ansible/KUBECONFIG_MANAGEMENT.md new file mode 100644 index 0000000..8484d20 --- /dev/null +++ b/ansible/KUBECONFIG_MANAGEMENT.md @@ -0,0 +1,233 @@ +# Kubeconfig Management - Modular & Repeatable + +This document explains the modular kubeconfig management system for your homelab's multiple Kubernetes clusters. + +## Overview + +The kubeconfig management has been refactored into reusable, modular components that can handle multiple clusters seamlessly: + +- **FastPass** (Vanilla Kubernetes) +- **Hub Cluster** (OpenShift SNO) +- **Internal Cluster** (OpenShift) +- **Future clusters** (easily extensible) + +## Architecture + +``` +ansible/playbooks/roles/ +├── kubeconfig-manager/ # Core reusable role +│ ├── tasks/main.yml # Main entry point +│ ├── tasks/merge-kubeconfig.yml # Merging logic +│ ├── defaults/main.yml # Default variables +│ └── README.md # Role documentation +├── cluster-kubeconfig/ # Generic wrapper role +└── fastpass-first-control-plane/ # Uses kubeconfig-manager +``` + +## Quick Usage + +### 1. Using the Script (Easiest) + +```bash +cd ansible + +# Setup FastPass cluster kubeconfig +./scripts/setup-kubeconfig.sh fastpass fastpass_control_plane[0] + +# Setup Hub cluster kubeconfig +./scripts/setup-kubeconfig.sh hub hub_cluster + +# Setup Internal cluster kubeconfig +./scripts/setup-kubeconfig.sh internal internal_cluster[0] +``` + +### 2. Direct Ansible Usage + +```bash +# Single cluster +ansible-playbook -i inventory.yml \ + playbooks/examples/multi-cluster-kubeconfig.yml \ + --limit fastpass_control_plane[0] \ + -e target_cluster_name=fastpass + +# Multiple clusters at once +ansible-playbook -i inventory.yml \ + playbooks/examples/multi-cluster-kubeconfig.yml +``` + +### 3. In Your Own Playbooks + +```yaml +- name: Setup kubeconfig for any cluster + hosts: my_cluster_nodes[0] + roles: + - role: kubeconfig-manager + vars: + cluster_name: "my-cluster" + kubeconfig_source_path: "/etc/kubernetes/admin.conf" +``` + +## Features + +### ✅ **Modular & Reusable** +- Single role works with any Kubernetes cluster +- Easy to extend for new clusters +- Consistent behavior across all clusters + +### ✅ **Safe Operations** +- Automatic backups before merging +- Non-destructive merging +- Preserves existing contexts + +### ✅ **Multi-Cluster Ready** +- Unique naming: `cluster-name-admin` +- No conflicts between clusters +- Easy context switching + +### ✅ **Homelab Optimized** +- Works with vanilla Kubernetes +- Works with OpenShift +- Handles different kubeconfig paths + +## Generated Structure + +After running the kubeconfig management: + +```bash +~/.kube/ +├── config # Merged config with all clusters +├── config-fastpass # Individual cluster configs +├── config-hub +├── config-internal +└── config.backup.1697123456 # Timestamped backups +``` + +## Context Management + +```bash +# List all available contexts +kubectl config get-contexts + +# Switch between clusters +kubectl config use-context fastpass-admin +kubectl config use-context hub-admin +kubectl config use-context internal-admin + +# Check current context +kubectl config current-context + +# Test connectivity +kubectl cluster-info +kubectl get nodes +``` + +## Integration with Existing Roles + +### Before (Monolithic) +```yaml +# fastpass-first-control-plane/tasks/main.yml +- name: 50+ lines of kubeconfig logic + # Lots of repetitive code +``` + +### After (Modular) +```yaml +# fastpass-first-control-plane/tasks/main.yml +- name: Setup kubeconfig for FastPass cluster + ansible.builtin.include_role: + name: kubeconfig-manager + vars: + cluster_name: "{{ cluster_name }}" +``` + +## Adding New Clusters + +To add a new cluster (e.g., "edge-cluster"): + +1. **Add to inventory:** +```yaml +edge_cluster: + hosts: + edge-node-01: +``` + +2. **Use the script:** +```bash +./scripts/setup-kubeconfig.sh edge edge_cluster[0] +``` + +3. **Or add to playbook:** +```yaml +- name: Setup kubeconfig for Edge cluster + hosts: edge_cluster[0] + roles: + - role: kubeconfig-manager + vars: + cluster_name: "edge" +``` + +## Customization + +### Different Kubeconfig Paths +```yaml +- role: kubeconfig-manager + vars: + cluster_name: "openshift-cluster" + kubeconfig_source_path: "/etc/kubernetes/static-pod-resources/kube-apiserver-certs/secrets/node-kubeconfigs/localhost.kubeconfig" +``` + +### Custom Context Names +```yaml +- role: kubeconfig-manager + vars: + cluster_name: "prod" + context_suffix: "system:admin" # Results in "prod-system:admin" +``` + +## Troubleshooting + +### Common Issues + +1. **Permission Denied** + ```bash + # Fix ownership + sudo chown -R $USER:$USER ~/.kube/ + ``` + +2. **Context Not Found** + ```bash + # List available contexts + kubectl config get-contexts + + # Check if cluster was added + kubectl config view + ``` + +3. **Backup Recovery** + ```bash + # Restore from backup + cp ~/.kube/config.backup.1697123456 ~/.kube/config + ``` + +### Debug Mode +```bash +# Run with verbose output +ansible-playbook -vvv playbooks/examples/multi-cluster-kubeconfig.yml +``` + +## Benefits for Your Homelab + +1. **Consistency**: Same process for all clusters +2. **Maintainability**: Single role to update/fix +3. **Scalability**: Easy to add new clusters +4. **Safety**: Automatic backups and safe merging +5. **Flexibility**: Works with different Kubernetes distributions + +## Next Steps + +1. **Test the modular approach** with your FastPass cluster +2. **Extend to Hub and Internal clusters** using the same pattern +3. **Create cluster-specific variables** in group_vars if needed +4. **Add monitoring/validation** tasks to verify kubeconfig health + +This modular approach makes your homelab's multi-cluster management much more maintainable and repeatable! \ No newline at end of file diff --git a/ansible/group_vars/all/vars b/ansible/group_vars/all/vars index 63996cd..aa1db5d 100644 --- a/ansible/group_vars/all/vars +++ b/ansible/group_vars/all/vars @@ -15,3 +15,6 @@ base_domain: "local.mk-labs.cloud" # Terraform variables terraform_server: "infra01" + +# Traefik variables +traefik_server: "lightning-lane" \ No newline at end of file diff --git a/ansible/group_vars/fastpass/vars b/ansible/group_vars/fastpass/vars index 2c7a3b7..08f85dd 100644 --- a/ansible/group_vars/fastpass/vars +++ b/ansible/group_vars/fastpass/vars @@ -8,12 +8,12 @@ pod_network_cidr: "10.244.0.0/16" service_cidr: "10.96.0.0/12" # Control Plane Configuration -control_plane_endpoint: "fastpass.local.mk-labs.cloud" +control_plane_endpoint: "{{ cluster_name}}.{{ base_domain}}" control_plane_port: "6443" # CNI Configuration cni_plugin: "calico" -calico_version: "v3.28.0" +calico_version: "v3.30.3" # Node Labels and Taints node_labels: diff --git a/ansible/host_vars/arcade/vars b/ansible/host_vars/arcade/vars new file mode 100644 index 0000000..3d6a344 --- /dev/null +++ b/ansible/host_vars/arcade/vars @@ -0,0 +1,59 @@ +--- +# file: host_vars/vm_template/vars +# Ansible vars template for hosts created via cloning. + +# Supported hypervisors: +# - Proxmox + +platform: "proxmox" + +# This is the Proxmox node where all the VM templates are stored. (Templates are not global.) + +proxmox_clone_node: "fantasyland" + +# Templates are named in the following format (all lower case): -- +# Current OS offerings are: +# - Ubuntu +# - 24.04 +# - Fedora +# - 42 + +vm_os_distribution: "ubuntu" +vm_os_version: "24.04" + +# Current VM sizes are: +# - Small: 2 cores, 2GB memory, 8 GiB virtual disk +# - Medium: 2 cores, 4GB memory, 16 GiB virtual disk +# - Large: 4 cores, 4GB memory, 32 GiB virtual disk +# - Large Plus: 4 cores, 4GB memory, 48 GiB virtual disk +# - Xlarge: 4 cores, 8GB memory, 64 GiB virtual disk +# - Xlarge Plus: 4 cores, 8GB memory, 128 GiB virtual disk + +vm_size: "large" + +# Proxmox storage target. + +vm_storage: "liberty-tree" + +# Proxmox does not yet do dynamic load balancing, the host target sets the target for HA groups +# and backup groups. (ha_group will be factored out in the next functionality update.) + +ha_group: "pve03" +proxmox_host_target: "pve03" + +# Currently, only single NIC VMs using IPv4 are supported via cloning. The IP address also +# sets the Proxmox VMID. The VMID is a combination of the 3rd and 4th octet of the IPv4 address. + +ip_address: 10.1.71.111 +# vm_mac_address: 'BC:24:11:11:BC:58' + +# Software +# Future enhancement will allow specification of additional software to automatically deploy to +# the VM after creation. + +#terraform_version: "1.11.3" + +# --- + +vm_clone_source: "{{ vm_os_distribution }}-{{ vm_os_version }}-{{ vm_size }}" +hostname: "{{ inventory_hostname }}.{{ base_domain }}" # Change variable to fqdn diff --git a/ansible/host_vars/lightning_lane/vars b/ansible/host_vars/lightning_lane/vars new file mode 100644 index 0000000..48d822d --- /dev/null +++ b/ansible/host_vars/lightning_lane/vars @@ -0,0 +1,33 @@ +--- +# file: host_vars/lightning_lane/vars +# Traefik Load Balancer Server + +# Supported hypervisors: +# - Proxmox + +platform: "proxmox" + +# This is the Proxmox node where all the VM templates are stored. (Templates are not global.) +proxmox_clone_node: "fantasyland" + +# VM Configuration +vm_os_distribution: "ubuntu" +vm_os_version: "24.04" +vm_size: "medium" +vm_storage: "general" + +# Proxmox HA Configuration +ha_group: "pve02" +proxmox_host_target: "pve02" + +# Network Configuration +# IP address for the Traefik load balancer +ip_address: 10.1.71.80 +vm_mac_address: 'BC:24:11:50:00:80' + +# Software Configuration +# Traefik will be installed and configured on this host + +# VM Template Configuration +vm_clone_source: "{{ vm_os_distribution }}-{{ vm_os_version }}-{{ vm_size }}" +hostname: "{{ inventory_hostname }}.{{ base_domain }}" \ No newline at end of file diff --git a/ansible/inventory.yml b/ansible/inventory.yml index 323598a..1d7fbb9 100644 --- a/ansible/inventory.yml +++ b/ansible/inventory.yml @@ -37,6 +37,11 @@ prometheus_nodes: # hosts: # cinderella-castle: +papermc_server: +# ansible-galaxy role install engonzal.papermc + hosts: + arcade: + semaphore_server: hosts: imagineering: @@ -45,6 +50,10 @@ n8n_server: hosts: tiki-room: +traefik_server: + hosts: + lightning_lane: + # dhcp_server: # hosts: # matchbox: diff --git a/ansible/playbooks/add_dns_entry.yml b/ansible/playbooks/add_dns_entry.yml index 3f2529a..309ed2a 100644 --- a/ansible/playbooks/add_dns_entry.yml +++ b/ansible/playbooks/add_dns_entry.yml @@ -1,17 +1,13 @@ --- -- name: Add entry to DNS +# Replacement for add_technitium_dns_entry.yml +# This playbook uses the modular task file approach + +- name: Add DNS entry using Technitium DNS hosts: all gather_facts: false tasks: - - name: Create DNS entry for {{ inventory_hostname }} - delegate_to: "{{ groups['ipaserver'][0] }}" - freeipa.ansible_freeipa.ipadnsrecord: - ipaapi_context: "server" - ipaadmin_password: "{{ vault_freeipa_password }}" - name: "{{ inventory_hostname }}" - zone_name: "{{ base_domain }}" - record_type: "A" - record_value: "{{ ip_address }}" - record_ttl: 60 - # create_reverse: yes + - name: Include Technitium DNS entry task + ansible.builtin.include_tasks: tasks/add_technitium_dns_entry.yml + vars: + host_name: "{{ inventory_hostname }}" diff --git a/ansible/playbooks/add_technitium_dns_entry.yml b/ansible/playbooks/add_technitium_dns_entry.yml.backup similarity index 100% rename from ansible/playbooks/add_technitium_dns_entry.yml rename to ansible/playbooks/add_technitium_dns_entry.yml.backup diff --git a/ansible/playbooks/create_vm_from_clone.yml b/ansible/playbooks/create_vm_from_clone.yml index 5ac2834..5de6f16 100644 --- a/ansible/playbooks/create_vm_from_clone.yml +++ b/ansible/playbooks/create_vm_from_clone.yml @@ -11,7 +11,7 @@ when: vm_os_distribution == "ubuntu" - name: DNS Playbook - ansible.builtin.import_playbook: add_technitium_dns_entry.yml + ansible.builtin.import_playbook: add_dns_entry.yml - name: DHCP Playbook ansible.builtin.import_playbook: add_dhcp_reservation.yml diff --git a/ansible/playbooks/deploy-fastpass-4step.yml b/ansible/playbooks/deploy-fastpass-4step.yml index 7aa255f..079499c 100644 --- a/ansible/playbooks/deploy-fastpass-4step.yml +++ b/ansible/playbooks/deploy-fastpass-4step.yml @@ -6,19 +6,21 @@ # roles: # - role: kubernetes-prerequisites -- name: Step 2 - Deploy First Control Plane Node - hosts: fastpass_control_plane[0] - become: true - gather_facts: true # false - roles: - - role: fastpass-first-control-plane - -# - name: Step 3 - Deploy Additional Control Plane Nodes -# hosts: fastpass_control_plane[1:] +# - name: Step 2 - Deploy First Control Plane Node +# hosts: fastpass_control_plane[0] # become: true # gather_facts: false # roles: -# - role: fastpass-additional-control-plane +# - role: fastpass-first-control-plane + +- name: Step 3 - Deploy Additional Control Plane Nodes + hosts: fastpass_control_plane[1:] + become: true + gather_facts: true # false + roles: + - role: fastpass-additional-control-plane + vars: + cluster_name: "fastpass" # - name: Step 4 - Deploy Worker Nodes # hosts: fastpass_workers @@ -26,18 +28,3 @@ # gather_facts: false # roles: # - role: fastpass-workers - -# - name: Final Cluster Validation -# hosts: fastpass_control_plane[0] -# become: false -# gather_facts: false -# environment: -# KUBECONFIG: "{{ kubeconfig_path }}" -# tasks: -# - name: Display cluster status -# ansible.builtin.command: kubectl get nodes -# delegate_to: localhost - -# - name: Display all pods -# ansible.builtin.command: kubectl get pods -A -# delegate_to: localhost diff --git a/ansible/playbooks/deploy_minecraft.yml b/ansible/playbooks/deploy_minecraft.yml new file mode 100644 index 0000000..6f0222c --- /dev/null +++ b/ansible/playbooks/deploy_minecraft.yml @@ -0,0 +1,28 @@ +--- +- name: 1. Deploy Paper Minecraft server + hosts: papermc_server + vars: + papermc_mem: 2G + papermc_server_port: 25565 + papermc_motd: "MK-Labs Minecraft Server" + papermc_broadcast_console_to_ops: false + papermc_version: 1.21.8 + papermc_dir_main: /app/minecraft + papermc_dir_data: /app/minecraft/data + papermc_dir_logs: /app/minecraft/logs + papermc_dir_plugins: /app/minecraft/plugins + papermc_dir_worlds: /app/minecraft/worlds + papermc_dir_worlds_nether: /app/minecraft/worlds/nether + papermc_dir_worlds_the_end: /app/minecraft/worlds/the_end + papermc_dir_worlds_world: /app/minecraft/worlds/world + papermc_jar_url: https://papermc.io/api/v2/projects/paper/versions/{{ papermc_version }}/builds/latest/downloads/paper-{{ papermc_version }}-{{ papermc_build }}.jar + papermc_jar_path: /opt/papermc/paper-{{ papermc_version }}-{{ papermc_build }}.jar + papermc_jar_checksum_type: sha256 + papermc_jar_checksum_path: /opt/papermc/paper-{{ papermc_version }}-{{ papermc_build }}.jar.sha256 + papermc_whitelist: + - ryansrailroad + papermc_white_list: "true" + papermc_enforce_whitelist: "true" + roles: + - role: engonzal.papermc + become: yes diff --git a/ansible/playbooks/examples/multi-cluster-kubeconfig.yml b/ansible/playbooks/examples/multi-cluster-kubeconfig.yml new file mode 100644 index 0000000..d3802a7 --- /dev/null +++ b/ansible/playbooks/examples/multi-cluster-kubeconfig.yml @@ -0,0 +1,41 @@ +--- +# Example playbook showing how to use the modular kubeconfig management +# across multiple clusters in your homelab + +- name: Setup kubeconfig for FastPass cluster + hosts: fastpass_control_plane[0] + gather_facts: true + roles: + - role: kubeconfig-manager + vars: + cluster_name: "fastpass" + +- name: Setup kubeconfig for Hub cluster + hosts: hub_cluster + gather_facts: true + roles: + - role: kubeconfig-manager + vars: + cluster_name: "hub" + +- name: Setup kubeconfig for Internal cluster + hosts: internal_cluster[0] + gather_facts: true + roles: + - role: kubeconfig-manager + vars: + cluster_name: "internal" + +# Alternative approach using the generic cluster-kubeconfig role +- name: Setup kubeconfig for any cluster + hosts: "{{ target_cluster_hosts }}" + gather_facts: true + roles: + - role: cluster-kubeconfig + vars: + cluster_name: "{{ target_cluster_name }}" + +# Usage examples: +# ansible-playbook -i inventory.yml examples/multi-cluster-kubeconfig.yml +# ansible-playbook -i inventory.yml examples/multi-cluster-kubeconfig.yml --limit fastpass_control_plane[0] +# ansible-playbook -i inventory.yml examples/multi-cluster-kubeconfig.yml -e target_cluster_hosts=hub_cluster -e target_cluster_name=hub \ No newline at end of file diff --git a/ansible/playbooks/examples/setup-fastpass-network.yml b/ansible/playbooks/examples/setup-fastpass-network.yml new file mode 100644 index 0000000..3978f03 --- /dev/null +++ b/ansible/playbooks/examples/setup-fastpass-network.yml @@ -0,0 +1,60 @@ +--- +# Example: Setup network infrastructure for FastPass cluster +# This demonstrates the modular approach for DNS and load balancer setup + +- name: Setup FastPass Cluster Network Infrastructure + hosts: fastpass_control_plane[0] + gather_facts: true + vars: + cluster_name: "fastpass" + cluster_endpoint: "{{ control_plane_endpoint }}" + cluster_vip: "{{ ansible_default_ipv4.address }}" + control_plane_nodes: "{{ groups['fastpass_control_plane'] }}" + + tasks: + - name: Display cluster configuration + ansible.builtin.debug: + msg: | + Setting up network for FastPass cluster: + - Cluster Name: {{ cluster_name }} + - Endpoint: {{ cluster_endpoint }} + - VIP: {{ cluster_vip }} + - Control Plane Nodes: {{ control_plane_nodes | join(', ') }} + + - name: Setup cluster network infrastructure + ansible.builtin.include_role: + name: cluster-network-setup + vars: + cluster_name: "{{ cluster_name }}" + cluster_endpoint: "{{ cluster_endpoint }}" + cluster_vip: "{{ cluster_vip }}" + control_plane_nodes: "{{ control_plane_nodes }}" + +# Alternative approach using task file directly +- name: Alternative - Use Technitium DNS task directly + hosts: localhost + gather_facts: false + vars: + cluster_endpoint: "{{ hostvars[groups['fastpass_control_plane'][0]]['control_plane_endpoint'] }}" + cluster_vip: "{{ hostvars[groups['fastpass_control_plane'][0]]['ansible_default_ipv4']['address'] }}" + + tasks: + - name: Create DNS entry using task file + ansible.builtin.include_tasks: ../tasks/add_technitium_dns_entry.yml + vars: + dns_record_name: "{{ cluster_endpoint.split('.')[0] }}" + dns_zone: "{{ base_domain }}" + dns_ip_address: "{{ cluster_vip }}" + dns_record_type: "A" + dns_ttl: 360 + dns_create_ptr: true + dns_debug: true + when: use_task_approach | default(false) + +# Usage examples: +# +# Use modular approach (recommended): +# ansible-playbook -i inventory.yml playbooks/examples/setup-fastpass-network.yml +# +# Use task file approach: +# ansible-playbook -i inventory.yml playbooks/examples/setup-fastpass-network.yml -e use_task_approach=true \ No newline at end of file diff --git a/ansible/playbooks/roles/cluster-kubeconfig/tasks/main.yml b/ansible/playbooks/roles/cluster-kubeconfig/tasks/main.yml new file mode 100644 index 0000000..7761cdf --- /dev/null +++ b/ansible/playbooks/roles/cluster-kubeconfig/tasks/main.yml @@ -0,0 +1,12 @@ +--- +# role: cluster-kubeconfig +# description: Generic role for any Kubernetes cluster kubeconfig management +# author: mk-labs +# version: 1.0.0 + +- name: Setup kubeconfig for {{ cluster_name }} cluster + ansible.builtin.include_role: + name: kubeconfig-manager + vars: + cluster_name: "{{ cluster_name }}" + kubeconfig_source_path: "{{ kubeconfig_source_path | default('/etc/kubernetes/admin.conf') }}" \ No newline at end of file diff --git a/ansible/playbooks/roles/cluster-network-setup/tasks/main.yml b/ansible/playbooks/roles/cluster-network-setup/tasks/main.yml new file mode 100644 index 0000000..72a24ae --- /dev/null +++ b/ansible/playbooks/roles/cluster-network-setup/tasks/main.yml @@ -0,0 +1,48 @@ +--- +# role: cluster-network-setup +# description: Combined DNS and Load Balancer setup for Kubernetes clusters +# author: mk-labs +# version: 1.0.0 + +- name: Setup DNS entry for cluster + ansible.builtin.include_role: + name: dns-manager + vars: + cluster_endpoint: "{{ cluster_endpoint }}" + cluster_vip: "{{ cluster_vip }}" + +- name: Setup Traefik load balancer for cluster + ansible.builtin.include_role: + name: traefik-manager + vars: + cluster_name: "{{ cluster_name }}" + cluster_endpoint: "{{ cluster_endpoint }}" + control_plane_nodes: "{{ control_plane_nodes }}" + when: traefik_enabled | default(true) + +- name: Wait for DNS propagation + ansible.builtin.wait_for: + timeout: 30 + delegate_to: localhost + +- name: Test cluster endpoint connectivity + ansible.builtin.wait_for: + host: "{{ cluster_endpoint }}" + port: "{{ cluster_api_port | default(6443) }}" + timeout: 60 + delegate_to: localhost + register: connectivity_test + failed_when: false + +- name: Display network setup results + ansible.builtin.debug: + msg: | + 🌐 Network Setup Complete for {{ cluster_name }}: + + DNS Entry: {{ cluster_endpoint }} → {{ cluster_vip }} + Load Balancer: {{ 'Configured' if traefik_enabled | default(true) else 'Skipped' }} + Connectivity: {{ 'Success' if connectivity_test.failed == false else 'Failed - Check firewall/network' }} + + Next steps: + 1. Verify: kubectl --kubeconfig ~/.kube/config-{{ cluster_name }} cluster-info + 2. Switch context: kubectl config use-context {{ cluster_name }}-admin \ No newline at end of file diff --git a/ansible/playbooks/roles/dns-manager/defaults/main.yml b/ansible/playbooks/roles/dns-manager/defaults/main.yml new file mode 100644 index 0000000..0292c9c --- /dev/null +++ b/ansible/playbooks/roles/dns-manager/defaults/main.yml @@ -0,0 +1,18 @@ +--- +# Default variables for dns-manager role + +# DNS Configuration +dns_management_enabled: true +use_hosts_file_fallback: false +dns_ttl: 360 +dns_propagation_wait: 2 +create_ptr_record: true + +# Cluster Configuration (to be provided by calling role) +# cluster_endpoint: "fastpass.local.mk-labs.cloud" +# cluster_vip: "10.1.71.53" + +# DNS Server Configuration (from group_vars) +# dns_server: "monorail" +# base_domain: "local.mk-labs.cloud" +# vault_technitium_api_key: "{{ vault_technitium_api_key }}" diff --git a/ansible/playbooks/roles/dns-manager/tasks/main.yml b/ansible/playbooks/roles/dns-manager/tasks/main.yml new file mode 100644 index 0000000..f687732 --- /dev/null +++ b/ansible/playbooks/roles/dns-manager/tasks/main.yml @@ -0,0 +1,17 @@ +--- +# role: dns-manager +# description: Reusable role for managing DNS entries across clusters using Technitium DNS +# author: mk-labs +# version: 1.0.0 + +- name: Create DNS entry using Technitium DNS task + ansible.builtin.include_tasks: "{{ playbook_dir }}/tasks/add_technitium_dns_entry.yml" + +- name: Wait for DNS propagation + ansible.builtin.pause: + seconds: "{{ dns_propagation_wait | default(10) }}" + when: dns_management_enabled | default(true) + +- name: Look up A (IPv4) records for example.org + ansible.builtin.debug: + msg: "{{ query('community.dns.lookup', 'fastpass') }}" diff --git a/ansible/playbooks/roles/fastpass-additional-control-plane/README.md b/ansible/playbooks/roles/fastpass-additional-control-plane/README.md new file mode 100644 index 0000000..225dd44 --- /dev/null +++ b/ansible/playbooks/roles/fastpass-additional-control-plane/README.md @@ -0,0 +1,38 @@ +Role Name +========= + +A brief description of the role goes here. + +Requirements +------------ + +Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. + +Role Variables +-------------- + +A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well. + +Dependencies +------------ + +A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles. + +Example Playbook +---------------- + +Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: + + - hosts: servers + roles: + - { role: username.rolename, x: 42 } + +License +------- + +BSD + +Author Information +------------------ + +An optional section for the role authors to include contact information, or a website (HTML is not allowed). diff --git a/ansible/playbooks/roles/fastpass-additional-control-plane/defaults/main.yml b/ansible/playbooks/roles/fastpass-additional-control-plane/defaults/main.yml new file mode 100644 index 0000000..6c152ab --- /dev/null +++ b/ansible/playbooks/roles/fastpass-additional-control-plane/defaults/main.yml @@ -0,0 +1,22 @@ +--- +# FastPass Additional Control Plane Role Defaults + +# Kubernetes services for control plane +kubernetes_services_control_plane: + - kubernetes_API + - etcd + - kubelet + - kube-scheduler + - kube-controller-manager + +# Join token configuration +join_token_ttl: "24h" +certificate_key_ttl: "2h" + +# Default cluster configuration +pod_network_cidr: "10.244.0.0/16" +service_cidr: "10.96.0.0/12" + +# Kubelet configuration +kubelet_cgroup_driver: "systemd" +container_runtime_endpoint: "unix:///run/containerd/containerd.sock" diff --git a/ansible/playbooks/roles/fastpass-additional-control-plane/handlers/main.yml b/ansible/playbooks/roles/fastpass-additional-control-plane/handlers/main.yml new file mode 100644 index 0000000..f3feb40 --- /dev/null +++ b/ansible/playbooks/roles/fastpass-additional-control-plane/handlers/main.yml @@ -0,0 +1,2 @@ +--- +# handlers file for fastpass-additional-control-plane diff --git a/ansible/playbooks/roles/fastpass-additional-control-plane/meta/main.yml b/ansible/playbooks/roles/fastpass-additional-control-plane/meta/main.yml new file mode 100644 index 0000000..29ca510 --- /dev/null +++ b/ansible/playbooks/roles/fastpass-additional-control-plane/meta/main.yml @@ -0,0 +1,33 @@ +--- +galaxy_info: + author: Ryan Blundon + description: FastPass Additional Control Plane - Deploy additional control plane nodes to existing FastPass Kubernetes cluster + company: Homelab + + license: MIT + + min_ansible_version: "2.9" + + platforms: + - name: Ubuntu + versions: + - focal + - jammy + - name: Debian + versions: + - bullseye + - bookworm + + galaxy_tags: + - kubernetes + - k8s + - controlplane + - cluster + - fastpass + - kubeadm + +dependencies: + - role: dns-manager + when: cluster_name is defined + - role: kubeconfig-manager + when: cluster_name is defined diff --git a/ansible/playbooks/roles/fastpass-additional-control-plane/tasks/main.yml b/ansible/playbooks/roles/fastpass-additional-control-plane/tasks/main.yml new file mode 100644 index 0000000..e398698 --- /dev/null +++ b/ansible/playbooks/roles/fastpass-additional-control-plane/tasks/main.yml @@ -0,0 +1,29 @@ +--- +# role: fastpass-additional-control-plane +# description: FastPass Additional Control Plane - Deploy additional control plane nodes to existing FastPass Kubernetes cluster +# author: Ryan Blundon +# version: 1.0.0 +# date: 2025-10-05 + +# This role joins additional nodes to an existing Kubernetes cluster as control plane nodes +# It follows the same patterns as fastpass-first-control-plane but uses kubeadm join instead of kubeadm init + +- name: Display role information + ansible.builtin.debug: + msg: "Starting FastPass Additional Control Plane deployment for {{ inventory_hostname }}" + +- name: Setup DNS record for cluster + ansible.builtin.include_role: + name: dns-manager + vars: + host_name: "{{ cluster_name }}" + +- name: Open services for control plane + become: true + when: ansible_os_family == "Debian" + block: + - name: Open firewall ports for control plane + community.general.ufw: + rule: allow + name: "{{ item }}" + loop: "{{ kubernetes_services_control_plane }}" diff --git a/ansible/playbooks/roles/fastpass-additional-control-plane/tests/inventory b/ansible/playbooks/roles/fastpass-additional-control-plane/tests/inventory new file mode 100644 index 0000000..03ca42f --- /dev/null +++ b/ansible/playbooks/roles/fastpass-additional-control-plane/tests/inventory @@ -0,0 +1,3 @@ +#SPDX-License-Identifier: MIT-0 +localhost + diff --git a/ansible/playbooks/roles/fastpass-additional-control-plane/tests/test.yml b/ansible/playbooks/roles/fastpass-additional-control-plane/tests/test.yml new file mode 100644 index 0000000..50fcde7 --- /dev/null +++ b/ansible/playbooks/roles/fastpass-additional-control-plane/tests/test.yml @@ -0,0 +1,6 @@ +#SPDX-License-Identifier: MIT-0 +--- +- hosts: localhost + remote_user: root + roles: + - fastpass-additional-control-plane diff --git a/ansible/playbooks/roles/fastpass-additional-control-plane/vars/main.yml b/ansible/playbooks/roles/fastpass-additional-control-plane/vars/main.yml new file mode 100644 index 0000000..56bd5f1 --- /dev/null +++ b/ansible/playbooks/roles/fastpass-additional-control-plane/vars/main.yml @@ -0,0 +1,2 @@ +--- +# vars file for fastpass-additional-control-plane diff --git a/ansible/playbooks/roles/fastpass-first-control-plane/tasks/main.yml b/ansible/playbooks/roles/fastpass-first-control-plane/tasks/main.yml index aaf7219..c4a4e1a 100644 --- a/ansible/playbooks/roles/fastpass-first-control-plane/tasks/main.yml +++ b/ansible/playbooks/roles/fastpass-first-control-plane/tasks/main.yml @@ -1,11 +1,16 @@ --- # role: fastpass-first-control-plane # description: FastPass First Control Plane -# author: mk-labs +# author: Ryan Blundon # version: 1.0.0 # date: 2025-09-27 -# Open sevices for control plane +- name: Setup DNS record for cluster + ansible.builtin.include_role: + name: dns-manager + vars: + host_name: "{{ cluster_name }}" + - name: Open services for control plane become: true when: ansible_os_family == "Debian" @@ -14,8 +19,7 @@ community.general.ufw: rule: allow name: "{{ item }}" - loop: - "{{ kubernetes_services_control_plane }}" + loop: "{{ kubernetes_services_control_plane }}" - name: Create initial kubelet config file become: true @@ -23,20 +27,27 @@ dest: /var/lib/kubelet/config.yaml owner: root group: root - mode: '0644' + mode: "0644" content: | apiVersion: kubelet.config.k8s.io/v1beta1 kind: KubeletConfiguration cgroupDriver: systemd containerRuntimeEndpoint: unix:///run/containerd/containerd.sock -# - name: Initialize Kubernetes cluster -# become: true -# ansible.builtin.command: kubeadm init --ignore-preflight-errors=NumCPU,Mem --control-plane-endpoint=fastpass # {{ cluster_name }} -# args: -# creates: /etc/kubernetes/admin.conf -# register: kubeadm_init -# changed_when: kubeadm_init.rc == 0 +- name: Initialize Kubernetes cluster + become: true + ansible.builtin.command: + argv: + - kubeadm + - init + - --apiserver-advertise-address={{ ip_address }} + - --control-plane-endpoint={{ cluster_name }} + - --pod-network-cidr={{ pod_network_cidr }} + - --service-cidr={{ service_cidr }} + args: + creates: /etc/kubernetes/admin.conf + register: kubeadm_init + changed_when: kubeadm_init.rc == 0 - name: Ensure kubelet is enabled and started become: true @@ -44,23 +55,49 @@ name: kubelet enabled: true state: started - -- name: Debug ansible_env.HOME + +- name: Setup kubeconfig for FastPass cluster + ansible.builtin.include_role: + name: kubeconfig-manager + +# - name: Download tigera-operator manifest +# delegate_to: localhost +# ansible.builtin.get_url: +# url: https://raw.githubusercontent.com/projectcalico/calico/{{ calico_version }}/manifests/tigera-operator.yaml +# dest: /tmp/tigera-operator.yaml +# mode: "0644" + +# - name: Install tigera-operator from downloaded file +# delegate_to: localhost +# kubernetes.core.k8s: +# kubeconfig: "{{ local_home }}/.kube/config" +# state: present +# src: /tmp/tigera-operator.yaml + +# - name: Download Calico CRDs +# delegate_to: localhost +# ansible.builtin.get_url: +# url: https://raw.githubusercontent.com/projectcalico/calico/{{ calico_version }}/manifests/custom-resources.yaml +# dest: /tmp/custom-resources.yaml +# mode: "0644" + +# - name: Install Calico CRDs from downloaded file +# delegate_to: localhost +# kubernetes.core.k8s: +# kubeconfig: "{{ local_home }}/.kube/config" +# state: present +# src: /tmp/custom-resources.yaml + +- name: Download Flannel CNI delegate_to: localhost - ansible.builtin.debug: - var: ansible_env.HOME + ansible.builtin.get_url: + url: https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml + dest: /tmp/kube-flannel.yaml + mode: "0644" - -- name: Create .kube directory for user +- name: Install Flannel CNI from downloaded file delegate_to: localhost - ansible.builtin.file: - path: "{{ ansible_env.HOME }}/.kube" - state: directory - mode: '0755' - -- name: Copy admin.conf to user's .kube directory on controller - ansible.builtin.fetch: - src: /etc/kubernetes/admin.conf - dest: "{{ ansible_env.HOME }}/.kube/config-fastpass" # {{cluster_name}}" - mode: '0644' - \ No newline at end of file + kubernetes.core.k8s: + kubeconfig: "{{ local_home }}/.kube/config" + state: present + src: /tmp/kube-flannel.yaml diff --git a/ansible/playbooks/roles/fastpass-worker-nodes/README.md b/ansible/playbooks/roles/fastpass-worker-nodes/README.md new file mode 100644 index 0000000..225dd44 --- /dev/null +++ b/ansible/playbooks/roles/fastpass-worker-nodes/README.md @@ -0,0 +1,38 @@ +Role Name +========= + +A brief description of the role goes here. + +Requirements +------------ + +Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. + +Role Variables +-------------- + +A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well. + +Dependencies +------------ + +A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles. + +Example Playbook +---------------- + +Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: + + - hosts: servers + roles: + - { role: username.rolename, x: 42 } + +License +------- + +BSD + +Author Information +------------------ + +An optional section for the role authors to include contact information, or a website (HTML is not allowed). diff --git a/ansible/playbooks/roles/fastpass-worker-nodes/defaults/main.yml b/ansible/playbooks/roles/fastpass-worker-nodes/defaults/main.yml new file mode 100644 index 0000000..45e7909 --- /dev/null +++ b/ansible/playbooks/roles/fastpass-worker-nodes/defaults/main.yml @@ -0,0 +1,3 @@ +#SPDX-License-Identifier: MIT-0 +--- +# defaults file for fastpass-worker-nodes diff --git a/ansible/playbooks/roles/fastpass-worker-nodes/handlers/main.yml b/ansible/playbooks/roles/fastpass-worker-nodes/handlers/main.yml new file mode 100644 index 0000000..184b265 --- /dev/null +++ b/ansible/playbooks/roles/fastpass-worker-nodes/handlers/main.yml @@ -0,0 +1,3 @@ +#SPDX-License-Identifier: MIT-0 +--- +# handlers file for fastpass-worker-nodes diff --git a/ansible/playbooks/roles/fastpass-worker-nodes/meta/main.yml b/ansible/playbooks/roles/fastpass-worker-nodes/meta/main.yml new file mode 100644 index 0000000..36b9858 --- /dev/null +++ b/ansible/playbooks/roles/fastpass-worker-nodes/meta/main.yml @@ -0,0 +1,35 @@ +#SPDX-License-Identifier: MIT-0 +galaxy_info: + author: your name + description: your role description + company: your company (optional) + + # If the issue tracker for your role is not on github, uncomment the + # next line and provide a value + # issue_tracker_url: http://example.com/issue/tracker + + # Choose a valid license ID from https://spdx.org - some suggested licenses: + # - BSD-3-Clause (default) + # - MIT + # - GPL-2.0-or-later + # - GPL-3.0-only + # - Apache-2.0 + # - CC-BY-4.0 + license: license (GPL-2.0-or-later, MIT, etc) + + min_ansible_version: 2.1 + + # If this a Container Enabled role, provide the minimum Ansible Container version. + # min_ansible_container_version: + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is a keyword that describes + # and categorizes the role. Users find roles by searching for tags. Be sure to + # remove the '[]' above, if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of alphanumeric characters. + # Maximum 20 tags per role. + +dependencies: [] + # List your role dependencies here, one per line. Be sure to remove the '[]' above, + # if you add dependencies to this list. diff --git a/ansible/playbooks/roles/fastpass-worker-nodes/tasks/main.yml b/ansible/playbooks/roles/fastpass-worker-nodes/tasks/main.yml new file mode 100644 index 0000000..16683a8 --- /dev/null +++ b/ansible/playbooks/roles/fastpass-worker-nodes/tasks/main.yml @@ -0,0 +1,3 @@ +#SPDX-License-Identifier: MIT-0 +--- +# tasks file for fastpass-worker-nodes diff --git a/ansible/playbooks/roles/fastpass-worker-nodes/tests/inventory b/ansible/playbooks/roles/fastpass-worker-nodes/tests/inventory new file mode 100644 index 0000000..03ca42f --- /dev/null +++ b/ansible/playbooks/roles/fastpass-worker-nodes/tests/inventory @@ -0,0 +1,3 @@ +#SPDX-License-Identifier: MIT-0 +localhost + diff --git a/ansible/playbooks/roles/fastpass-worker-nodes/tests/test.yml b/ansible/playbooks/roles/fastpass-worker-nodes/tests/test.yml new file mode 100644 index 0000000..f165c18 --- /dev/null +++ b/ansible/playbooks/roles/fastpass-worker-nodes/tests/test.yml @@ -0,0 +1,6 @@ +#SPDX-License-Identifier: MIT-0 +--- +- hosts: localhost + remote_user: root + roles: + - fastpass-worker-nodes diff --git a/ansible/playbooks/roles/fastpass-worker-nodes/vars/main.yml b/ansible/playbooks/roles/fastpass-worker-nodes/vars/main.yml new file mode 100644 index 0000000..e2724c1 --- /dev/null +++ b/ansible/playbooks/roles/fastpass-worker-nodes/vars/main.yml @@ -0,0 +1,3 @@ +#SPDX-License-Identifier: MIT-0 +--- +# vars file for fastpass-worker-nodes diff --git a/ansible/playbooks/roles/kubeconfig-manager/README.md b/ansible/playbooks/roles/kubeconfig-manager/README.md new file mode 100644 index 0000000..b738559 --- /dev/null +++ b/ansible/playbooks/roles/kubeconfig-manager/README.md @@ -0,0 +1,86 @@ +# Kubeconfig Manager Role + +A reusable Ansible role for managing kubeconfig files across multiple Kubernetes clusters. + +## Features + +- Fetches kubeconfig from remote Kubernetes nodes +- Merges multiple cluster configs into a single `~/.kube/config` file +- Creates backups before merging +- Provides unique cluster, context, and user names +- Works with any Kubernetes cluster (vanilla K8s, OpenShift, etc.) + +## Requirements + +- Ansible 2.9+ +- Access to Kubernetes cluster admin.conf file +- Local kubectl installation (optional, for testing) + +## Role Variables + +| Variable | Default | Description | +|----------|---------|-------------| +| `cluster_name` | `kubernetes` | Name of the cluster (required) | +| `kubeconfig_source_path` | `/etc/kubernetes/admin.conf` | Path to kubeconfig on remote host | +| `context_suffix` | `admin` | Suffix for context name | + +## Example Usage + +### In a playbook: + +```yaml +- name: Setup kubeconfig for FastPass cluster + hosts: fastpass_control_plane[0] + roles: + - role: kubeconfig-manager + vars: + cluster_name: "fastpass" + +- name: Setup kubeconfig for Hub cluster + hosts: hub_cluster + roles: + - role: kubeconfig-manager + vars: + cluster_name: "hub" + kubeconfig_source_path: "/etc/kubernetes/admin.conf" +``` + +### As an included role: + +```yaml +- name: Manage kubeconfig + ansible.builtin.include_role: + name: kubeconfig-manager + vars: + cluster_name: "{{ my_cluster_name }}" +``` + +## Generated Structure + +The role creates contexts with this naming pattern: +- **Cluster**: `{{ cluster_name }}` +- **Context**: `{{ cluster_name }}-admin` +- **User**: `{{ cluster_name }}-admin` + +## File Structure + +``` +~/.kube/ +├── config # Merged kubeconfig +├── config-fastpass # Individual cluster configs +├── config-hub +├── config-internal +└── config.backup.1234567890 # Timestamped backups +``` + +## Dependencies + +None + +## License + +MIT + +## Author + +mk-labs \ No newline at end of file diff --git a/ansible/playbooks/roles/kubeconfig-manager/defaults/main.yml b/ansible/playbooks/roles/kubeconfig-manager/defaults/main.yml new file mode 100644 index 0000000..905980e --- /dev/null +++ b/ansible/playbooks/roles/kubeconfig-manager/defaults/main.yml @@ -0,0 +1,11 @@ +--- +# Default variables for kubeconfig-manager role + +# Source path for the kubeconfig file on the remote host +kubeconfig_source_path: "/etc/kubernetes/admin.conf" + +# Cluster name - should be provided by the calling playbook +cluster_name: "kubernetes" + +# Context suffix for the cluster +context_suffix: "admin" \ No newline at end of file diff --git a/ansible/playbooks/roles/kubeconfig-manager/tasks/main.yml b/ansible/playbooks/roles/kubeconfig-manager/tasks/main.yml new file mode 100644 index 0000000..67e02b9 --- /dev/null +++ b/ansible/playbooks/roles/kubeconfig-manager/tasks/main.yml @@ -0,0 +1,34 @@ +--- +# role: kubeconfig-manager +# description: Reusable role for managing kubeconfig files across multiple clusters +# author: mk-labs +# version: 1.0.0 + +- name: Get local user environment + delegate_to: localhost + ansible.builtin.set_fact: + local_home: "{{ lookup('env', 'HOME') }}" + local_user: "{{ lookup('env', 'USER') }}" + +- name: Debug local environment + delegate_to: localhost + ansible.builtin.debug: + msg: "Local user: {{ local_user }}, Home directory: {{ local_home }}" + +- name: Create .kube directory + delegate_to: localhost + ansible.builtin.file: + path: "{{ local_home }}/.kube" + state: directory + owner: "{{ local_user }}" + mode: "0755" + +- name: Copy kubeconfig from remote host + ansible.builtin.fetch: + src: "{{ kubeconfig_source_path | default('/etc/kubernetes/admin.conf') }}" + dest: "{{ local_home }}/.kube/config-{{ cluster_name }}" + flat: true + mode: "0644" + +- name: Include kubeconfig merge tasks + ansible.builtin.include_tasks: merge-kubeconfig.yml \ No newline at end of file diff --git a/ansible/playbooks/roles/kubeconfig-manager/tasks/merge-kubeconfig.yml b/ansible/playbooks/roles/kubeconfig-manager/tasks/merge-kubeconfig.yml new file mode 100644 index 0000000..5ad8c8f --- /dev/null +++ b/ansible/playbooks/roles/kubeconfig-manager/tasks/merge-kubeconfig.yml @@ -0,0 +1,103 @@ +--- +# Kubeconfig merging tasks + +- name: Check if main kubeconfig exists + delegate_to: localhost + ansible.builtin.stat: + path: "{{ local_home }}/.kube/config" + register: main_kubeconfig + +- name: Create backup of existing kubeconfig + delegate_to: localhost + ansible.builtin.copy: + src: "{{ local_home }}/.kube/config" + dest: "{{ local_home }}/.kube/config.backup.{{ ansible_date_time.epoch }}" + mode: "0644" + when: main_kubeconfig.stat.exists + +- name: Read new cluster kubeconfig + delegate_to: localhost + ansible.builtin.slurp: + src: "{{ local_home }}/.kube/config-{{ cluster_name }}" + register: new_kubeconfig_content + +- name: Parse new kubeconfig + delegate_to: localhost + ansible.builtin.set_fact: + new_kubeconfig: "{{ new_kubeconfig_content.content | b64decode | from_yaml }}" + +- name: Update cluster name in kubeconfig + delegate_to: localhost + ansible.builtin.set_fact: + updated_kubeconfig: + apiVersion: "{{ new_kubeconfig.apiVersion }}" + kind: "{{ new_kubeconfig.kind }}" + clusters: + - name: "{{ cluster_name }}" + cluster: "{{ new_kubeconfig.clusters[0].cluster }}" + contexts: + - name: "{{ cluster_name }}-admin" + context: + cluster: "{{ cluster_name }}" + user: "{{ cluster_name }}-admin" + users: + - name: "{{ cluster_name }}-admin" + user: "{{ new_kubeconfig.users[0].user }}" + current-context: "{{ cluster_name }}-admin" + +- name: Merge with existing kubeconfig or create new one + delegate_to: localhost + block: + - name: Read existing kubeconfig + ansible.builtin.slurp: + src: "{{ local_home }}/.kube/config" + register: existing_kubeconfig_content + when: main_kubeconfig.stat.exists + + - name: Parse existing kubeconfig + ansible.builtin.set_fact: + existing_kubeconfig: "{{ existing_kubeconfig_content.content | b64decode | from_yaml }}" + when: main_kubeconfig.stat.exists + + - name: Merge kubeconfigs + ansible.builtin.set_fact: + merged_kubeconfig: + apiVersion: "{{ existing_kubeconfig.apiVersion | default('v1') }}" + kind: "{{ existing_kubeconfig.kind | default('Config') }}" + clusters: "{{ (existing_kubeconfig.clusters | default([])) + updated_kubeconfig.clusters }}" + contexts: "{{ (existing_kubeconfig.contexts | default([])) + updated_kubeconfig.contexts }}" + users: "{{ (existing_kubeconfig.users | default([])) + updated_kubeconfig.users }}" + current-context: "{{ updated_kubeconfig['current-context'] }}" + when: main_kubeconfig.stat.exists + + - name: Use new kubeconfig as merged config + ansible.builtin.set_fact: + merged_kubeconfig: "{{ updated_kubeconfig }}" + when: not main_kubeconfig.stat.exists + +- name: Write merged kubeconfig + delegate_to: localhost + ansible.builtin.copy: + content: "{{ merged_kubeconfig | to_nice_yaml }}" + dest: "{{ local_home }}/.kube/config" + mode: "0644" + owner: "{{ local_user }}" + +- name: Display available contexts + delegate_to: localhost + ansible.builtin.debug: + msg: | + Kubeconfig updated successfully! + + Available contexts: + {% for context in merged_kubeconfig.contexts %} + - {{ context.name }} + {% endfor %} + + Current context: {{ merged_kubeconfig['current-context'] }} + + To switch contexts, use: + kubectl config use-context + + To list all contexts: + kubectl config get-contexts \ No newline at end of file diff --git a/ansible/playbooks/roles/kubernetes-prerequisites/tasks/main.yml b/ansible/playbooks/roles/kubernetes-prerequisites/tasks/main.yml index a229dd7..4c3b6b4 100644 --- a/ansible/playbooks/roles/kubernetes-prerequisites/tasks/main.yml +++ b/ansible/playbooks/roles/kubernetes-prerequisites/tasks/main.yml @@ -74,43 +74,3 @@ - name: 7 Install containerd ansible.builtin.include_role: name: containerd - -# - name: Create kubelet config directory -# ansible.builtin.file: -# path: /var/lib/kubelet -# state: directory -# owner: root -# group: root -# mode: '0755' - -# - name: Create initial kubelet config file -# ansible.builtin.copy: -# dest: /var/lib/kubelet/config.yaml -# owner: root -# group: root -# mode: '0644' -# content: | -# apiVersion: kubelet.config.k8s.io/v1beta1 -# kind: KubeletConfiguration -# cgroupDriver: systemd -# containerRuntimeEndpoint: unix:///run/containerd/containerd.sock - -# - name: Install CNI plugins via dnf -# ansible.builtin.dnf: -# name: containernetworking-plugins -# state: present - -# - name: Verify CNI plugins installation -# ansible.builtin.shell: ls -la /opt/cni/bin/ || echo "CNI plugins not found in /opt/cni/bin/" -# register: cni_plugins -# ignore_errors: true - -# - name: Display installed CNI plugins -# ansible.builtin.debug: -# msg: "CNI plugins status: {{ cni_plugins.stdout }}" - -# - name: Enable kubelet service (but don't start yet) -# ansible.builtin.systemd: -# name: kubelet -# enabled: true -# state: stopped diff --git a/ansible/playbooks/roles/traefik-manager/defaults/main.yml b/ansible/playbooks/roles/traefik-manager/defaults/main.yml new file mode 100644 index 0000000..cef5d50 --- /dev/null +++ b/ansible/playbooks/roles/traefik-manager/defaults/main.yml @@ -0,0 +1,12 @@ +--- +# Default variables for traefik-manager role + +# Traefik Configuration +traefik_config_dir: "/etc/traefik" +traefik_host: "{{ traefik_server | default(groups['traefik_servers'][0] | default('localhost')) }}" +cluster_api_port: 6443 + +# Cluster Configuration (to be provided by calling role) +# cluster_name: "fastpass" +# cluster_endpoint: "fastpass.local.mk-labs.cloud" +# control_plane_nodes: ["space-mountain", "big-thunder-mountain", "splash-mountain"] \ No newline at end of file diff --git a/ansible/playbooks/roles/traefik-manager/handlers/main.yml b/ansible/playbooks/roles/traefik-manager/handlers/main.yml new file mode 100644 index 0000000..71ea18d --- /dev/null +++ b/ansible/playbooks/roles/traefik-manager/handlers/main.yml @@ -0,0 +1,8 @@ +--- +# Handlers for traefik-manager role + +- name: reload traefik + ansible.builtin.systemd: + name: traefik + state: reloaded + delegate_to: "{{ traefik_host }}" \ No newline at end of file diff --git a/ansible/playbooks/roles/traefik-manager/tasks/main.yml b/ansible/playbooks/roles/traefik-manager/tasks/main.yml new file mode 100644 index 0000000..6083313 --- /dev/null +++ b/ansible/playbooks/roles/traefik-manager/tasks/main.yml @@ -0,0 +1,45 @@ +--- +# role: traefik-manager +# description: Reusable role for managing Traefik load balancer configuration +# author: mk-labs +# version: 1.0.0 + +- name: Create Traefik configuration directory + ansible.builtin.file: + path: "{{ traefik_config_dir }}/dynamic" + state: directory + mode: "0755" + delegate_to: "{{ traefik_host }}" + +- name: Generate Traefik TCP router configuration for Kubernetes API + ansible.builtin.template: + src: k8s-api-router.yml.j2 + dest: "{{ traefik_config_dir }}/dynamic/{{ cluster_name }}-api.yml" + mode: "0644" + delegate_to: "{{ traefik_host }}" + notify: reload traefik + +- name: Generate Traefik service configuration for control plane nodes + ansible.builtin.template: + src: k8s-api-service.yml.j2 + dest: "{{ traefik_config_dir }}/dynamic/{{ cluster_name }}-service.yml" + mode: "0644" + delegate_to: "{{ traefik_host }}" + notify: reload traefik + +- name: Verify Traefik configuration syntax + ansible.builtin.command: | + traefik --configfile={{ traefik_config_dir }}/traefik.yml --dry-run + delegate_to: "{{ traefik_host }}" + register: traefik_syntax_check + failed_when: traefik_syntax_check.rc != 0 + changed_when: false + +- name: Display Traefik configuration status + ansible.builtin.debug: + msg: | + ✅ Traefik configuration created successfully: + - Router: {{ cluster_name }}-api + - Service: {{ cluster_name }}-backend + - Endpoint: {{ cluster_endpoint }}:{{ cluster_api_port }} + - Backend nodes: {{ control_plane_nodes | join(', ') }} \ No newline at end of file diff --git a/ansible/playbooks/roles/traefik-manager/templates/k8s-api-router.yml.j2 b/ansible/playbooks/roles/traefik-manager/templates/k8s-api-router.yml.j2 new file mode 100644 index 0000000..c9d4a22 --- /dev/null +++ b/ansible/playbooks/roles/traefik-manager/templates/k8s-api-router.yml.j2 @@ -0,0 +1,23 @@ +--- +# Traefik TCP Router for {{ cluster_name }} Kubernetes API +tcp: + routers: + {{ cluster_name }}-api: + rule: "HostSNI(`{{ cluster_endpoint }}`)" + service: "{{ cluster_name }}-backend" + tls: + passthrough: true + entryPoints: + - "k8s-api" + + services: + {{ cluster_name }}-backend: + loadBalancer: + servers: +{% for node in control_plane_nodes %} + - address: "{{ hostvars[node]['ansible_default_ipv4']['address'] }}:{{ cluster_api_port }}" +{% endfor %} + healthCheck: + path: "/healthz" + interval: "10s" + timeout: "3s" \ No newline at end of file diff --git a/ansible/playbooks/tasks/add_technitium_dns_entry.yml b/ansible/playbooks/tasks/add_technitium_dns_entry.yml new file mode 100644 index 0000000..1ae4b9d --- /dev/null +++ b/ansible/playbooks/tasks/add_technitium_dns_entry.yml @@ -0,0 +1,20 @@ +--- +# Reusable task file for adding Technitium DNS entries +# This replaces the standalone playbook and can be imported into any playbook + +# - name: Display cluster_name +# ansible.builtin.debug: +# msg: "{{ host_name }} - {{ ip_address }} - {{ vault_technitium_api_key }}" + +- name: Create DNS A Record entry for {{ host_name }} + delegate_to: localhost + effectivelywild.technitium_dns.technitium_dns_add_record: + api_url: "http://{{ dns_server }}.{{ base_domain }}" + api_token: "{{ vault_technitium_api_key }}" + zone: "{{ base_domain }}" + name: "{{ host_name }}.{{ base_domain }}" + type: "A" + ipAddress: "{{ ip_address }}" + ptr: true + ttl: 360 + validate_certs: false diff --git a/ansible/playbooks/test-dns-cname.yml b/ansible/playbooks/test-dns-cname.yml new file mode 100644 index 0000000..da9cfb8 --- /dev/null +++ b/ansible/playbooks/test-dns-cname.yml @@ -0,0 +1,11 @@ +--- +- name: Test DNS CNAME Creation + hosts: fastpass_control_plane[0] + gather_facts: false + tasks: + - name: Test DNS CNAME entry creation + ansible.builtin.include_role: + name: dns-manager + vars: + cluster_endpoint: "{{ control_plane_endpoint }}" + cluster_cname_target: "{{ traefik_server }}.{{ base_domain }}" \ No newline at end of file diff --git a/ansible/playbooks/roles/requirements.yml b/ansible/requirements.yml similarity index 50% rename from ansible/playbooks/roles/requirements.yml rename to ansible/requirements.yml index 4ad69f8..43b195f 100644 --- a/ansible/playbooks/roles/requirements.yml +++ b/ansible/requirements.yml @@ -1,13 +1,16 @@ # requirements.yml +--- collections: - name: community.general version: 11.1.0 - - name: nccurry.openshift - version: 1.4.0 + # - name: nccurry.openshift + # version: 1.4.0 - name: somaz94.ansible_k8s_iac_tool version: 1.1.6 - - name: prometheus.prometheus - version: 0.27.0 \ No newline at end of file + # - name: prometheus.prometheus + # version: 0.27.0 + + - name: kubernetes.core diff --git a/ansible/scripts/migrate-dns-references.sh b/ansible/scripts/migrate-dns-references.sh new file mode 100644 index 0000000..0257740 --- /dev/null +++ b/ansible/scripts/migrate-dns-references.sh @@ -0,0 +1,82 @@ +#!/bin/bash + +# Migration script to update DNS entry references +# This script helps migrate from the old add_technitium_dns_entry.yml to the new modular approach + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +print_status() { + local status=$1 + local message=$2 + case $status in + "INFO") + echo -e "${BLUE}ℹ️ INFO${NC}: $message" + ;; + "SUCCESS") + echo -e "${GREEN}✅ SUCCESS${NC}: $message" + ;; + "ERROR") + echo -e "${RED}❌ ERROR${NC}: $message" + ;; + "WARN") + echo -e "${YELLOW}⚠️ WARN${NC}: $message" + ;; + esac +} + +print_status "INFO" "Migrating DNS entry references to modular approach..." + +# Search for references to the old playbook +OLD_PLAYBOOK="add_technitium_dns_entry.yml" +NEW_PLAYBOOK="add_dns_entry.yml" + +# Find all YAML files that might reference the old playbook +YAML_FILES=$(find . -name "*.yml" -type f | grep -v ".git") + +FOUND_REFERENCES=0 + +for file in $YAML_FILES; do + if grep -q "$OLD_PLAYBOOK" "$file" 2>/dev/null; then + print_status "WARN" "Found reference in: $file" + FOUND_REFERENCES=$((FOUND_REFERENCES + 1)) + + # Show the context + echo " Context:" + grep -n -B2 -A2 "$OLD_PLAYBOOK" "$file" | sed 's/^/ /' + echo "" + fi +done + +if [ $FOUND_REFERENCES -eq 0 ]; then + print_status "SUCCESS" "No references to $OLD_PLAYBOOK found" +else + print_status "INFO" "Found $FOUND_REFERENCES references to migrate" + print_status "INFO" "Migration options:" + echo "" + echo "1. Replace playbook imports:" + echo " OLD: - import_playbook: $OLD_PLAYBOOK" + echo " NEW: - import_playbook: $NEW_PLAYBOOK" + echo "" + echo "2. Use task includes in roles:" + echo " - ansible.builtin.include_tasks: tasks/add_technitium_dns_entry.yml" + echo "" + echo "3. Use the dns-manager role:" + echo " - ansible.builtin.include_role:" + echo " name: dns-manager" +fi + +# Check if the old playbook exists and suggest backup +if [ -f "playbooks/$OLD_PLAYBOOK" ]; then + print_status "INFO" "Old playbook exists at: playbooks/$OLD_PLAYBOOK" + print_status "INFO" "Consider backing it up before removing:" + echo " mv playbooks/$OLD_PLAYBOOK playbooks/${OLD_PLAYBOOK}.backup" +fi + +print_status "SUCCESS" "Migration analysis complete" \ No newline at end of file diff --git a/ansible/scripts/setup-cluster-network.sh b/ansible/scripts/setup-cluster-network.sh new file mode 100644 index 0000000..aa5b96b --- /dev/null +++ b/ansible/scripts/setup-cluster-network.sh @@ -0,0 +1,114 @@ +#!/bin/bash + +# FastPass Homelab - Cluster Network Setup Script +# This script sets up DNS (via Technitium) and load balancer configuration for any Kubernetes cluster + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Function to print colored output +print_status() { + local status=$1 + local message=$2 + case $status in + "INFO") + echo -e "${BLUE}ℹ️ INFO${NC}: $message" + ;; + "SUCCESS") + echo -e "${GREEN}✅ SUCCESS${NC}: $message" + ;; + "ERROR") + echo -e "${RED}❌ ERROR${NC}: $message" + ;; + "WARN") + echo -e "${YELLOW}⚠️ WARN${NC}: $message" + ;; + esac +} + +# Usage function +usage() { + echo "Usage: $0 " + echo "" + echo "Examples:" + echo " $0 fastpass fastpass.local.mk-labs.cloud fastpass_control_plane" + echo " $0 hub hub.local.mk-labs.cloud hub_cluster" + echo " $0 internal internal.local.mk-labs.cloud internal_cluster" + echo "" + echo "This script will:" + echo " 1. Create DNS entry for the cluster endpoint" + echo " 2. Configure Traefik load balancer" + echo " 3. Test connectivity" + echo "" + exit 1 +} + +# Check arguments +if [ $# -ne 3 ]; then + print_status "ERROR" "Invalid number of arguments" + usage +fi + +CLUSTER_NAME=$1 +CLUSTER_ENDPOINT=$2 +CONTROL_PLANE_GROUP=$3 + +print_status "INFO" "Setting up network for cluster: $CLUSTER_NAME" +print_status "INFO" "Endpoint: $CLUSTER_ENDPOINT" +print_status "INFO" "Control plane group: $CONTROL_PLANE_GROUP" + +# Check if inventory file exists +if [ ! -f "inventory.yml" ]; then + print_status "ERROR" "inventory.yml not found. Please run from ansible directory." + exit 1 +fi + +# Create temporary playbook +TEMP_PLAYBOOK=$(mktemp /tmp/cluster-network-setup-XXXXXX.yml) +cat > "$TEMP_PLAYBOOK" << EOF +--- +- name: Setup network infrastructure for $CLUSTER_NAME + hosts: ${CONTROL_PLANE_GROUP}[0] + gather_facts: true + tasks: + - name: Setup cluster network infrastructure + ansible.builtin.include_role: + name: cluster-network-setup + vars: + cluster_name: "$CLUSTER_NAME" + cluster_endpoint: "$CLUSTER_ENDPOINT" + cluster_vip: "{{ ansible_default_ipv4.address }}" + control_plane_nodes: "{{ groups['$CONTROL_PLANE_GROUP'] }}" +EOF + +print_status "INFO" "Running network setup playbook..." + +# Run the network setup +if ansible-playbook -i inventory.yml "$TEMP_PLAYBOOK"; then + print_status "SUCCESS" "Network setup completed for $CLUSTER_NAME" + + # Test connectivity + print_status "INFO" "Testing connectivity to $CLUSTER_ENDPOINT:6443..." + if timeout 10 bash -c " " + echo "" + echo "Examples:" + echo " $0 fastpass fastpass_control_plane[0]" + echo " $0 hub hub_cluster" + echo " $0 internal internal_cluster[0]" + echo "" + echo "Available clusters in your homelab:" + echo " - fastpass (FastPass Kubernetes cluster)" + echo " - hub (OpenShift Hub cluster)" + echo " - internal (Internal OpenShift cluster)" + echo "" + exit 1 +} + +# Check arguments +if [ $# -ne 2 ]; then + print_status "ERROR" "Invalid number of arguments" + usage +fi + +CLUSTER_NAME=$1 +HOST_GROUP=$2 + +print_status "INFO" "Setting up kubeconfig for cluster: $CLUSTER_NAME" +print_status "INFO" "Target hosts: $HOST_GROUP" + +# Check if inventory file exists +if [ ! -f "inventory.yml" ]; then + print_status "ERROR" "inventory.yml not found. Please run from ansible directory." + exit 1 +fi + +# Run the kubeconfig setup +print_status "INFO" "Running Ansible playbook..." + +ansible-playbook -i inventory.yml \ + playbooks/examples/multi-cluster-kubeconfig.yml \ + --limit "$HOST_GROUP" \ + -e "target_cluster_hosts=$HOST_GROUP" \ + -e "target_cluster_name=$CLUSTER_NAME" \ + --tags kubeconfig + +if [ $? -eq 0 ]; then + print_status "SUCCESS" "Kubeconfig setup completed for $CLUSTER_NAME" + print_status "INFO" "You can now use: kubectl config use-context ${CLUSTER_NAME}-admin" + + # Show available contexts + echo "" + print_status "INFO" "Available contexts:" + kubectl config get-contexts 2>/dev/null || print_status "WARN" "kubectl not found or kubeconfig not accessible" +else + print_status "ERROR" "Kubeconfig setup failed" + exit 1 +fi \ No newline at end of file diff --git a/ansible/scripts/test-fastpass-deployment.sh b/ansible/scripts/test-fastpass-deployment.sh old mode 100755 new mode 100644 diff --git a/ansible/test-fastpass-role.yml b/ansible/test-fastpass-role.yml new file mode 100644 index 0000000..a69e1fe --- /dev/null +++ b/ansible/test-fastpass-role.yml @@ -0,0 +1,9 @@ +--- +- name: Test FastPass First Control Plane Role + hosts: localhost + gather_facts: true + vars: + cluster_name: "fastpass" + kubernetes_services_control_plane: [] + roles: + - role: playbooks/roles/fastpass-first-control-plane \ No newline at end of file diff --git a/calendar-sync.applescript b/calendar-sync.applescript new file mode 100644 index 0000000..f813893 --- /dev/null +++ b/calendar-sync.applescript @@ -0,0 +1,161 @@ +(* + Calendar Sync Script + + Synchronizes calendar events between two calendar accounts for the current day. + Reads events from a source calendar and mirrors them to a destination calendar, + including removal of events that no longer exist in the source. +*) + +-- Configuration Properties +property sourceAccountName : "Work Account" +property sourceCalendarName : "Main Calendar" +property destinationAccountName : "Personal Account" +property destinationCalendarName : "Synced Events" +property enableLogging : true +property enableDebugMode : false + +-- Logging levels +property LOG_ERROR : 1 +property LOG_WARNING : 2 +property LOG_INFO : 3 +property LOG_DEBUG : 4 + +-- Global variables for tracking sync state +global syncResults +global errorList + +-- Initialize sync results record +on initializeSyncResults() + set syncResults to {eventsCreated:0, eventsUpdated:0, eventsRemoved:0, eventsSkipped:0, errors:{}} + set errorList to {} +end initializeSyncResults + +-- Main entry point +on run + try + -- Initialize logging and sync tracking + initializeSyncResults() + logMessage("Starting Calendar Sync", LOG_INFO) + + -- Display configuration + logMessage("Source: " & sourceAccountName & " -> " & sourceCalendarName, LOG_INFO) + logMessage("Destination: " & destinationAccountName & " -> " & destinationCalendarName, LOG_INFO) + + -- TODO: Implement main sync workflow + logMessage("Calendar sync setup complete", LOG_INFO) + + on error errorMessage number errorNumber + handleError("Main execution error: " & errorMessage, errorNumber) + end try +end run + +-- Logging and Error Handling Framework + +-- Log a message with specified level +on logMessage(message, level) + if not enableLogging then return + + set levelText to getLevelText(level) + set timestamp to (current date) as string + set logEntry to "[" & timestamp & "] " & levelText & ": " & message + + -- Display to user (can be modified to write to file if needed) + if level ≤ LOG_WARNING or enableDebugMode then + display notification message with title "Calendar Sync " & levelText + end if + + -- Always log errors and warnings to console + if level ≤ LOG_WARNING then + log logEntry + else if enableDebugMode then + log logEntry + end if +end logMessage + +-- Get text representation of log level +on getLevelText(level) + if level = LOG_ERROR then + return "ERROR" + else if level = LOG_WARNING then + return "WARNING" + else if level = LOG_INFO then + return "INFO" + else if level = LOG_DEBUG then + return "DEBUG" + else + return "UNKNOWN" + end if +end getLevelText + +-- Handle errors with logging and user feedback +on handleError(errorMessage, errorNumber) + set fullErrorMessage to errorMessage & " (Error " & errorNumber & ")" + + -- Log the error + logMessage(fullErrorMessage, LOG_ERROR) + + -- Add to error list for reporting + set end of errorList to fullErrorMessage + + -- Display user-friendly error dialog + display dialog "Calendar Sync Error: " & errorMessage buttons {"OK"} default button "OK" with icon stop +end handleError + +-- Display progress to user +on displayProgress(currentItem, totalItems, itemDescription) + if not enableLogging then return + + set progressPercent to round ((currentItem / totalItems) * 100) + set progressMessage to "Processing " & itemDescription & " (" & currentItem & " of " & totalItems & " - " & progressPercent & "%)" + + logMessage(progressMessage, LOG_INFO) +end displayProgress + +-- Display final sync summary +on showSyncSummary() + set summaryMessage to "Sync Complete!" & return & return + set summaryMessage to summaryMessage & "Events Created: " & (eventsCreated of syncResults) & return + set summaryMessage to summaryMessage & "Events Updated: " & (eventsUpdated of syncResults) & return + set summaryMessage to summaryMessage & "Events Removed: " & (eventsRemoved of syncResults) & return + set summaryMessage to summaryMessage & "Events Skipped: " & (eventsSkipped of syncResults) & return + + if (count of errorList) > 0 then + set summaryMessage to summaryMessage & return & "Errors encountered: " & (count of errorList) + end if + + logMessage(summaryMessage, LOG_INFO) + display dialog summaryMessage buttons {"OK"} default button "OK" with icon note +end showSyncSummary + +-- Validate configuration before starting sync +on validateConfiguration() + logMessage("Validating configuration...", LOG_DEBUG) + + -- Check that required properties are set + if sourceAccountName = "" or sourceCalendarName = "" then + handleError("Source calendar configuration is incomplete", -1) + return false + end if + + if destinationAccountName = "" or destinationCalendarName = "" then + handleError("Destination calendar configuration is incomplete", -2) + return false + end if + + logMessage("Configuration validation passed", LOG_DEBUG) + return true +end validateConfiguration + +-- Utility function to get current date for today's events +on getCurrentDate() + return current date +end getCurrentDate + +-- Utility function to create date range for current day +on getCurrentDayRange() + set today to getCurrentDate() + set startOfDay to date (short date string of today) + set endOfDay to startOfDay + (24 * hours) - 1 + + return {startDate:startOfDay, endDate:endOfDay} +end getCurrentDayRange \ No newline at end of file diff --git a/infra-config/04-vm-templates/fedora-42/fedora-42-large-plus.pkrvars.hcl b/infra-config/04-vm-templates/fedora-42/fedora-42-large-plus.pkrvars.hcl old mode 100755 new mode 100644 diff --git a/infra-config/04-vm-templates/fedora-42/fedora-42-large.pkrvars.hcl b/infra-config/04-vm-templates/fedora-42/fedora-42-large.pkrvars.hcl old mode 100755 new mode 100644 diff --git a/infra-config/04-vm-templates/fedora-42/fedora-42-medium.pkrvars.hcl b/infra-config/04-vm-templates/fedora-42/fedora-42-medium.pkrvars.hcl old mode 100755 new mode 100644 diff --git a/infra-config/04-vm-templates/fedora-42/fedora-42-small.pkrvars.hcl b/infra-config/04-vm-templates/fedora-42/fedora-42-small.pkrvars.hcl old mode 100755 new mode 100644 diff --git a/infra-config/04-vm-templates/fedora-42/fedora-42-xlarge-plus.pkrvars.hcl b/infra-config/04-vm-templates/fedora-42/fedora-42-xlarge-plus.pkrvars.hcl old mode 100755 new mode 100644 diff --git a/infra-config/04-vm-templates/fedora-42/fedora-42-xlarge.pkrvars.hcl b/infra-config/04-vm-templates/fedora-42/fedora-42-xlarge.pkrvars.hcl old mode 100755 new mode 100644 diff --git a/infra-config/04-vm-templates/fedora-42/fedora-42.pkr.hcl b/infra-config/04-vm-templates/fedora-42/fedora-42.pkr.hcl old mode 100755 new mode 100644 diff --git a/infra-config/04-vm-templates/fedora-42/variables.pkrvars-xlarge.hcl b/infra-config/04-vm-templates/fedora-42/variables.pkrvars-xlarge.hcl old mode 100755 new mode 100644 diff --git a/infra-config/04-vm-templates/ubuntu-24.04.03/ubuntu-24.04.pkr.hcl b/infra-config/04-vm-templates/ubuntu-24.04.03/ubuntu-24.04.pkr.hcl old mode 100755 new mode 100644 diff --git a/infra-config/04-vm-templates/ubuntu-24.04.03/ubuntu-24.04.pkrvars.hcl b/infra-config/04-vm-templates/ubuntu-24.04.03/ubuntu-24.04.pkrvars.hcl old mode 100755 new mode 100644 diff --git a/infra-config/04-vm-templates/ubuntu-24.04.03/vm-large-plus.pkrvars.hcl b/infra-config/04-vm-templates/ubuntu-24.04.03/vm-large-plus.pkrvars.hcl old mode 100755 new mode 100644 diff --git a/infra-config/04-vm-templates/ubuntu-24.04.03/vm-large.pkrvars.hcl b/infra-config/04-vm-templates/ubuntu-24.04.03/vm-large.pkrvars.hcl old mode 100755 new mode 100644 diff --git a/infra-config/04-vm-templates/ubuntu-24.04.03/vm-medium.pkrvars.hcl b/infra-config/04-vm-templates/ubuntu-24.04.03/vm-medium.pkrvars.hcl old mode 100755 new mode 100644 diff --git a/infra-config/04-vm-templates/ubuntu-24.04.03/vm-small.pkrvars.hcl b/infra-config/04-vm-templates/ubuntu-24.04.03/vm-small.pkrvars.hcl old mode 100755 new mode 100644 diff --git a/infra-config/04-vm-templates/ubuntu-24.04.03/vm-xlarge-plus.pkrvars.hcl b/infra-config/04-vm-templates/ubuntu-24.04.03/vm-xlarge-plus.pkrvars.hcl old mode 100755 new mode 100644 diff --git a/infra-config/04-vm-templates/ubuntu-24.04.03/vm-xlarge.pkrvars.hcl b/infra-config/04-vm-templates/ubuntu-24.04.03/vm-xlarge.pkrvars.hcl old mode 100755 new mode 100644 diff --git a/step-by-step.md b/step-by-step.md index d521346..bd8f3d5 100644 --- a/step-by-step.md +++ b/step-by-step.md @@ -38,6 +38,28 @@ May refactor folder structure to: ansible-vault create vault ``` +To set up the virtual environment, follow these steps: + +1. Create a virtual environment named `venv-ansible`: + + ```bash + python3 -m venv ~/venv-ansible + ``` + +2. Activate the virtual environment: + + ```bash + source ~/venv-ansible/bin/activate + ``` + +3. Install the required packages: + + ```bash + pip install -r /requirements.txt + ``` +ansible-galaxy collection install -r ansible/requirements.yml + + - Modify ansible variables for your environment ## [Network](00-network/README.md) *Manual* @@ -73,7 +95,7 @@ May refactor folder structure to: ssh infra01 cd homelab - ansible-galaxy collection install -r requirements.yml + ansible-galaxy collection install -r ansible/requirements.yml ansible-playbook -i inventory.yml 10-sno-hub-cluster/install.yml ``` diff --git a/tmp/Chart.yaml b/tmp/Chart.yaml deleted file mode 100644 index 7006e89..0000000 --- a/tmp/Chart.yaml +++ /dev/null @@ -1,30 +0,0 @@ -apiVersion: v2 -name: external-secrets -description: A Helm chart for Kubernetes - -# A chart can be either an 'application' or a 'library' chart. -# -# Application charts are a collection of templates that can be packaged into versioned archives -# to be deployed. -# -# Library charts provide useful utilities or functions for the chart developer. They're included as -# a dependency of application charts to inject those utilities and functions into the rendering -# pipeline. Library charts do not define any templates and therefore cannot be deployed. -type: application - -# This is the chart version. This version number should be incremented each time you make changes -# to the chart and its templates, including the app version. -# Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.0 - -# This is the version number of the application being deployed. This version number should be -# incremented each time you make changes to the application. Versions are not expected to -# follow Semantic Versioning. They should reflect the version the application is using. -# It is recommended to use it with quotes. -appVersion: "0.16.1" - -dependencies: -- name: external-secrets - version: "0.16.1" - repository: https://charts.external-secrets.io/ - condition: external-secrets.enabled diff --git a/tmp/acm-hub-bootstrap-old/.gitignore b/tmp/acm-hub-bootstrap-old/.gitignore deleted file mode 100644 index 5c083b8..0000000 --- a/tmp/acm-hub-bootstrap-old/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -sealed-secrets-key.yaml -slack-token-key.yaml -*-private.yaml -eso-token-*.yaml \ No newline at end of file diff --git a/tmp/acm-hub-bootstrap-old/README.md b/tmp/acm-hub-bootstrap-old/README.md deleted file mode 100644 index ce0c676..0000000 --- a/tmp/acm-hub-bootstrap-old/README.md +++ /dev/null @@ -1,38 +0,0 @@ -### Introduction - -This repository is used to bootstrap the RHACM Hub cluster as well as hold the ACM configuration -I use in my homelab environment. It is referenced by the [cluster-config](https://github.com/gnunn-gitops/cluster-config) repo for the `local.hub` cluster's ACM applications (Hub, Policies and Observerability). - -From the perspective of bootstrapping the Hub there are a couple of different ways to go. You could -manually install OpenShift GitOps and have it bootstrap everything on the Hub including RHACM. However while -I did consider that approach I'm using ACM to bootstrap my managed clusters and I wanted to use the exact same workflow -if I could for the Hub. This is because I wanted to avoid having to create a tweaked workflow just for the Hub. - -### Bootstrap Process - -The bootstrap process, encapsulated in the `bootstrap.sh` script, is as follows: - -1. Install the RHACM operator and wait for it to complete -2. Install the MultiClusterHub custom resource and wait for it to be in the Running phase -3. Deploy all of the RHACM policies including the policy that deploys the OpenShift -GitOps operator with the bootstrap application -4. Label the Hub cluster, `local-cluster`, with the label `gitops=local.hub`. This trigger the -GitOps policy we deployed in step #3 to install OpenShift GitOps on the Hub cluster and -deploy the bootstrap application pointing to the repo and path needed for this cluster, i.e. -`local.home` - -At this point the GitOps operator deploys everything the Hub cluster requires including storage, operators, etc -as well as other ACM components. In particular, the components that the script deployed (Hub + Policies) have -Argo applications that will take over managing these. - -With the script bootstrapping the Hub because a one command affair. Once the command completes successfully -I walk away for 20-30 minutes while everything gets sorted out. - -### Side-note on LVM Operator - -If you are running a SNO cluster like I am and using the LVM Operator make sure that whatever device you are -using for storage with it is free. For example, if you are doing a reinstall of the hub (or other cluster), after -the cluster is provisioned but before you provision Day 2 ops ssh to the cluster and run `lsblk` to make sure -the device is empty with no partitions. - -A reminder for future me. :) \ No newline at end of file diff --git a/tmp/acm-hub-bootstrap-old/bootstrap.sh b/tmp/acm-hub-bootstrap-old/bootstrap.sh deleted file mode 100755 index be9010f..0000000 --- a/tmp/acm-hub-bootstrap-old/bootstrap.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash - -LANG=C -SLEEP_SECONDS=30 - -echo "" -echo "Installing RHACM Operator." - -kustomize build github.com/redhat-cop/gitops-catalog/advanced-cluster-management/operator/overlays/release-2.9 | oc apply -f - - -echo "Pause $SLEEP_SECONDS seconds for the creation of the rhacm-operator..." -sleep $SLEEP_SECONDS - -echo "Waiting for operator to start" -until oc get deployment multiclusterhub-operator -n open-cluster-management -do - sleep 10; -done - -echo "Installing the MultiClusterHub" - -kustomize build github.com/redhat-cop/gitops-catalog/advanced-cluster-management/instance/base | oc apply -f - - -echo "Waiting for hub to be installed" - -until [[ $(oc get multiclusterhub multiclusterhub -n open-cluster-management -o jsonpath='{.status.phase}') == 'Running' ]] -do - echo "Waiting for hub, current status:" - oc get multiclusterhub multiclusterhub -n open-cluster-management - sleep 10 -done - -echo "Installing policies and initial secrets" - -kustomize build bootstrap/secrets/base | oc apply -f - -kustomize build bootstrap/policies/overlays/default --enable-alpha-plugins | oc apply -f - - -echo "Labeling cluster with 'gitops: local.home'" -oc label managedcluster local-cluster gitops=local.hub --overwrite=true - -echo "Check policy compliance with the following command:" -echo " oc get policy -A" - -echo "Once GitOps configuration is complete you may need to run the following to fix Unknown status\n" -echo " oc delete secret local-cluster-import -n local-cluster\n" diff --git a/tmp/acm-hub-bootstrap-old/bootstrap/install-gitops/README.md b/tmp/acm-hub-bootstrap-old/bootstrap/install-gitops/README.md deleted file mode 100644 index 7346b2b..0000000 --- a/tmp/acm-hub-bootstrap-old/bootstrap/install-gitops/README.md +++ /dev/null @@ -1 +0,0 @@ -Experimental, not used at the momentgit add \ No newline at end of file diff --git a/tmp/acm-hub-bootstrap-old/bootstrap/install-gitops/setup.sh b/tmp/acm-hub-bootstrap-old/bootstrap/install-gitops/setup.sh deleted file mode 100644 index 77a8973..0000000 --- a/tmp/acm-hub-bootstrap-old/bootstrap/install-gitops/setup.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/bash - -LANG=C -SLEEP_SECONDS=45 - -echo "" -echo "Installing GitOps Operator." - -kustomize build ../../components/policies/gitops/base/manifests/gitops-subscription | oc apply -f - - -echo "Pause $SLEEP_SECONDS seconds for the creation of the gitops-operator..." -sleep $SLEEP_SECONDS - -echo "Waiting for operator to start" -until oc get deployment gitops-operator-controller-manager -n openshift-operators -do - sleep 5; -done - -echo "Waiting for openshift-gitops namespace to be created" -until oc get ns openshift-gitops -do - sleep 5; -done - -echo "Waiting for deployments to start" -until oc get deployment cluster -n openshift-gitops -do - sleep 5; -done - -echo "Waiting for all pods to be created" -deployments=(cluster kam openshift-gitops-applicationset-controller openshift-gitops-redis openshift-gitops-repo-server openshift-gitops-server) -for i in "${deployments[@]}"; -do - echo "Waiting for deployment $i"; - oc rollout status deployment $i -n openshift-gitops -done - -echo "Apply overlay to override default instance" -# echo "Create default instance of gitops operator" -kustomize build ../../components/policies/gitops/base/manifests/gitops-instance/base | - yq -y ".spec.repo.env |= map(select(.name == \"INFRASTRUCTURE_ID\").value=\"$INFRASTRUCTURE_ID\")" | - yq -y ".spec.repo.env |= map(select(.name == \"CLUSTER_ID\").value=\"$CLUSTER_ID\")" | - yq -y ".spec.repo.env |= map(select(.name == \"CLUSTER_NAME\").value=\"$CLUSTER_NAME\")" | - yq -y ".spec.repo.env |= map(select(.name == \"SUB_DOMAIN\").value=\"$SUB_DOMAIN\")" | - oc apply -f - - -sleep 10 -echo "Waiting for all pods to redeploy" -deployments=(cluster kam openshift-gitops-applicationset-controller openshift-gitops-redis openshift-gitops-repo-server openshift-gitops-server) -for i in "${deployments[@]}"; -do - echo "Waiting for deployment $i"; - oc rollout status deployment $i -n openshift-gitops -done - -echo "GitOps Operator ready" \ No newline at end of file diff --git a/tmp/acm-hub-bootstrap-old/bootstrap/policies/overlays/default/kustomization.yaml b/tmp/acm-hub-bootstrap-old/bootstrap/policies/overlays/default/kustomization.yaml deleted file mode 100644 index 8159677..0000000 --- a/tmp/acm-hub-bootstrap-old/bootstrap/policies/overlays/default/kustomization.yaml +++ /dev/null @@ -1,8 +0,0 @@ -namespace: acm-policies - -namespace: acm-policies - -resources: -# - ../../../../components/policies/compliance/base -- ../../../../components/policies/cert-expiration/base -- ../../../../components/policies/gitops/base diff --git a/tmp/acm-hub-bootstrap-old/bootstrap/secrets/base/README.md b/tmp/acm-hub-bootstrap-old/bootstrap/secrets/base/README.md deleted file mode 100644 index 02dd1cc..0000000 --- a/tmp/acm-hub-bootstrap-old/bootstrap/secrets/base/README.md +++ /dev/null @@ -1 +0,0 @@ -Bootstrap tokens for ESO to access Doppler projects, note that these secrets are not in git. \ No newline at end of file diff --git a/tmp/acm-hub-bootstrap-old/bootstrap/secrets/base/hub-secrets-namespace.yaml b/tmp/acm-hub-bootstrap-old/bootstrap/secrets/base/hub-secrets-namespace.yaml deleted file mode 100644 index c27f512..0000000 --- a/tmp/acm-hub-bootstrap-old/bootstrap/secrets/base/hub-secrets-namespace.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: hub-secrets diff --git a/tmp/acm-hub-bootstrap-old/bootstrap/secrets/base/kustomization.yaml b/tmp/acm-hub-bootstrap-old/bootstrap/secrets/base/kustomization.yaml deleted file mode 100644 index 4ccb786..0000000 --- a/tmp/acm-hub-bootstrap-old/bootstrap/secrets/base/kustomization.yaml +++ /dev/null @@ -1,10 +0,0 @@ -resources: -- namespace.yaml -- hub-secrets-namespace.yaml -# Note these secrets are not stored in git and only applied during bootstrap process -# They are the tokens for accessing the Doppler secrets SaaS service where secrets are stored -- eso-token-cluster-push-secret.yaml -- eso-token-cluster-home-secret.yaml -- eso-token-cluster-hub-secret.yaml -- eso-token-cluster-rhdp-secret.yaml -- eso-token-cluster-microshift-secret.yaml diff --git a/tmp/acm-hub-bootstrap-old/bootstrap/secrets/base/namespace.yaml b/tmp/acm-hub-bootstrap-old/bootstrap/secrets/base/namespace.yaml deleted file mode 100644 index 0d05982..0000000 --- a/tmp/acm-hub-bootstrap-old/bootstrap/secrets/base/namespace.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - annotations: - openshift.io/description: ACM Policies - openshift.io/display-name: ACM Policies - labels: - name: acm-policies diff --git a/tmp/acm-hub-bootstrap-old/components/apps/acm/overlays/hub/kustomization.yaml b/tmp/acm-hub-bootstrap-old/components/apps/acm/overlays/hub/kustomization.yaml deleted file mode 100644 index 1ecabad..0000000 --- a/tmp/acm-hub-bootstrap-old/components/apps/acm/overlays/hub/kustomization.yaml +++ /dev/null @@ -1,12 +0,0 @@ -resources: -- github.com/redhat-cop/gitops-catalog/advanced-cluster-management/operator/overlays/release-2.12 -- github.com/redhat-cop/gitops-catalog/advanced-cluster-management/instance/base - -patches: - - patch: |- - - op: replace - path: /spec/channel - value: 'release-2.13' - target: - kind: Subscription - name: advanced-cluster-management diff --git a/tmp/acm-hub-bootstrap-old/components/apps/acm/overlays/observability/custom-metrics-allowlist.yaml b/tmp/acm-hub-bootstrap-old/components/apps/acm/overlays/observability/custom-metrics-allowlist.yaml deleted file mode 100644 index 97a591f..0000000 --- a/tmp/acm-hub-bootstrap-old/components/apps/acm/overlays/observability/custom-metrics-allowlist.yaml +++ /dev/null @@ -1,31 +0,0 @@ -kind: ConfigMap -apiVersion: v1 -metadata: - name: observability-metrics-custom-allowlist - namespace: open-cluster-management-observability -data: - metrics_list.yaml: | - names: - - argocd_cluster_info - - argocd-server-metrics - - argocd_app_info - - argocd_app_sync_total - - argocd_app_reconcile_count - - argocd_app_reconcile_bucket - - argocd_app_k8s_request_total - - argocd_kubectl_exec_pending - - argocd-metrics - - argocd_cluster_api_resource_objects - - argocd_cluster_api_resources - - argocd_cluster_events_total - - argocd_git_request_total - - argocd_git_request_duration_seconds_bucket - - argocd-repo-server - - argocd_redis_request_total - - process_start_time_seconds - - workqueue_depth - - go_memstats_heap_alloc_bytes - - process_cpu_seconds_total - - go_goroutines - - go_gc_duration_seconds - - grpc_server_handled_total \ No newline at end of file diff --git a/tmp/acm-hub-bootstrap-old/components/apps/acm/overlays/observability/gitops-dashboard.json b/tmp/acm-hub-bootstrap-old/components/apps/acm/overlays/observability/gitops-dashboard.json deleted file mode 100644 index bc87db0..0000000 --- a/tmp/acm-hub-bootstrap-old/components/apps/acm/overlays/observability/gitops-dashboard.json +++ /dev/null @@ -1,4212 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "id": 1, - "iteration": 1605574886303, - "links": [], - "panels": [ - { - "collapsed": false, - "datasource": "$datasource", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 68, - "panels": [], - "title": "Overview", - "type": "row" - }, - { - "content": "![argoimage](https://avatars1.githubusercontent.com/u/30269780?s=110&v=4)", - "datasource": "$datasource", - "gridPos": { - "h": 4, - "w": 2, - "x": 0, - "y": 1 - }, - "id": 26, - "links": [], - "mode": "markdown", - "options": {}, - "title": "", - "transparent": true, - "type": "text" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 4, - "w": 3, - "x": 2, - "y": 1 - }, - "id": 32, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "options": {}, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "count(count by (cluster) (argocd_cluster_info{namespace=~\"$namespace\",cluster=~\"$host\"}))", - "format": "time_series", - "instant": false, - "intervalFactor": 1, - "refId": "A" - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Clusters", - "description": "Number of clusters hosting Argo CD", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "0", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "$datasource", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "gridPos": { - "h": 4, - "w": 3, - "x": 5, - "y": 1 - }, - "id": 94, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "options": {}, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "count(count by (cluster,namespace) (argocd_cluster_info{namespace=~\"$namespace\",cluster=~\"$host\"}))", - "format": "time_series", - "instant": false, - "intervalFactor": 1, - "refId": "A" - } - ], - "thresholds": "", - "timeFrom": null, - "timeShift": null, - "title": "Instances", - "description": "Total number of Argo CD instances", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "0", - "value": "null" - } - ], - "valueName": "current" - }, - { - "id": 23763571883, - "gridPos": { - "h": 4, - "w": 3, - "x": 8, - "y": 1 - }, - "type": "piechart", - "title": "Health Status", - "datasource": "$datasource", - "description": "Application Health Status", - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "tooltip": false, - "viz": false, - "legend": false - } - }, - "color": { - "mode": "palette-classic" - }, - "mappings": [] - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Degraded" - }, - "properties": [ - { - "id": "color", - "value": { - "mode": "fixed", - "fixedColor": "semi-dark-red" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Healthy" - }, - "properties": [ - { - "id": "color", - "value": { - "mode": "fixed", - "fixedColor": "green" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Progressing" - }, - "properties": [ - { - "id": "color", - "value": { - "mode": "fixed", - "fixedColor": "semi-dark-blue" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Missing" - }, - "properties": [ - { - "id": "color", - "value": { - "mode": "fixed", - "fixedColor": "semi-dark-orange" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Unknown" - }, - "properties": [ - { - "id": "color", - "value": { - "mode": "fixed", - "fixedColor": "rgb(255, 255, 255)" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Suspended" - }, - "properties": [ - { - "id": "color", - "value": { - "mode": "fixed", - "fixedColor": "semi-dark-purple" - } - } - ] - } - ] - }, - "options": { - "reduceOptions": { - "values": false, - "calcs": [ - "lastNotNull" - ], - "fields": "" - }, - "pieType": "donut", - "displayLabels": [], - "tooltip": { - "mode": "single" - }, - "legend": { - "displayMode": "hidden", - "placement": "bottom" - } - }, - "targets": [ - { - "exemplar": true, - "expr": "sum(argocd_app_info{namespace=~\"$namespace\",dest_server=~\"$cluster\",health_status=~\"$health_status\",sync_status=~\"$sync_status\",health_status!=\"\",cluster=~\"$host\"}) by (health_status)", - "interval": "", - "legendFormat": "{{health_status}}", - "refId": "A" - } - ] - }, - { - "id": 23763571995, - "gridPos": { - "h": 4, - "w": 3, - "x": 11, - "y": 1 - }, - "type": "piechart", - "title": "Sync Status", - "datasource": "$datasource", - "description": "Application Sync Status", - "fieldConfig": { - "defaults": { - "custom": { - "hideFrom": { - "tooltip": false, - "viz": false, - "legend": false - } - }, - "color": { - "mode": "palette-classic" - }, - "mappings": [] - }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Unknown" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "rgb(255, 255, 255)", - "mode": "fixed" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Synced" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "green", - "mode": "fixed" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "OutOfSync" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "semi-dark-yellow", - "mode": "fixed" - } - } - ] - } - ] - }, - "options": { - "reduceOptions": { - "values": false, - "calcs": [ - "lastNotNull" - ], - "fields": "" - }, - "pieType": "donut", - "displayLabels": [], - "tooltip": { - "mode": "single" - }, - "legend": { - "displayMode": "hidden", - "placement": "bottom" - } - }, - "targets": [ - { - "exemplar": true, - "expr": "sum(argocd_app_info{namespace=~\"$namespace\",dest_server=~\"$cluster\",health_status=~\"$health_status\",sync_status=~\"$sync_status\",health_status!=\"\",cluster=~\"$host\"}) by (sync_status)", - "interval": "", - "legendFormat": "{{sync_status}}", - "refId": "A" - } - ] - }, - { - "cacheTimeout": null, - "datasource": "$datasource", - "gridPos": { - "h": 4, - "w": 3, - "x": 14, - "y": 1 - }, - "id": 100, - "links": [], - "options": { - "fieldOptions": { - "calcs": [ - "lastNotNull" - ], - "defaults": { - "mappings": [ - { - "id": 0, - "op": "=", - "text": "0", - "type": 1, - "value": "null" - } - ], - "max": 100, - "min": 0, - "nullValueMode": "connected", - "thresholds": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ], - "unit": "none" - }, - "override": {}, - "overrides": [], - "values": false - }, - "orientation": "horizontal", - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "6.5.2", - "repeatDirection": "h", - "targets": [ - { - "expr": "sum(argocd_app_info{namespace=~\"$namespace\",dest_server=~\"$cluster\",operation!=\"\",cluster=~\"$host\"})", - "format": "time_series", - "instant": true, - "intervalFactor": 1, - "legendFormat": "", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Operations", - "type": "gauge" - }, - { - "aliasColors": {}, - "bars": false, - "cacheTimeout": null, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "decimals": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 4, - "w": 7, - "x": 17, - "y": 1 - }, - "hiddenSeries": false, - "id": 28, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "connected", - "options": { - "dataLinks": [] - }, - "paceLength": 10, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(argocd_app_info{namespace=~\"$namespace\",dest_server=~\"$cluster\",health_status=~\"$health_status\",sync_status=~\"$sync_status\",cluster=~\"$host\"}) by (cluster)", - "format": "time_series", - "instant": false, - "intervalFactor": 1, - "legendFormat": "{{cluster}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Applications", - "description": "Applications by host", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "collapsed": true, - "datasource": "$datasource", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 5 - }, - "id": 77, - "panels": [ - { - "id": 23763571776, - "gridPos": { - "h": 6, - "w": 12, - "x": 0, - "y": 6 - }, - "type": "timeseries", - "title": "Health Status", - "datasource": "$datasource", - "pluginVersion": "8.5.20", - "links": [], - "cacheTimeout": null, - "interval": "", - "targets": [ - { - "expr": "sum(argocd_app_info{namespace=~\"$namespace\",dest_server=~\"$cluster\",health_status=~\"$health_status\",sync_status=~\"$sync_status\",health_status!=\"\",cluster=~\"$host\"}) by (cluster,namespace,health_status)", - "legendFormat": "{{health_status}} ({{cluster}}/{{namespace}})", - "interval": "", - "exemplar": true, - "format": "time_series", - "instant": false, - "intervalFactor": 1, - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "fieldConfig": { - "defaults": { - "custom": { - "drawStyle": "line", - "lineInterpolation": "linear", - "barAlignment": 0, - "lineWidth": 1, - "fillOpacity": 10, - "gradientMode": "none", - "spanNulls": false, - "showPoints": "never", - "pointSize": 5, - "stacking": { - "mode": "none", - "group": "A" - }, - "axisPlacement": "auto", - "axisLabel": "", - "scaleDistribution": { - "type": "linear" - }, - "hideFrom": { - "tooltip": false, - "viz": false, - "legend": false - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "color": { - "mode": "palette-classic" - }, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "mappings": [], - "links": [], - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byRegexp", - "options": "Healthy.*" - }, - "properties": [ - { - "id": "color", - "value": { - "mode": "fixed", - "fixedColor": "green" - } - } - ] - }, - { - "matcher": { - "id": "byRegexp", - "options": "Degraded.*" - }, - "properties": [ - { - "id": "color", - "value": { - "mode": "fixed", - "fixedColor": "semi-dark-red" - } - } - ] - }, - { - "matcher": { - "id": "byRegexp", - "options": "Missing.*" - }, - "properties": [ - { - "id": "color", - "value": { - "mode": "fixed", - "fixedColor": "semi-dark-orange" - } - } - ] - }, - { - "matcher": { - "id": "byRegexp", - "options": "Progressing.*" - }, - "properties": [ - { - "id": "color", - "value": { - "mode": "fixed", - "fixedColor": "semi-dark-blue" - } - } - ] - }, - { - "matcher": { - "id": "byRegexp", - "options": "Suspended.*" - }, - "properties": [ - { - "id": "color", - "value": { - "mode": "fixed", - "fixedColor": "semi-dark-purple" - } - } - ] - }, - { - "matcher": { - "id": "byRegexp", - "options": "Unknown.*" - }, - "properties": [ - { - "id": "color", - "value": { - "mode": "fixed", - "fixedColor": "rgb(255, 255, 255)" - } - } - ] - } - ] - }, - "options": { - "tooltip": { - "mode": "single" - }, - "legend": { - "displayMode": "table", - "placement": "right", - "calcs": [ - "lastNotNull" - ] - } - } - }, - { - "id": 23763571993, - "gridPos": { - "h": 6, - "w": 12, - "x": 12, - "y": 6 - }, - "type": "timeseries", - "title": "Sync Status", - "datasource": "$datasource", - "pluginVersion": "8.5.20", - "links": [], - "cacheTimeout": null, - "interval": "", - "targets": [ - { - "expr": "sum(argocd_app_info{namespace=~\"$namespace\",dest_server=~\"$cluster\",health_status=~\"$health_status\",sync_status=~\"$sync_status\",health_status!=\"\",cluster=~\"$host\"}) by (cluster,namespace,sync_status)", - "legendFormat": "{{sync_status}} ({{cluster}}/{{namespace}})", - "interval": "", - "exemplar": true, - "format": "time_series", - "instant": false, - "intervalFactor": 1, - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "fieldConfig": { - "defaults": { - "custom": { - "drawStyle": "line", - "lineInterpolation": "linear", - "barAlignment": 0, - "lineWidth": 1, - "fillOpacity": 10, - "gradientMode": "none", - "spanNulls": false, - "showPoints": "never", - "pointSize": 5, - "stacking": { - "mode": "none", - "group": "A" - }, - "axisPlacement": "auto", - "axisLabel": "", - "scaleDistribution": { - "type": "linear" - }, - "hideFrom": { - "tooltip": false, - "viz": false, - "legend": false - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "color": { - "mode": "palette-classic" - }, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "value": null, - "color": "green" - }, - { - "value": 80, - "color": "red" - } - ] - }, - "mappings": [], - "links": [], - "unit": "short" - }, - "overrides": [ - { - "matcher": { - "id": "byRegexp", - "options": "OutOfSync.*" - }, - "properties": [ - { - "id": "color", - "value": { - "mode": "fixed", - "fixedColor": "semi-dark-yellow" - } - } - ] - }, - { - "matcher": { - "id": "byRegexp", - "options": "Synced.*" - }, - "properties": [ - { - "id": "color", - "value": { - "mode": "fixed", - "fixedColor": "semi-dark-green" - } - } - ] - }, - { - "matcher": { - "id": "byRegexp", - "options": "Unknown.*" - }, - "properties": [ - { - "id": "color", - "value": { - "mode": "fixed", - "fixedColor": "rgb(255, 255, 255)" - } - } - ] - } - ] - }, - "options": { - "tooltip": { - "mode": "single" - }, - "legend": { - "displayMode": "table", - "placement": "right", - "calcs": [ - "lastNotNull" - ] - } - } - } - ], - "title": "Application Status", - "type": "row" - }, - { - "collapsed": true, - "datasource": "$datasource", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 6 - }, - "id": 104, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "decimals": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 6, - "w": 24, - "x": 0, - "y": 3 - }, - "hiddenSeries": false, - "id": 56, - "interval": "", - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sort": "total", - "sortDesc": true, - "total": true, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "paceLength": 10, - "percentage": false, - "pointradius": 1, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "exemplar": true, - "expr": "sum(round(increase(argocd_app_sync_total{namespace=~\"$namespace\",dest_server=~\"$cluster\",cluster=~\"$host\"}[$interval]))) by ($grouping)", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "{{$grouping}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Sync Activity", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "decimals": -12, - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "decimals": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 5, - "w": 24, - "x": 0, - "y": 9 - }, - "hiddenSeries": false, - "id": 73, - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "hideEmpty": true, - "hideZero": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sort": "total", - "sortDesc": true, - "total": true, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "paceLength": 10, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(round(increase(argocd_app_sync_total{namespace=~\"$namespace\",phase=~\"Error|Failed\",dest_server=~\"$cluster\",cluster=~\"$host\"}[$interval]))) by ($grouping, phase)", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "{{phase}}: {{$grouping}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Sync Failures", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "none", - "label": "", - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - } - ], - "title": "Sync Stats", - "type": "row" - }, - { - "collapsed": true, - "datasource": "$datasource", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 7 - }, - "id": 64, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 6, - "w": 24, - "x": 0, - "y": 12 - }, - "hiddenSeries": false, - "id": 58, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": true, - "min": false, - "rightSide": true, - "show": true, - "sort": "total", - "sortDesc": true, - "total": true, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "paceLength": 10, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(increase(argocd_app_reconcile_count{namespace=~\"$namespace\",dest_server=~\"$cluster\",cluster=~\"$host\"}[$interval])) by ($grouping)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{$grouping}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Reconciliation Activity", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "cards": { - "cardPadding": null, - "cardRound": null - }, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateSpectral", - "exponent": 0.5, - "min": null, - "mode": "spectrum" - }, - "dataFormat": "tsbuckets", - "datasource": "$datasource", - "gridPos": { - "h": 7, - "w": 24, - "x": 0, - "y": 18 - }, - "heatmap": {}, - "hideZeroBuckets": false, - "highlightCards": true, - "id": 60, - "legend": { - "show": true - }, - "links": [], - "options": {}, - "reverseYBuckets": false, - "targets": [ - { - "expr": "sum(increase(argocd_app_reconcile_bucket{namespace=~\"$namespace\",cluster=~\"$host\"}[$interval])) by (le)", - "format": "heatmap", - "instant": false, - "intervalFactor": 10, - "legendFormat": "{{le}}", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Reconciliation Performance", - "tooltip": { - "show": true, - "showHistogram": true - }, - "tooltipDecimals": 0, - "type": "heatmap", - "xAxis": { - "show": true - }, - "xBucketNumber": null, - "xBucketSize": null, - "yAxis": { - "decimals": null, - "format": "short", - "logBase": 1, - "max": null, - "min": null, - "show": true, - "splitFactor": null - }, - "yBucketBound": "auto", - "yBucketNumber": null, - "yBucketSize": null - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 6, - "w": 24, - "x": 0, - "y": 25 - }, - "hiddenSeries": false, - "id": 80, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "options": { - "dataLinks": [] - }, - "paceLength": 10, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(increase(argocd_app_k8s_request_total{namespace=~\"$namespace\",server=~\"$cluster\",cluster=~\"$host\"}[$interval])) by (verb, resource_kind)", - "format": "time_series", - "instant": false, - "intervalFactor": 1, - "legendFormat": "{{verb}} {{resource_kind}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "K8s API Activity", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 31 - }, - "hiddenSeries": false, - "id": 96, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideZero": true, - "max": true, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": null, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(workqueue_depth{namespace=~\"$namespace\",name=~\"app_.*\",cluster=~\"$host\"}) by (name)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{name}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Workqueue Depth", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "decimals": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 31 - }, - "hiddenSeries": false, - "id": 98, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideZero": false, - "max": true, - "min": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(argocd_kubectl_exec_pending{namespace=~\"$namespace\",cluster=~\"$host\"}) by (command)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{command}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Pending kubectl run", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "decimals": 0, - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": "0", - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - } - ], - "title": "Controller Stats", - "type": "row" - }, - { - "collapsed": true, - "datasource": "$datasource", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 8 - }, - "id": 102, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 24, - "x": 0, - "y": 26 - }, - "hiddenSeries": false, - "id": 34, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": true, - "min": false, - "rightSide": true, - "show": true, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "connected", - "options": { - "dataLinks": [] - }, - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "go_memstats_heap_alloc_bytes{container=\"argocd-application-controller\",namespace=~\"$namespace\",cluster=~\"$host\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{cluster}}/{{namespace}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Memory Usage", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 24, - "x": 0, - "y": 33 - }, - "hiddenSeries": false, - "id": 108, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": true, - "min": false, - "rightSide": true, - "show": true, - "sort": "avg", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "connected", - "options": { - "dataLinks": [] - }, - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "irate(process_cpu_seconds_total{container=\"argocd-application-controller\",namespace=~\"$namespace\"}[$__rate_interval])", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{cluster}}/{{namespace}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "CPU Usage", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 1, - "format": "none", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 24, - "x": 0, - "y": 40 - }, - "hiddenSeries": false, - "id": 62, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": false, - "hideZero": false, - "max": true, - "min": false, - "rightSide": true, - "show": true, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "go_goroutines{container=\"argocd-application-controller\",namespace=~\"$namespace\",cluster=~\"$host\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{cluster}}/{{namespace}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Goroutines", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - } - ], - "title": "Controller Telemetry", - "type": "row" - }, - { - "collapsed": true, - "datasource": "$datasource", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 9 - }, - "id": 88, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 24, - "x": 0, - "y": 27 - }, - "hiddenSeries": false, - "id": 90, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(argocd_cluster_api_resource_objects{namespace=~\"$namespace\",server=~\"$cluster\",cluster=~\"$host\"}) by (server)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{server}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Resource Objects Count", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 6, - "w": 24, - "x": 0, - "y": 34 - }, - "hiddenSeries": false, - "id": 92, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "hideEmpty": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": " sum(argocd_cluster_api_resources{namespace=~\"$namespace\",server=~\"$cluster\",cluster=~\"$host\"}) by (server)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{server}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "API Resources Count", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 24, - "x": 0, - "y": 40 - }, - "hiddenSeries": false, - "id": 86, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(increase(argocd_cluster_events_total{namespace=~\"$namespace\",server=~\"$cluster\",cluster=~\"$host\"}[$interval])) by (server)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{server}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Cluster Events Count", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - } - ], - "title": "Destination Stats", - "type": "row" - }, - { - "collapsed": true, - "datasource": "$datasource", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 10 - }, - "id": 70, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 7 - }, - "hiddenSeries": false, - "id": 82, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(increase(argocd_git_request_total{request_type=\"ls-remote\", namespace=~\"$namespace\",cluster=~\"$host\"}[10m])) by (namespace)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{namespace}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Git Requests (ls-remote)", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 7 - }, - "hiddenSeries": false, - "id": 84, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(increase(argocd_git_request_total{request_type=\"fetch\", namespace=~\"$namespace\",cluster=~\"$host\"}[$__rate_interval])) by (namespace)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{namespace}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Git Requests (checkout)", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "cards": { - "cardPadding": null, - "cardRound": null - }, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateSpectral", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "tsbuckets", - "datasource": "$datasource", - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 15 - }, - "heatmap": {}, - "hideZeroBuckets": false, - "highlightCards": true, - "id": 114, - "legend": { - "show": false - }, - "options": {}, - "reverseYBuckets": false, - "targets": [ - { - "expr": "sum(increase(argocd_git_request_duration_seconds_bucket{request_type=\"fetch\", namespace=~\"$namespace\",cluster=~\"$host\"}[$__rate_interval])) by (le)", - "format": "heatmap", - "intervalFactor": 10, - "legendFormat": "{{le}}", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Git Fetch Performance", - "tooltip": { - "show": true, - "showHistogram": false - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "xBucketNumber": null, - "xBucketSize": null, - "yAxis": { - "decimals": null, - "format": "short", - "logBase": 1, - "max": null, - "min": null, - "show": true, - "splitFactor": null - }, - "yBucketBound": "auto", - "yBucketNumber": null, - "yBucketSize": null - }, - { - "cards": { - "cardPadding": null, - "cardRound": null - }, - "color": { - "cardColor": "#b4ff00", - "colorScale": "sqrt", - "colorScheme": "interpolateSpectral", - "exponent": 0.5, - "mode": "spectrum" - }, - "dataFormat": "tsbuckets", - "datasource": "$datasource", - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 15 - }, - "heatmap": {}, - "hideZeroBuckets": false, - "highlightCards": true, - "id": 116, - "legend": { - "show": false - }, - "options": {}, - "reverseYBuckets": false, - "targets": [ - { - "expr": "sum(increase(argocd_git_request_duration_seconds_bucket{request_type=\"ls-remote\", namespace=~\"$namespace\",cluster=~\"$host\"}[$__rate_interval])) by (le)", - "format": "heatmap", - "intervalFactor": 10, - "legendFormat": "{{le}}", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Git Ls-Remote Performance", - "tooltip": { - "show": true, - "showHistogram": false - }, - "type": "heatmap", - "xAxis": { - "show": true - }, - "xBucketNumber": null, - "xBucketSize": null, - "yAxis": { - "decimals": null, - "format": "short", - "logBase": 1, - "max": null, - "min": null, - "show": true, - "splitFactor": null - }, - "yBucketBound": "auto", - "yBucketNumber": null, - "yBucketSize": null - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 24, - "x": 0, - "y": 23 - }, - "hiddenSeries": false, - "id": 71, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "connected", - "options": { - "dataLinks": [] - }, - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "go_memstats_heap_alloc_bytes{container=\"argocd-repo-server\",namespace=~\"$namespace\",cluster=~\"$host\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{pod}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Memory Used", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 24, - "x": 0, - "y": 31 - }, - "hiddenSeries": false, - "id": 72, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "go_goroutines{container=\"argocd-repo-server\",namespace=~\"$namespace\",cluster=~\"$host\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{pod}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Goroutines", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - } - ], - "title": "Repo Server Stats", - "type": "row" - }, - { - "collapsed": true, - "datasource": "$datasource", - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 11 - }, - "id": 66, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "gridPos": { - "h": 8, - "w": 24, - "x": 0, - "y": 89 - }, - "id": 61, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "go_memstats_heap_alloc_bytes{container=\"argocd-server\",namespace=~\"$namespace\",cluster=~\"$host\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{pod}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Memory Used", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 97 - }, - "id": 36, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "go_goroutines{container=\"argocd-server\",namespace=~\"$namespace\",cluster=~\"$host\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{pod}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Goroutines", - "tooltip": { - "shared": true, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 106 - }, - "id": 38, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "connected", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "go_gc_duration_seconds{container=\"argocd-server\", quantile=\"1\", namespace=~\"$namespace\",cluster=~\"$host\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{pod}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "GC Time Quantiles", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "content": "#### gRPC Services:", - "gridPos": { - "h": 2, - "w": 24, - "x": 0, - "y": 115 - }, - "id": 54, - "links": [], - "mode": "markdown", - "title": "", - "transparent": true, - "type": "text" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "decimals": null, - "fill": 1, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 117 - }, - "id": 40, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sort": "total", - "sortDesc": true, - "total": true, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(increase(grpc_server_handled_total{container=\"argocd-server\",grpc_service=\"application.ApplicationService\",namespace=~\"$namespace\",cluster=~\"$host\"}[$__rate_interval])) by (grpc_code, grpc_method)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{grpc_code}},{{grpc_method}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "ApplicationService Requests", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 117 - }, - "id": 42, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": true, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(increase(grpc_server_handled_total{container=\"argocd-server\",grpc_service=\"cluster.ClusterService\",namespace=~\"$namespace\",cluster=~\"$host\"}[$__rate_interval])) by (grpc_code, grpc_method)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{grpc_code}},{{grpc_method}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "ClusterService Requests", - "tooltip": { - "shared": false, - "sort": 2, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 126 - }, - "id": 44, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": true, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(increase(grpc_server_handled_total{container=\"argocd-server\",grpc_service=\"project.ProjectService\",namespace=~\"$namespace\",cluster=~\"$host\"}[$__rate_interval])) by (grpc_code, grpc_method)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{grpc_code}},{{grpc_method}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "ProjectService Requests", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 126 - }, - "id": 46, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "show": true, - "total": true, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(increase(grpc_server_handled_total{container=\"argocd-server\",grpc_service=\"repository.RepositoryService\",namespace=~\"$namespace\",cluster=~\"$host\"}[$__rate_interval])) by (grpc_code, grpc_method)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{grpc_code}},{{grpc_method}}", - "refId": "A" - } - ], - "thresholds": [ - { - "colorMode": "critical", - "fill": true, - "line": true, - "op": "gt", - "yaxis": "left" - } - ], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "RepositoryService Requests", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 135 - }, - "id": 48, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "show": true, - "total": true, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(increase(grpc_server_handled_total{container=\"argocd-server\",grpc_service=\"session.SessionService\",namespace=~\"$namespace\",cluster=~\"$host\"}[$__rate_interval])) by (grpc_code, grpc_method)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{grpc_code}},{{grpc_method}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "SessionService Requests", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 135 - }, - "id": 49, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "show": true, - "total": true, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(increase(grpc_server_handled_total{container=\"argocd-server\",grpc_service=\"version.VersionService\",namespace=~\"$namespace\",cluster=~\"$host\"}[$__rate_interval])) by (grpc_code, grpc_method)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{grpc_code}},{{grpc_method}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "VersionService Requests", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 144 - }, - "id": 50, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "show": true, - "total": true, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(increase(grpc_server_handled_total{container=\"argocd-server\",grpc_service=\"account.AccountService\",namespace=~\"$namespace\",cluster=~\"$host\"}[$__rate_interval])) by (grpc_code, grpc_method)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{grpc_code}},{{grpc_method}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "AccountService Requests", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$datasource", - "fill": 1, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 144 - }, - "id": 99, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": true, - "hideZero": true, - "max": false, - "min": false, - "show": true, - "total": true, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null as zero", - "paceLength": 10, - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(increase(grpc_server_handled_total{container=\"argocd-server\",grpc_service=\"settings.SettingsService\",namespace=~\"$namespace\",cluster=~\"$host\"}[$__rate_interval])) by (grpc_code, grpc_method)", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{grpc_code}},{{grpc_method}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "SettingsService Requests", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - } - ], - "title": "Server Stats", - "type": "row" - }, - { - "collapsed": true, - "datasource": null, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 12 - }, - "id": 110, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 7, - "w": 24, - "x": 0, - "y": 9 - }, - "hiddenSeries": false, - "id": 112, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(increase(argocd_redis_request_total{namespace=~\"$namespace\",cluster=~\"$host\"}[$__rate_interval])) by (failed)", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Requests by result", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - } - ], - "title": "Redis Stats", - "type": "row" - } - ], - "refresh": false, - "schemaVersion": 21, - "style": "dark", - "tags": [], - "templating": { - "list": [ - { - "current": { - "text": "Prometheus", - "value": "Prometheus" - }, - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "datasource", - "options": [], - "query": "prometheus", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "type": "datasource" - }, - { - "allValue": ".*", - "current": { - "selected": false, - "text": "All", - "value": "$__all" - }, - "datasource": "$datasource", - "definition": "label_values(argocd_cluster_info, cluster)", - "hide": 0, - "includeAll": true, - "label": "cluster", - "multi": false, - "name": "host", - "options": [], - "query": "label_values(argocd_cluster_info, cluster)", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": ".*", - "current": { - "selected": false, - "text": "All", - "value": "$__all" - }, - "datasource": "$datasource", - "definition": "label_values(kube_pod_info, namespace)", - "hide": 0, - "includeAll": true, - "label": null, - "multi": false, - "name": "namespace", - "options": [], - "query": "label_values(kube_pod_info, namespace)", - "refresh": 1, - "regex": ".*argocd.*", - "skipUrlSync": false, - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "auto": true, - "auto_count": 30, - "auto_min": "1m", - "current": { - "selected": false, - "text": "auto", - "value": "$__auto_interval_interval" - }, - "hide": 0, - "label": null, - "name": "interval", - "options": [ - { - "selected": true, - "text": "auto", - "value": "$__auto_interval_interval" - }, - { - "selected": false, - "text": "1m", - "value": "1m" - }, - { - "selected": false, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "10m", - "value": "10m" - }, - { - "selected": false, - "text": "30m", - "value": "30m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - }, - { - "selected": false, - "text": "2h", - "value": "2h" - }, - { - "selected": false, - "text": "4h", - "value": "4h" - }, - { - "selected": false, - "text": "8h", - "value": "8h" - } - ], - "query": "1m,5m,10m,30m,1h,2h,4h,8h", - "refresh": 2, - "skipUrlSync": false, - "type": "interval" - }, - { - "allValue": "", - "current": { - "selected": true, - "text": "namespace", - "value": "namespace" - }, - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "grouping", - "options": [ - { - "selected": true, - "text": "namespace", - "value": "namespace" - }, - { - "selected": false, - "text": "name", - "value": "name" - }, - { - "selected": false, - "text": "project", - "value": "project" - } - ], - "query": "namespace,name,project", - "skipUrlSync": false, - "type": "custom" - }, - { - "allValue": ".*", - "current": { - "selected": false, - "text": "All", - "value": "$__all" - }, - "datasource": "$datasource", - "definition": "label_values(argocd_cluster_info, server)", - "hide": 0, - "includeAll": true, - "label": "destination", - "multi": false, - "name": "cluster", - "options": [], - "query": "label_values(argocd_cluster_info, server)", - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 1, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": ".*", - "current": { - "selected": true, - "text": "All", - "value": "$__all" - }, - "hide": 0, - "includeAll": true, - "label": null, - "multi": false, - "name": "health_status", - "options": [ - { - "selected": true, - "text": "All", - "value": "$__all" - }, - { - "selected": false, - "text": "Healthy", - "value": "Healthy" - }, - { - "selected": false, - "text": "Progressing", - "value": "Progressing" - }, - { - "selected": false, - "text": "Suspended", - "value": "Suspended" - }, - { - "selected": false, - "text": "Missing", - "value": "Missing" - }, - { - "selected": false, - "text": "Degraded", - "value": "Degraded" - }, - { - "selected": false, - "text": "Unknown", - "value": "Unknown" - } - ], - "query": "Healthy,Progressing,Suspended,Missing,Degraded,Unknown", - "skipUrlSync": false, - "type": "custom" - }, - { - "allValue": ".*", - "current": { - "selected": true, - "text": "All", - "value": "$__all" - }, - "hide": 0, - "includeAll": true, - "label": null, - "multi": false, - "name": "sync_status", - "options": [ - { - "selected": true, - "text": "All", - "value": "$__all" - }, - { - "selected": false, - "text": "Synced", - "value": "Synced" - }, - { - "selected": false, - "text": "OutOfSync", - "value": "OutOfSync" - }, - { - "selected": false, - "text": "Unknown", - "value": "Unknown" - } - ], - "query": "Synced,OutOfSync,Unknown", - "skipUrlSync": false, - "type": "custom" - } - ] - }, - "time": { - "from": "now-30m", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "", - "title": "GitOps", - "uid": "LCAgc9rWz", - "version": 1 -} diff --git a/tmp/acm-hub-bootstrap-old/components/apps/acm/overlays/observability/kustomization.yaml b/tmp/acm-hub-bootstrap-old/components/apps/acm/overlays/observability/kustomization.yaml deleted file mode 100644 index b7aaf10..0000000 --- a/tmp/acm-hub-bootstrap-old/components/apps/acm/overlays/observability/kustomization.yaml +++ /dev/null @@ -1,46 +0,0 @@ -namespace: open-cluster-management-observability - -generatorOptions: - disableNameSuffixHash: true - labels: - grafana-custom-dashboard: "true" - -resources: -- github.com/redhat-cop/gitops-catalog/advanced-cluster-management/instance/observability -- custom-metrics-allowlist.yaml - -configMapGenerator: -- name: gitops-dashboard - files: - - gitops.json=gitops-dashboard.json - -patches: - - patch: |- - - op: replace - path: /spec/storageConfig/storageClass - value: lvms-vg1 - - op: replace - path: /spec/observabilityAddonSpec/interval - value: 60 - - op: add - path: /spec/advanced - value: - alertmanager: - replicas: 1 - grafana: - replicas: 1 - observatoriumAPI: - replicas: 1 - query: - replicas: 1 - queryFrontend: - replicas: 1 - queryFrontendMemcached: - replicas: 1 - rbacQueryProxy: - replicas: 1 - receive: - replicas: 1 - target: - kind: MultiClusterObservability - name: observability diff --git a/tmp/acm-hub-bootstrap-old/components/clusters/base/kustomization.yaml b/tmp/acm-hub-bootstrap-old/components/clusters/base/kustomization.yaml deleted file mode 100644 index e6961ed..0000000 --- a/tmp/acm-hub-bootstrap-old/components/clusters/base/kustomization.yaml +++ /dev/null @@ -1,3 +0,0 @@ -resources: -- local-home.yaml -- local-hub.yaml diff --git a/tmp/acm-hub-bootstrap-old/components/clusters/base/local-home.yaml b/tmp/acm-hub-bootstrap-old/components/clusters/base/local-home.yaml deleted file mode 100644 index 7df0334..0000000 --- a/tmp/acm-hub-bootstrap-old/components/clusters/base/local-home.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: cluster.open-cluster-management.io/v1 -kind: ManagedCluster -metadata: - annotations: - open-cluster-management/created-via: other - labels: - cloud: Other - cluster.open-cluster-management.io/clusterset: dev - gitops: local.home - color: "0066CC" - name: home - vendor: OpenShift - name: home -spec: - hubAcceptsClient: true - leaseDurationSeconds: 60 - managedClusterClientConfigs: - - url: https://api.home.ocplab.com:6443 diff --git a/tmp/acm-hub-bootstrap-old/components/clusters/base/local-hub.yaml b/tmp/acm-hub-bootstrap-old/components/clusters/base/local-hub.yaml deleted file mode 100644 index fd66fb7..0000000 --- a/tmp/acm-hub-bootstrap-old/components/clusters/base/local-hub.yaml +++ /dev/null @@ -1,20 +0,0 @@ -apiVersion: cluster.open-cluster-management.io/v1 -kind: ManagedCluster -metadata: - annotations: - open-cluster-management/created-via: other - labels: - cloud: Other - cluster.open-cluster-management.io/clusterset: default - gitops: local.hub - color: "3E8635" - local-cluster: "true" - name: local-cluster - velero.io/exclude-from-backup: "true" - vendor: OpenShift - name: local-cluster -spec: - hubAcceptsClient: true - leaseDurationSeconds: 60 - managedClusterClientConfigs: - - url: https://api.hub.ocplab.com:6443 diff --git a/tmp/acm-hub-bootstrap-old/components/policies/cert-expiration/base/kustomization.yaml b/tmp/acm-hub-bootstrap-old/components/policies/cert-expiration/base/kustomization.yaml deleted file mode 100644 index 467f048..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/cert-expiration/base/kustomization.yaml +++ /dev/null @@ -1,2 +0,0 @@ -resources: -- policy-cert-expiration.yaml \ No newline at end of file diff --git a/tmp/acm-hub-bootstrap-old/components/policies/cert-expiration/base/policy-cert-expiration.yaml b/tmp/acm-hub-bootstrap-old/components/policies/cert-expiration/base/policy-cert-expiration.yaml deleted file mode 100644 index 153a2e4..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/cert-expiration/base/policy-cert-expiration.yaml +++ /dev/null @@ -1,50 +0,0 @@ -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: certificate-expiration - annotations: - policy.open-cluster-management.io/categories: SC System and Communications Protection - policy.open-cluster-management.io/standards: NIST SP 800-53 - policy.open-cluster-management.io/controls: SC-8 Transmission Confidentiality and Integrity -spec: - disabled: false - remediationAction: inform - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: CertificatePolicy - metadata: - name: policy-certificate - spec: - namespaceSelector: - include: - - default - exclude: - - kube-* - remediationAction: inform - severity: low - minimumDuration: 300h ---- -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: certificate-expiration-placement -spec: - clusterSelector: - matchExpressions: [] - clusterConditions: - - status: "True" - type: ManagedClusterConditionAvailable ---- -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: certificate-expiration-placement -placementRef: - name: certificate-expiration-placement - apiGroup: apps.open-cluster-management.io - kind: PlacementRule -subjects: - - name: certificate-expiration - apiGroup: policy.open-cluster-management.io - kind: Policy \ No newline at end of file diff --git a/tmp/acm-hub-bootstrap-old/components/policies/compliance/base/kustomization.yaml b/tmp/acm-hub-bootstrap-old/components/policies/compliance/base/kustomization.yaml deleted file mode 100644 index 08ecde2..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/compliance/base/kustomization.yaml +++ /dev/null @@ -1,2 +0,0 @@ -resources: -- scan-nist-800-53-policy.yaml \ No newline at end of file diff --git a/tmp/acm-hub-bootstrap-old/components/policies/compliance/base/scan-nist-800-53-policy.yaml b/tmp/acm-hub-bootstrap-old/components/policies/compliance/base/scan-nist-800-53-policy.yaml deleted file mode 100644 index 5b1efd2..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/compliance/base/scan-nist-800-53-policy.yaml +++ /dev/null @@ -1,55 +0,0 @@ -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: scan-nist-800-53 - annotations: - policy.open-cluster-management.io/standards: NIST-CSF - policy.open-cluster-management.io/categories: PR.IP Information Protection Processes and Procedures - policy.open-cluster-management.io/controls: PR.IP-1 Baseline Configuration -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: scan-nist-800-53 - spec: - remediationAction: inform - severity: high - object-templates: - - complianceType: mustnothave - objectDefinition: - apiVersion: compliance.openshift.io/v1alpha1 - kind: ComplianceCheckResult - metadata: - namespace: openshift-compliance - labels: - compliance.openshift.io/check-status: FAIL - compliance.openshift.io/suite: cis-compliance ---- -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: binding-scan-nist-800-53 -placementRef: - name: placement-scan-nist-800-53 - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: scan-nist-800-53 - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: placement-scan-nist-800-53 -spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - {key: vendor, operator: In, values: ["OpenShift"]} \ No newline at end of file diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gatekeeper/config-policy-namespace.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gatekeeper/config-policy-namespace.yaml deleted file mode 100644 index 48aeeff..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gatekeeper/config-policy-namespace.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - annotations: - openshift.io/description: ACM Configuration Policies - openshift.io/display-name: ACM Configuration Policies - name: acm-config-policies \ No newline at end of file diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gatekeeper/gatekeeper-exclude-namespaces.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gatekeeper/gatekeeper-exclude-namespaces.yaml deleted file mode 100644 index 61125fc..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gatekeeper/gatekeeper-exclude-namespaces.yaml +++ /dev/null @@ -1,131 +0,0 @@ -# Sample policy to configure gatekeeper to exclude namespaces from certain processes for all constraints in the cluster -# See: https://github.com/open-policy-agent/gatekeeper/tree/release-3.3#exempting-namespaces-from-gatekeeper -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: policy-gatekeeper-config-exclude-namespaces - annotations: - policy.open-cluster-management.io/standards: NIST SP 800-53 - policy.open-cluster-management.io/categories: CM Configuration Management - policy.open-cluster-management.io/controls: CM-2 Baseline Configuration -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: policy-gatekeeper-config-exclude-namespaces - spec: - remediationAction: enforce # will be overridden by remediationAction in parent policy - severity: low - object-templates: - - complianceType: mustonlyhave - objectDefinition: - apiVersion: config.gatekeeper.sh/v1alpha1 - kind: Config - metadata: - name: config - namespace: openshift-gatekeeper-system - spec: - match: - - excludedNamespaces: - - hive - - kube-node-lease - - kube-public - - kube-storage-version-migrator-operator - - kube-system - - open-cluster-management - - open-cluster-management-hub - - open-cluster-management-agent - - open-cluster-management-agent-addon - - openshift - - openshift-apiserver - - openshift-apiserver-operator - - openshift-authentication - - openshift-authentication-operator - - openshift-cloud-credential-operator - - openshift-cluster-csi-drivers - - openshift-cluster-machine-approver - - openshift-cluster-node-tuning-operator - - openshift-cluster-samples-operator - - openshift-cluster-storage-operator - - openshift-cluster-version - - openshift-compliance - - openshift-config - - openshift-config-managed - - openshift-config-operator - - openshift-console - - openshift-console-operator - - openshift-console-user-settings - - openshift-controller-manager - - openshift-controller-manager-operator - - openshift-dns - - openshift-dns-operator - - openshift-etcd - - openshift-etcd-operator - - openshift-gatekeeper-operator - - openshift-gatekeeper-system - - openshift-image-registry - - openshift-infra - - openshift-ingress - - openshift-ingress-canary - - openshift-ingress-operator - - openshift-insights - - openshift-kni-infra - - openshift-kube-apiserver - - openshift-kube-apiserver-operator - - openshift-kube-controller-manager - - openshift-kube-controller-manager-operator - - openshift-kube-scheduler - - openshift-kube-scheduler-operator - - openshift-kube-storage-version-migrator - - openshift-kube-storage-version-migrator-operator - - openshift-kubevirt-infra - - openshift-machine-api - - openshift-machine-config-operator - - openshift-marketplace - - openshift-monitoring - - openshift-multus - - openshift-network-diagnostics - - openshift-network-operator - - openshift-node - - openshift-oauth-apiserver - - openshift-openstack-infra - - openshift-operators - - openshift-operator-lifecycle-manager - - openshift-ovirt-infra - - openshift-ovn-kubernetes - - openshift-sdn - - openshift-service-ca - - openshift-service-ca-operator - - openshift-user-workload-monitoring - - openshift-vsphere-infra - processes: - - '*' ---- -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: binding-policy-gatekeeper-config-exclude-namespaces -placementRef: - name: placement-policy-gatekeeper-config-exclude-namespaces - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: -- name: policy-gatekeeper-config-exclude-namespaces - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: placement-policy-gatekeeper-config-exclude-namespaces -spec: - clusterConditions: - - status: "True" - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - {key: policy, operator: In, values: ["opa"]} \ No newline at end of file diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gatekeeper/gatekeeper-install-policy.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gatekeeper/gatekeeper-install-policy.yaml deleted file mode 100644 index 8f36d2d..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gatekeeper/gatekeeper-install-policy.yaml +++ /dev/null @@ -1,139 +0,0 @@ -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: policy-gatekeeper-operator - annotations: - policy.open-cluster-management.io/standards: NIST SP 800-53 - policy.open-cluster-management.io/categories: CM Configuration Management - policy.open-cluster-management.io/controls: CM-2 Baseline Configuration -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: gatekeeper-operator-ns - spec: - remediationAction: enforce - severity: high - object-templates: - - complianceType: musthave - objectDefinition: - apiVersion: v1 - kind: Namespace - metadata: - name: openshift-gatekeeper-operator - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: gatekeeper-operator-catalog-source - spec: - remediationAction: enforce - severity: high - object-templates: - - complianceType: musthave - objectDefinition: - apiVersion: operators.coreos.com/v1alpha1 - kind: CatalogSource - metadata: - name: gatekeeper-operator - namespace: openshift-gatekeeper-operator - spec: - displayName: Gatekeeper Operator Upstream - publisher: github.com/font/gatekeeper-operator - sourceType: grpc - image: 'quay.io/gatekeeper/gatekeeper-operator-bundle-index:v0.2.1' - updateStrategy: - registryPoll: - interval: 45m - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: gatekeeper-operator-group - spec: - remediationAction: enforce - severity: high - object-templates: - - complianceType: musthave - objectDefinition: - apiVersion: operators.coreos.com/v1 - kind: OperatorGroup - metadata: - name: gatekeeper-operator - namespace: openshift-gatekeeper-operator - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: gatekeeper-operator-subscription - spec: - remediationAction: enforce - severity: high - object-templates: - - complianceType: musthave - objectDefinition: - apiVersion: operators.coreos.com/v1alpha1 - kind: Subscription - metadata: - name: gatekeeper-operator-sub - namespace: openshift-gatekeeper-operator - spec: - channel: stable - name: gatekeeper-operator - source: gatekeeper-operator - sourceNamespace: openshift-gatekeeper-operator - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: gatekeeper - spec: - remediationAction: enforce - severity: high - object-templates: - - complianceType: musthave - objectDefinition: - apiVersion: operator.gatekeeper.sh/v1alpha1 - kind: Gatekeeper - metadata: - name: gatekeeper - spec: - audit: - auditChunkSize: 500 - logLevel: INFO - replicas: 1 - validatingWebhook: Enabled - mutatingWebhook: Disabled - webhook: - emitAdmissionEvents: Enabled - logLevel: INFO - replicas: 2 ---- -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: binding-policy-gatekeeper-operator -placementRef: - name: placement-policy-gatekeeper-operator - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: -- name: policy-gatekeeper-operator - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: placement-policy-gatekeeper-operator -spec: - clusterConditions: - - status: "True" - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - {key: policy, operator: In, values: ["opa"]} \ No newline at end of file diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/kustomization.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/kustomization.yaml deleted file mode 100644 index 4041c39..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/kustomization.yaml +++ /dev/null @@ -1,8 +0,0 @@ -namespace: acm-policies - -resources: -- placement.yaml -- managedclustersetbinding.yaml - -generators: -- policy-generator-config.yaml \ No newline at end of file diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/managedclustersetbinding.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/managedclustersetbinding.yaml deleted file mode 100644 index 7d389dc..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/managedclustersetbinding.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: cluster.open-cluster-management.io/v1beta2 -kind: ManagedClusterSetBinding -metadata: - name: global - namespace: acm-policies -spec: - clusterSet: global \ No newline at end of file diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/eso/base/secret-store.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/eso/base/secret-store.yaml deleted file mode 100644 index 3388a7c..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/eso/base/secret-store.yaml +++ /dev/null @@ -1,39 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: eso-token-cluster - namespace: external-secrets -data: - dopplerToken: '{{hub (fromSecret "acm-policies" (printf "eso-token-cluster-%s" .ManagedClusterName) "dopplerToken") hub}}' ---- -apiVersion: external-secrets.io/v1beta1 -kind: ClusterSecretStore -metadata: - name: doppler-cluster -spec: - provider: - doppler: - auth: - secretRef: - dopplerToken: - name: eso-token-cluster - key: dopplerToken - namespace: external-secrets - - conditions: - - namespaceSelector: - matchLabels: - openshift.io/cluster-monitoring: "true" - - - namespaces: - - "cert-manager" - - "dev-tools" - - "gitops" - - "openshift-config" - - "openshift-gitops" - - "openshift-monitoring" - - "openshift-pipelines" - - "stackrox" - - "stackrox-secured-cluster-service" - - "tenant-secrets" - - "trusted-profile-analyzer" diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-alerting/base/kustomization.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-alerting/base/kustomization.yaml deleted file mode 100644 index b3323f2..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-alerting/base/kustomization.yaml +++ /dev/null @@ -1,4 +0,0 @@ -namespace: openshift-gitops - -resources: -- prometheus-rules.yaml diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-alerting/base/prometheus-rules.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-alerting/base/prometheus-rules.yaml deleted file mode 100644 index 6c7ab28..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-alerting/base/prometheus-rules.yaml +++ /dev/null @@ -1,31 +0,0 @@ -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: argocd-health-alerts - annotations: - policy.open-cluster-management.io/disable-templates: "true" -spec: - groups: - - name: ArgoCD - rules: - - alert: ArgoCDHealthAlert - annotations: - message: ArgoCD application {{ $labels.name }} is not healthy - expr: argocd_app_info{namespace="openshift-gitops", health_status!~"Healthy|Suspended|Progressing|Degraded"} > 0 - for: 5m - labels: - severity: warning - - alert: ArgoCDDegradedAlert - annotations: - message: ArgoCD application {{ $labels.name }} is degraded - expr: argocd_app_info{namespace="openshift-gitops", health_status="Degraded"} > 0 - for: 5m - labels: - severity: critical - - alert: ArgoCDStuckAlert - annotations: - message: ArgoCD application {{ $labels.name }} is stuck in progressing for more than 10m - expr: argocd_app_info{namespace="openshift-gitops", health_status="Progressing"} > 0 - for: 10m - labels: - severity: warning diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-bootstrap/base/bootstrap-app.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-bootstrap/base/bootstrap-app.yaml deleted file mode 100644 index a98cbec..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-bootstrap/base/bootstrap-app.yaml +++ /dev/null @@ -1,27 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: cluster-config-bootstrap - namespace: openshift-gitops - labels: - gitops.ownedBy: cluster-config -spec: - destination: - namespace: openshift-gitops - server: https://kubernetes.default.svc - project: bootstrap - source: - path: bootstrap/overlays/{{ fromClusterClaim "gitops" }} - repoURL: https://github.com/gnunn-gitops/cluster-config-pins.git - targetRevision: 'HEAD' - syncPolicy: - automated: - prune: false - selfHeal: false - ignoreDifferences: - - group: argoproj.io - kind: Application - managedFieldsManagers: - - argocd-server - jsonPointers: - - /spec/syncPolicy/automated diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-bootstrap/base/bootstrap-appproject.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-bootstrap/base/bootstrap-appproject.yaml deleted file mode 100644 index bce3e9f..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-bootstrap/base/bootstrap-appproject.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: AppProject -metadata: - name: bootstrap - namespace: openshift-gitops -spec: - clusterResourceWhitelist: - - group: '*' - kind: '*' - description: Project for bootstrap cluster app - destinations: - - namespace: '*' - server: https://kubernetes.default.svc - sourceRepos: - - https://github.com/gnunn-gitops/cluster-config - - https://github.com/gnunn-gitops/cluster-config-pins diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-bootstrap/base/kustomization.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-bootstrap/base/kustomization.yaml deleted file mode 100644 index ca4eb20..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-bootstrap/base/kustomization.yaml +++ /dev/null @@ -1,3 +0,0 @@ -resources: -- bootstrap-appproject.yaml -- bootstrap-app.yaml \ No newline at end of file diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-instance/base/argocd.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-instance/base/argocd.yaml deleted file mode 100644 index 556fa4e..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-instance/base/argocd.yaml +++ /dev/null @@ -1,389 +0,0 @@ -apiVersion: argoproj.io/v1beta1 -kind: ArgoCD -metadata: - name: openshift-gitops - namespace: openshift-gitops -spec: - resourceTrackingMethod: annotation - applicationSet: {} - extraConfig: - exec.enabled: "true" - resource.respectRBAC: "normal" - resource.ignoreResourceUpdatesEnabled: 'true' - resource.compareoptions: | - ignoreAggregatedRoles: true - resource.customizations.ignoreResourceUpdates.external-secrets.io_ExternalSecret: | - jsonPointers: - - /status/refreshTime - resource.customizations.ignoreResourceUpdates.ocs.openshift.io_StorageCluster: | - jsonPointers: - - /status - - /metadata/resourceVersion - resource.customizations.ignoreResourceUpdates.ocs.openshift.io_StorageSystem: | - jsonPointers: - - /status - - /metadata/resourceVersion - resource.customizations.ignoreResourceUpdates.noobaa.io_Noobaa: | - jsonPointers: - - /status - - /metadata/resourceVersion - resource.customizations.ignoreResourceUpdates.noobaa.io_BackingStore: | - jsonPointers: - - /status - - /metadata/resourceVersion - accounts.admin: apiKey, login - ui.cssurl: 'https://gnunn-gitops.github.io/cluster-config/themes/{{ fromClusterClaim "gitops" }}/custom-cluster.css' - kustomizeBuildOptions: "--enable-helm --enable-alpha-plugins" - oidcConfig: | - name: Keycloak - issuer: https://sso.ocplab.com/realms/ocplab - clientID: argocd - clientSecret: $oidc.keycloak.clientSecret - requestedScopes: ["openid", "profile", "email", "groups"] - controller: - extraCommandArgs: - - '--persist-resource-health=false' - resources: - limits: - memory: 4Gi - requests: - cpu: 1000m - memory: 3Gi - monitoring: - enabled: true - repo: - sidecarContainers: - - name: setenv-cmp-plugin - command: [/var/run/argocd/argocd-cmp-server] - env: - - name: KUSTOMIZE_PLUGIN_HOME - value: /etc/kustomize/plugin - - name: INFRASTRUCTURE_ID - value: '{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").status.infrastructureName }}' - - name: CLUSTER_ID - value: '{{ (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").spec.clusterID }}' - - name: CLUSTER_GITOPS_NAME - value: '{{ fromClusterClaim "gitops" }}' - - name: CLUSTER_NAME - value: '{{ fromClusterClaim "name" }}' - - name: SUB_DOMAIN - value: '{{ (lookup "config.openshift.io/v1" "Ingress" "openshift-ingress" "cluster").spec.domain }}' - - name: BASE_DOMAIN - value: '{{ (lookup "config.openshift.io/v1" "DNS" "" "cluster").spec.baseDomain }}' - - name: COLOR - value: '{{ default "0066CC" (fromClusterClaim "color") }}' - image: quay.io/gnunn/tools:latest - imagePullPolicy: Always - securityContext: - runAsNonRoot: true - volumeMounts: - - mountPath: /var/run/argocd - name: var-files - - mountPath: /home/argocd/cmp-server/plugins - name: plugins - - mountPath: /tmp - name: tmp - - mountPath: /home/argocd/cmp-server/config/plugin.yaml - subPath: plugin.yaml - name: setenv-cmp-plugin - volumes: - - configMap: - name: setenv-cmp-plugin - name: setenv-cmp-plugin - resources: - limits: - cpu: '1' - memory: 1.5Gi - requests: - cpu: 250m - memory: 768Mi - redis: - resources: - limits: - cpu: 500m - memory: 512Mi - requests: - cpu: 250m - memory: 256Mi - server: - insecure: true - # host: 'openshift-gitops-server-openshift-gitops.{{ (lookup "config.openshift.io/v1" "Ingress" "openshift-ingress" "cluster").spec.domain }}' - route: - enabled: true - tls: - termination: edge - insecureEdgeTerminationPolicy: Redirect - notifications: - enabled: true - resourceActions: - - group: compliance.openshift.io - kind: ComplianceScan - action: | - discovery.lua: | - local actions = {} - local enabled = false - if obj.status ~= nil and obj.status.phase == "DONE" then - enabled = true - end - actions["rescan"] = {["disabled"] = not(enabled)} - return actions - definitions: - - name: rescan - action.lua: | - if obj.metadata.annotations == nil then - obj.metadata.annotations = {} - end - obj.metadata.annotations["compliance.openshift.io/rescan"] = "" - return obj - resourceHealthChecks: - - group: argoproj.io - kind: Application - check: | - hs = {} - hs.status = "Progressing" - hs.message = "" - if obj.status ~= nil then - if obj.status.health ~= nil then - hs.status = obj.status.health.status - hs.message = obj.status.health.message - end - end - return hs - - group: argoproj.io - kind: RolloutManager - check: | - hs = {} - if obj.status ~= nil then - if obj.status.conditions ~= nil then - for _, condition in ipairs(obj.status.conditions) do - hs.message = condition.message - break - end - end - if obj.status.phase ~= nil then - if obj.status.phase == "Failure" then - hs.status = "Degraded" - return hs - elseif obj.status.phase == "Available" then - hs.status = "Healthy" - return hs - elseif obj.status.phase == "Pending" then - hs.status = "Progressing" - return hs - end - end - hs.status = "Progressing" - hs.message = "Waiting for operator to update status" - return hs - end - - group: operators.coreos.com - kind: Subscription - check: | - health_status = {} - if obj.status ~= nil then - if obj.status.conditions ~= nil then - numDegraded = 0 - numPending = 0 - numSuspended = 0 - msg = "" - for i, condition in pairs(obj.status.conditions) do - msg = msg .. i .. ": " .. condition.type .. " | " .. condition.status .. " | " .. (condition.reason and condition.reason or '') .. "\n" - if condition.type == "InstallPlanPending" and condition.status == "True" then - if condition.reason == "RequiresApproval" then - numSuspended = numSuspended + 1 - else - numPending = numPending + 1 - end - elseif (condition.type == "InstallPlanMissing" and condition.reason ~= "ReferencedInstallPlanNotFound") then - numDegraded = numDegraded + 1 - elseif (condition.type == "CatalogSourcesUnhealthy" or condition.type == "InstallPlanFailed") and condition.status == "True" then - numDegraded = numDegraded + 1 - elseif (condition.type == "ResolutionFailed" and condition.reason ~= "ConstraintsNotSatisfiable") then - numDegraded = numDegraded + 1 - elseif (condition.type == 'ChannelDeprecated' and condition.status == "True") then - numDegraded = numDegraded + 1 - end - end - if numDegraded > 0 then - health_status.status = "Degraded" - health_status.message = msg - return health_status - elseif numSuspended > 0 then - health_status.status = "Suspended" - health_status.message = msg - return health_status - elseif numPending > 0 then - health_status.status = "Progressing" - health_status.message = "An install plan for a subscription is pending installation" - return health_status - else - health_status.status = "Healthy" - health_status.message = msg - return health_status - end - end - end - health_status.status = "Progressing" - health_status.message = "An install plan for a subscription is pending installation" - return health_status - - group: operators.coreos.com - kind: InstallPlan - check: | - hs = {} - if obj.status ~= nil then - if obj.status.phase ~= nil then - if obj.status.phase == "Complete" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - elseif obj.status.phase == "RequiresApproval" then - hs.status = "Suspended" - hs.message = obj.status.phase - return hs - else - hs.status = "Progressing" - hs.message = obj.status.phase - return hs - end - end - end - hs.status = "Progressing" - hs.message = "Waiting for InstallPlan to complete" - return hs - - group: platform.stackrox.io - kind: Central - check: | - hs = {} - if obj.status ~= nil and obj.status.conditions ~= nil then - for i, condition in ipairs(obj.status.conditions) do - if condition.status == "True" or condition.reason == "InstallSuccessful" or condition.reason == "UpgradeSuccessful" then - hs.status = "Healthy" - hs.message = "Install Successful" - return hs - end - end - end - hs.status = "Progressing" - hs.message = "Waiting for Central to deploy." - return hs - - group: image.openshift.io - kind: ImageStream - check: | - hs = {} - hs.status = "Progressing" - hs.message = "" - if obj.status ~= nil then - if obj.status.tags ~= nil then - numTags = 0 - for _ , item in pairs(obj.status.tags) do - numTags = numTags + 1 - numItems = 0 - if item.tags ~= nil then - for _ , item in pairs(item.tags) do - numItems = numItems + 1 - end - if numItems == 0 then - return hs - end - end - end - if numTags > 0 then - hs.status = "Healthy" - hs.message = "ImageStream has tags resolved" - return hs - end - end - end - return hs - - group: build.openshift.io - kind: Build - check: | - hs = {} - if obj.status ~= nil then - if obj.status.phase ~= nil then - if obj.status.phase == "Complete" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - end - end - end - hs.status = "Progressing" - hs.message = "Waiting for Build to complete" - return hs - - kind: PersistentVolumeClaim - check: | - hs = {} - if obj.status ~= nil then - if obj.status.phase ~= nil then - if obj.status.phase == "Pending" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - end - if obj.status.phase == "Bound" then - hs.status = "Healthy" - hs.message = obj.status.phase - return hs - end - end - end - hs.status = "Progressing" - hs.message = "Waiting for PVC" - return hs - resourceIgnoreDifferences: - resourceIdentifiers: - - group: route.openshift.io - kind: Route - customization: - jsonPointers: - - /status/ingress - - /metadata/annotations - - group: quay.redhat.com - kind: QuayRegistry - customization: - jsonPointers: - - /status/ingress - - group: cluster.open-cluster-management.io - kind: ManagedCluster - customization: - jsonPointers: - - /spec/managedClusterClientConfigs - resourceExclusions: | - - apiGroups: - - tekton.dev - clusters: - - '*' - kinds: - - TaskRun - - PipelineRun - - apiGroups: - - operator.tekton.dev - clusters: - - '*' - kinds: - - TektonAddon - - TektonInstallerSet - - apiGroups: - - compliance.openshift.io - kinds: - - ComplianceCheckResult - - ComplianceRemediation - - apiGroups: - - policy.open-cluster-management.io - kinds: - - ConfigurationPolicy - - apiGroups: - - noobaa.io - kinds: - - NooBaa - - BucketClass - ha: - enabled: false - rbac: - defaultPolicy: 'role:none' - policy: | - p, role:none, *, *, */*, deny - g, system:cluster-admins, role:admin - g, cluster-admins, role:admin - scopes: "[groups]" diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-instance/base/kustomization.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-instance/base/kustomization.yaml deleted file mode 100644 index 8652851..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-instance/base/kustomization.yaml +++ /dev/null @@ -1,3 +0,0 @@ -resources: -- setenv-cmp-plugin-cm.yaml -- argocd.yaml diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-instance/base/setenv-cmp-plugin-cm.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-instance/base/setenv-cmp-plugin-cm.yaml deleted file mode 100644 index e375aeb..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-instance/base/setenv-cmp-plugin-cm.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: setenv-cmp-plugin - namespace: openshift-gitops -data: - plugin.yaml: | - apiVersion: argoproj.io/v1alpha1 - kind: ConfigManagementPlugin - metadata: - name: setenv-cmp-plugin - spec: - init: - command: [sh, -c, 'echo "Initializing setenv-plugin-cmp..."'] - generate: - command: - - sh - - "-c" - - "set -o pipefail && kustomize build --enable-helm --enable-alpha-plugins . | envsub" diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-notifications/base/kustomization.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-notifications/base/kustomization.yaml deleted file mode 100644 index 2fb0084..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-notifications/base/kustomization.yaml +++ /dev/null @@ -1,2 +0,0 @@ -resources: -- notifications-config.yaml diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-notifications/base/notifications-cm.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-notifications/base/notifications-cm.yaml deleted file mode 100644 index 95ac995..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-notifications/base/notifications-cm.yaml +++ /dev/null @@ -1,256 +0,0 @@ -# No longer needed with NotificationsConfig introduced in 1.12 -apiVersion: v1 -kind: ConfigMap -metadata: - labels: - app.kubernetes.io/managed-by: openshift-gitops - app.kubernetes.io/name: argocd-notifications-cm - app.kubernetes.io/part-of: argocd - annotation: - policy.open-cluster-management.io/disable-templates: "true" - name: argocd-notifications-cm - namespace: openshift-gitops -data: - service.slack: | - token: $slack-token - template.app-deployed: |- - slack: - attachments: | - [{ - "title": "{{ .app.metadata.name}}", - "title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}", - "color": "#18be52", - "fields": [ - { - "title": "Sync Status", - "value": "{{.app.status.sync.status}}", - "short": true - }, - { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", - "short": true - }, - { - "title": "Revision", - "value": "{{.app.status.sync.revision}}", - "short": true - } - {{range $index, $c := .app.status.conditions}} - {{if not $index}},{{end}} - {{if $index}},{{end}} - { - "title": "{{$c.type}}", - "value": "{{$c.message}}", - "short": true - } - {{end}} - ] - }] - deliveryPolicy: Post - groupingKey: "" - notifyBroadcast: false - template.app-health-degraded: |- - slack: - attachments: | - [{ - "title": "{{ .app.metadata.name}}", - "title_link": "{{.context.argocdUrl}}/applications/{{.app.metadata.name}}", - "color": "#f4c030", - "fields": [ - { - "title": "Health Status", - "value": "{{.app.status.health.status}}", - "short": true - }, - { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", - "short": true - } - {{range $index, $c := .app.status.conditions}} - {{if not $index}},{{end}} - {{if $index}},{{end}} - { - "title": "{{$c.type}}", - "value": "{{$c.message}}", - "short": true - } - {{end}} - ] - }] - deliveryPolicy: Post - groupingKey: "" - notifyBroadcast: false - template.app-sync-failed: |- - slack: - attachments: | - [{ - "title": "{{ .app.metadata.name}}", - "title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}", - "color": "#E96D76", - "fields": [ - { - "title": "Sync Status", - "value": "{{.app.status.sync.status}}", - "short": true - }, - { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", - "short": true - } - {{range $index, $c := .app.status.conditions}} - {{if not $index}},{{end}} - {{if $index}},{{end}} - { - "title": "{{$c.type}}", - "value": "{{$c.message}}", - "short": true - } - {{end}} - ] - }] - deliveryPolicy: Post - groupingKey: "" - notifyBroadcast: false - template.app-sync-running: |- - slack: - attachments: | - [{ - "title": "{{ .app.metadata.name}}", - "title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}", - "color": "#0DADEA", - "fields": [ - { - "title": "Sync Status", - "value": "{{.app.status.sync.status}}", - "short": true - }, - { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", - "short": true - } - {{range $index, $c := .app.status.conditions}} - {{if not $index}},{{end}} - {{if $index}},{{end}} - { - "title": "{{$c.type}}", - "value": "{{$c.message}}", - "short": true - } - {{end}} - ] - }] - deliveryPolicy: Post - groupingKey: "" - notifyBroadcast: false - template.app-sync-status-unknown: |- - slack: - attachments: | - [{ - "title": "{{ .app.metadata.name}}", - "title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}", - "color": "#E96D76", - "fields": [ - { - "title": "Sync Status", - "value": "{{.app.status.sync.status}}", - "short": true - }, - { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", - "short": true - } - {{range $index, $c := .app.status.conditions}} - {{if not $index}},{{end}} - {{if $index}},{{end}} - { - "title": "{{$c.type}}", - "value": "{{$c.message}}", - "short": true - } - {{end}} - ] - }] - deliveryPolicy: Post - groupingKey: "" - notifyBroadcast: false - template.app-sync-succeeded: |- - slack: - attachments: | - [{ - "title": "{{ .app.metadata.name}}", - "title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}", - "color": "#18be52", - "fields": [ - { - "title": "Sync Status", - "value": "{{.app.status.sync.status}}", - "short": true - }, - { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", - "short": true - } - {{range $index, $c := .app.status.conditions}} - {{if not $index}},{{end}} - {{if $index}},{{end}} - { - "title": "{{$c.type}}", - "value": "{{$c.message}}", - "short": true - } - {{end}} - ] - }] - deliveryPolicy: Post - groupingKey: "" - notifyBroadcast: false - # trigger.on-created: |- - # - description: Application is created. - # oncePer: app.metadata.name - # send: - # - app-created - # when: "true" - # trigger.on-deleted: |- - # - description: Application is deleted. - # oncePer: app.metadata.name - # send: - # - app-deleted - # when: app.metadata.deletionTimestamp != nil - trigger.on-deployed: |- - - description: Application is synced and healthy. Triggered once per commit. - oncePer: app.status.operationState.syncResult.revision - send: - - app-deployed - when: app.status.operationState.phase in ['Succeeded'] and app.status.health.status - == 'Healthy' - trigger.on-health-degraded: |- - - description: Application has degraded - send: - - app-health-degraded - when: app.status.health.status == 'Degraded' - trigger.on-sync-failed: |- - - description: Application syncing has failed - send: - - app-sync-failed - when: app.status.operationState.phase in ['Error', 'Failed'] - trigger.on-sync-running: |- - - description: Application is being synced - send: - - app-sync-running - when: app.status.operationState.phase in ['Running'] - trigger.on-sync-status-unknown: |- - - description: Application status is 'Unknown' - end: - - app-sync-status-unknown - when: app.status.sync.status == 'Unknown' - trigger.on-sync-succeeded: |- - - description: Application syncing has succeeded - send: - - app-sync-succeeded - when: app.status.operationState.phase in ['Succeeded'] diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-notifications/base/notifications-config.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-notifications/base/notifications-config.yaml deleted file mode 100644 index 07281ce..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-notifications/base/notifications-config.yaml +++ /dev/null @@ -1,540 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: NotificationsConfiguration -metadata: - name: default-notifications-configuration - namespace: openshift-gitops -spec: - services: - service.slack: | - token: $slack-token - templates: - template.app-created: |- - email: - subject: Application {{.app.metadata.name}} has been created. - message: Application {{.app.metadata.name}} has been created. - teams: - title: Application {{.app.metadata.name}} has been created. - template.app-deleted: |- - email: - subject: Application {{.app.metadata.name}} has been deleted. - message: Application {{.app.metadata.name}} has been deleted. - teams: - title: Application {{.app.metadata.name}} has been deleted. - template.app-deployed: |- - email: - subject: New version of an application {{.app.metadata.name}} is up and running. - message: | - {{if eq .serviceType "slack"}}:white_check_mark:{{end}} Application {{.app.metadata.name}} is now running new version of deployments manifests. - slack: - attachments: | - [{ - "title": "{{ .app.metadata.name}}", - "title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}", - "color": "#18be52", - "fields": [ - { - "title": "Sync Status", - "value": "{{.app.status.sync.status}}", - "short": true - }, - { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", - "short": true - }, - { - "title": "Revision", - "value": "{{.app.status.sync.revision}}", - "short": true - } - {{range $index, $c := .app.status.conditions}} - {{if not $index}},{{end}} - {{if $index}},{{end}} - { - "title": "{{$c.type}}", - "value": "{{$c.message}}", - "short": true - } - {{end}} - ] - }] - deliveryPolicy: Post - groupingKey: "" - notifyBroadcast: false - teams: - facts: | - [{ - "name": "Sync Status", - "value": "{{.app.status.sync.status}}" - }, - { - "name": "Repository", - "value": "{{.app.spec.source.repoURL}}" - }, - { - "name": "Revision", - "value": "{{.app.status.sync.revision}}" - } - {{range $index, $c := .app.status.conditions}} - {{if not $index}},{{end}} - {{if $index}},{{end}} - { - "name": "{{$c.type}}", - "value": "{{$c.message}}" - } - {{end}} - ] - potentialAction: |- - [{ - "@type":"OpenUri", - "name":"Operation Application", - "targets":[{ - "os":"default", - "uri":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}" - }] - }, - { - "@type":"OpenUri", - "name":"Open Repository", - "targets":[{ - "os":"default", - "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" - }] - }] - themeColor: '#000080' - title: New version of an application {{.app.metadata.name}} is up and running. - template.app-health-degraded: |- - email: - subject: Application {{.app.metadata.name}} has degraded. - message: | - {{if eq .serviceType "slack"}}:exclamation:{{end}} Application {{.app.metadata.name}} has degraded. - Application details: {{.context.argocdUrl}}/applications/{{.app.metadata.name}}. - slack: - attachments: | - [{ - "title": "{{ .app.metadata.name}}", - "title_link": "{{.context.argocdUrl}}/applications/{{.app.metadata.name}}", - "color": "#f4c030", - "fields": [ - { - "title": "Health Status", - "value": "{{.app.status.health.status}}", - "short": true - }, - { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", - "short": true - } - {{range $index, $c := .app.status.conditions}} - {{if not $index}},{{end}} - {{if $index}},{{end}} - { - "title": "{{$c.type}}", - "value": "{{$c.message}}", - "short": true - } - {{end}} - ] - }] - deliveryPolicy: Post - groupingKey: "" - notifyBroadcast: false - teams: - facts: | - [{ - "name": "Health Status", - "value": "{{.app.status.health.status}}" - }, - { - "name": "Repository", - "value": "{{.app.spec.source.repoURL}}" - } - {{range $index, $c := .app.status.conditions}} - {{if not $index}},{{end}} - {{if $index}},{{end}} - { - "name": "{{$c.type}}", - "value": "{{$c.message}}" - } - {{end}} - ] - potentialAction: | - [{ - "@type":"OpenUri", - "name":"Open Application", - "targets":[{ - "os":"default", - "uri":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}" - }] - }, - { - "@type":"OpenUri", - "name":"Open Repository", - "targets":[{ - "os":"default", - "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" - }] - }] - themeColor: '#FF0000' - title: Application {{.app.metadata.name}} has degraded. - template.app-sync-failed: |- - email: - subject: Failed to sync application {{.app.metadata.name}}. - message: | - {{if eq .serviceType "slack"}}:exclamation:{{end}} The sync operation of application {{.app.metadata.name}} has failed at {{.app.status.operationState.finishedAt}} with the following error: {{.app.status.operationState.message}} - Sync operation details are available at: {{.context.argocdUrl}}/applications/{{.app.metadata.name}}?operation=true . - slack: - attachments: | - [{ - "title": "{{ .app.metadata.name}}", - "title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}", - "color": "#E96D76", - "fields": [ - { - "title": "Sync Status", - "value": "{{.app.status.sync.status}}", - "short": true - }, - { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", - "short": true - } - {{range $index, $c := .app.status.conditions}} - {{if not $index}},{{end}} - {{if $index}},{{end}} - { - "title": "{{$c.type}}", - "value": "{{$c.message}}", - "short": true - } - {{end}} - ] - }] - deliveryPolicy: Post - groupingKey: "" - notifyBroadcast: false - teams: - facts: | - [{ - "name": "Sync Status", - "value": "{{.app.status.sync.status}}" - }, - { - "name": "Failed at", - "value": "{{.app.status.operationState.finishedAt}}" - }, - { - "name": "Repository", - "value": "{{.app.spec.source.repoURL}}" - } - {{range $index, $c := .app.status.conditions}} - {{if not $index}},{{end}} - {{if $index}},{{end}} - { - "name": "{{$c.type}}", - "value": "{{$c.message}}" - } - {{end}} - ] - potentialAction: |- - [{ - "@type":"OpenUri", - "name":"Open Operation", - "targets":[{ - "os":"default", - "uri":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}?operation=true" - }] - }, - { - "@type":"OpenUri", - "name":"Open Repository", - "targets":[{ - "os":"default", - "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" - }] - }] - themeColor: '#FF0000' - title: Failed to sync application {{.app.metadata.name}}. - template.app-sync-running: |- - email: - subject: Start syncing application {{.app.metadata.name}}. - message: | - The sync operation of application {{.app.metadata.name}} has started at {{.app.status.operationState.startedAt}}. - Sync operation details are available at: {{.context.argocdUrl}}/applications/{{.app.metadata.name}}?operation=true . - slack: - attachments: | - [{ - "title": "{{ .app.metadata.name}}", - "title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}", - "color": "#0DADEA", - "fields": [ - { - "title": "Sync Status", - "value": "{{.app.status.sync.status}}", - "short": true - }, - { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", - "short": true - } - {{range $index, $c := .app.status.conditions}} - {{if not $index}},{{end}} - {{if $index}},{{end}} - { - "title": "{{$c.type}}", - "value": "{{$c.message}}", - "short": true - } - {{end}} - ] - }] - deliveryPolicy: Post - groupingKey: "" - notifyBroadcast: false - teams: - facts: | - [{ - "name": "Sync Status", - "value": "{{.app.status.sync.status}}" - }, - { - "name": "Started at", - "value": "{{.app.status.operationState.startedAt}}" - }, - { - "name": "Repository", - "value": "{{.app.spec.source.repoURL}}" - } - {{range $index, $c := .app.status.conditions}} - {{if not $index}},{{end}} - {{if $index}},{{end}} - { - "name": "{{$c.type}}", - "value": "{{$c.message}}" - } - {{end}} - ] - potentialAction: |- - [{ - "@type":"OpenUri", - "name":"Open Operation", - "targets":[{ - "os":"default", - "uri":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}?operation=true" - }] - }, - { - "@type":"OpenUri", - "name":"Open Repository", - "targets":[{ - "os":"default", - "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" - }] - }] - title: Start syncing application {{.app.metadata.name}}. - template.app-sync-status-unknown: |- - email: - subject: Application {{.app.metadata.name}} sync status is 'Unknown' - message: | - {{if eq .serviceType "slack"}}:exclamation:{{end}} Application {{.app.metadata.name}} sync is 'Unknown'. - Application details: {{.context.argocdUrl}}/applications/{{.app.metadata.name}}. - {{if ne .serviceType "slack"}} - {{range $c := .app.status.conditions}} - * {{$c.message}} - {{end}} - {{end}} - slack: - attachments: | - [{ - "title": "{{ .app.metadata.name}}", - "title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}", - "color": "#E96D76", - "fields": [ - { - "title": "Sync Status", - "value": "{{.app.status.sync.status}}", - "short": true - }, - { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", - "short": true - } - {{range $index, $c := .app.status.conditions}} - {{if not $index}},{{end}} - {{if $index}},{{end}} - { - "title": "{{$c.type}}", - "value": "{{$c.message}}", - "short": true - } - {{end}} - ] - }] - deliveryPolicy: Post - groupingKey: "" - notifyBroadcast: false - teams: - facts: | - [{ - "name": "Sync Status", - "value": "{{.app.status.sync.status}}" - }, - { - "name": "Repository", - "value": "{{.app.spec.source.repoURL}}" - } - {{range $index, $c := .app.status.conditions}} - {{if not $index}},{{end}} - {{if $index}},{{end}} - { - "name": "{{$c.type}}", - "value": "{{$c.message}}" - } - {{end}} - ] - potentialAction: |- - [{ - "@type":"OpenUri", - "name":"Open Application", - "targets":[{ - "os":"default", - "uri":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}" - }] - }, - { - "@type":"OpenUri", - "name":"Open Repository", - "targets":[{ - "os":"default", - "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" - }] - }] - title: Application {{.app.metadata.name}} sync status is 'Unknown' - template.app-sync-succeeded: |- - email: - subject: Application {{.app.metadata.name}} has been successfully synced. - message: | - {{if eq .serviceType "slack"}}:white_check_mark:{{end}} Application {{.app.metadata.name}} has been successfully synced at {{.app.status.operationState.finishedAt}}. - Sync operation details are available at: {{.context.argocdUrl}}/applications/{{.app.metadata.name}}?operation=true . - slack: - attachments: | - [{ - "title": "{{ .app.metadata.name}}", - "title_link":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}", - "color": "#18be52", - "fields": [ - { - "title": "Sync Status", - "value": "{{.app.status.sync.status}}", - "short": true - }, - { - "title": "Repository", - "value": "{{.app.spec.source.repoURL}}", - "short": true - } - {{range $index, $c := .app.status.conditions}} - {{if not $index}},{{end}} - {{if $index}},{{end}} - { - "title": "{{$c.type}}", - "value": "{{$c.message}}", - "short": true - } - {{end}} - ] - }] - deliveryPolicy: Post - groupingKey: "" - notifyBroadcast: false - teams: - facts: | - [{ - "name": "Sync Status", - "value": "{{.app.status.sync.status}}" - }, - { - "name": "Synced at", - "value": "{{.app.status.operationState.finishedAt}}" - }, - { - "name": "Repository", - "value": "{{.app.spec.source.repoURL}}" - } - {{range $index, $c := .app.status.conditions}} - {{if not $index}},{{end}} - {{if $index}},{{end}} - { - "name": "{{$c.type}}", - "value": "{{$c.message}}" - } - {{end}} - ] - potentialAction: |- - [{ - "@type":"OpenUri", - "name":"Operation Details", - "targets":[{ - "os":"default", - "uri":"{{.context.argocdUrl}}/applications/{{.app.metadata.name}}?operation=true" - }] - }, - { - "@type":"OpenUri", - "name":"Open Repository", - "targets":[{ - "os":"default", - "uri":"{{.app.spec.source.repoURL | call .repo.RepoURLToHTTPS}}" - }] - }] - themeColor: '#000080' - title: Application {{.app.metadata.name}} has been successfully synced - triggers: - trigger.on-created: |- - - description: Application is created. - oncePer: app.metadata.name - send: - - app-created - when: "true" - trigger.on-deleted: |- - - description: Application is deleted. - oncePer: app.metadata.name - send: - - app-deleted - when: app.metadata.deletionTimestamp != nil - trigger.on-deployed: |- - - description: Application is synced and healthy. Triggered once per commit. - oncePer: app.status.operationState.syncResult.revision - send: - - app-deployed - when: app.status.operationState.phase in ['Succeeded'] and app.status.health.status - == 'Healthy' - trigger.on-health-degraded: |- - - description: Application has degraded - send: - - app-health-degraded - when: app.status.health.status == 'Degraded' - trigger.on-sync-failed: |- - - description: Application syncing has failed - send: - - app-sync-failed - when: app.status.operationState.phase in ['Error', 'Failed'] - trigger.on-sync-running: |- - - description: Application is being synced - send: - - app-sync-running - when: app.status.operationState.phase in ['Running'] - trigger.on-sync-status-unknown: |- - - description: Application status is 'Unknown' - send: - - app-sync-status-unknown - when: app.status.sync.status == 'Unknown' - trigger.on-sync-succeeded: |- - - description: Application syncing has succeeded - send: - - app-sync-succeeded - when: app.status.operationState.phase in ['Succeeded'] diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-secrets/base/argocd-external-secret.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-secrets/base/argocd-external-secret.yaml deleted file mode 100644 index 5144c7b..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-secrets/base/argocd-external-secret.yaml +++ /dev/null @@ -1,20 +0,0 @@ -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: argocd-secret - namespace: openshift-gitops -spec: - data: - - remoteRef: - conversionStrategy: Default - decodingStrategy: None - key: OIDC_ARGOCD - secretKey: oidc.keycloak.clientSecret - refreshInterval: 1h - secretStoreRef: - kind: ClusterSecretStore - name: doppler-cluster - target: - creationPolicy: Merge - deletionPolicy: Retain - name: argocd-secret \ No newline at end of file diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-secrets/base/kustomization.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-secrets/base/kustomization.yaml deleted file mode 100644 index f37ad67..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-secrets/base/kustomization.yaml +++ /dev/null @@ -1,3 +0,0 @@ -resources: -- argocd-external-secret.yaml -- notifications-secret.yaml diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-secrets/base/notifications-secret.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-secrets/base/notifications-secret.yaml deleted file mode 100644 index 2249b0f..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-secrets/base/notifications-secret.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: argocd-notifications-secret - namespace: openshift-gitops -spec: - secretStoreRef: - kind: ClusterSecretStore - name: doppler-cluster - target: - name: argocd-notifications-secret - creationPolicy: Merge - deletionPolicy: Retain - data: - - secretKey: slack-token - remoteRef: - key: GITOPS_SLACK_TOKEN \ No newline at end of file diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-subscription/base/cluster-admin-rolebinding.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-subscription/base/cluster-admin-rolebinding.yaml deleted file mode 100644 index 3e4a00d..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-subscription/base/cluster-admin-rolebinding.yaml +++ /dev/null @@ -1,12 +0,0 @@ -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: argocd-application-controller-cluster-admin -subjects: - - kind: ServiceAccount - name: openshift-gitops-argocd-application-controller - namespace: openshift-gitops -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin \ No newline at end of file diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-subscription/base/gitops-controller-rbac.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-subscription/base/gitops-controller-rbac.yaml deleted file mode 100644 index a37c07d..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-subscription/base/gitops-controller-rbac.yaml +++ /dev/null @@ -1,39 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - annotations: - rbac.authorization.kubernetes.io/autoupdate: "true" - name: gitops-controller -aggregationRule: - clusterRoleSelectors: - - matchLabels: - gitops/aggregate-to-controller: "true" -rules: [] ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: gitops-controller-admin - labels: - gitops/aggregate-to-controller: "true" -aggregationRule: - clusterRoleSelectors: - - matchLabels: - rbac.authorization.k8s.io/aggregate-to-admin: "true" -rules: [] ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: gitops-controller-view - labels: - gitops/aggregate-to-controller: "true" -rules: -- apiGroups: - - '*' - resources: - - '*' - verbs: - - get - - list - - watch diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-subscription/base/gitops-server-rbac.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-subscription/base/gitops-server-rbac.yaml deleted file mode 100644 index d75279a..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-subscription/base/gitops-server-rbac.yaml +++ /dev/null @@ -1,53 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: gitops-server -rules: -- verbs: - - get - - patch - - delete - apiGroups: - - '*' - resources: - - '*' -- verbs: - - create - - get - - list - - watch - - update - - patch - - delete - apiGroups: - - '' - resources: - - secrets - - configmaps -- verbs: - - create - - get - - list - - watch - - update - - delete - - patch - apiGroups: - - argoproj.io - resources: - - applications - - appprojects - - applicationsets -- verbs: - - create - - list - apiGroups: - - '' - resources: - - events -- apiGroups: - - "" - resources: - - pods/exec - verbs: - - create diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-subscription/base/kustomization.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-subscription/base/kustomization.yaml deleted file mode 100644 index 68df95e..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-subscription/base/kustomization.yaml +++ /dev/null @@ -1,8 +0,0 @@ -resources: -- sub-namespace.yaml -- sub-operatorgroup.yaml -- subscription.yaml -- namespace.yaml -- gitops-controller-rbac.yaml -- gitops-server-rbac.yaml -- cluster-admin-rolebinding.yaml diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-subscription/base/namespace.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-subscription/base/namespace.yaml deleted file mode 100644 index 6b876b7..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-subscription/base/namespace.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - labels: - openshift.io/cluster-monitoring: "true" - name: openshift-gitops diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-subscription/base/sub-namespace.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-subscription/base/sub-namespace.yaml deleted file mode 100644 index 909dfec..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-subscription/base/sub-namespace.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - labels: - openshift.io/cluster-monitoring: "true" - name: openshift-gitops-operator diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-subscription/base/sub-operatorgroup.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-subscription/base/sub-operatorgroup.yaml deleted file mode 100644 index 1e83597..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-subscription/base/sub-operatorgroup.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: operators.coreos.com/v1 -kind: OperatorGroup -metadata: - name: gitops-operators - namespace: openshift-gitops-operator -spec: - upgradeStrategy: Default diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-subscription/base/subscription.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-subscription/base/subscription.yaml deleted file mode 100644 index 351b2ab..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/manifests/gitops-subscription/base/subscription.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: operators.coreos.com/v1alpha1 -kind: Subscription -metadata: - name: openshift-gitops-operator - namespace: openshift-gitops-operator -spec: - config: - env: - - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES - value: openshift-gitops, gitops - - name: CONTROLLER_CLUSTER_ROLE - value: gitops-controller - - name: SERVER_CLUSTER_ROLE - value: gitops-server - channel: gitops-1.15 - installPlanApproval: Automatic - name: openshift-gitops-operator - source: redhat-operators - sourceNamespace: openshift-marketplace diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/placement.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/placement.yaml deleted file mode 100644 index d173a04..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/placement.yaml +++ /dev/null @@ -1,28 +0,0 @@ -apiVersion: cluster.open-cluster-management.io/v1beta1 -kind: Placement -metadata: - name: placement-policy-gitops - namespace: acm-policies -spec: - clusterSets: - - global - predicates: - - requiredClusterSelector: - labelSelector: - matchExpressions: - - key: gitops - operator: Exists ---- -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: binding-policy-gitops - namespace: acm-policies -placementRef: - apiGroup: cluster.open-cluster-management.io - kind: Placement - name: placement-policy-gitops -subjects: -- apiGroup: policy.open-cluster-management.io - kind: PolicySet - name: gitops \ No newline at end of file diff --git a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/policy-generator-config.yaml b/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/policy-generator-config.yaml deleted file mode 100644 index 52e1919..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/gitops/base/policy-generator-config.yaml +++ /dev/null @@ -1,60 +0,0 @@ -apiVersion: policy.open-cluster-management.io/v1 -kind: PolicyGenerator -metadata: - name: gitops-policy-generator -policyDefaults: - namespace: acm-policies - remediationAction: enforce -placementBindingDefaults: - name: "binding-policy-gitops" -policies: - - name: policy-eso-secret-store - configurationPolicyAnnotations: - apps.open-cluster-management.io/reconcile-option: replace - manifests: - - path: manifests/eso/base/ - - name: policy-gitops-subscription - remediationAction: enforce - manifests: - - path: manifests/gitops-subscription/base/ - - name: policy-gitops-instance - # Needed to fix issue with merging lists resulting in duplicates - configurationPolicyAnnotations: - apps.open-cluster-management.io/reconcile-option: replace - complianceType: "mustonlyhave" - manifests: - - path: manifests/gitops-instance/base/ - - name: policy-gitops-bootstrap - manifests: - - path: manifests/gitops-bootstrap/base/ - - name: policy-gitops-notifications - remediationAction: enforce - manifests: - - path: manifests/gitops-notifications/base/ - configurationPolicyAnnotations: - policy.open-cluster-management.io/disable-templates: "true" - - name: policy-gitops-alerting - remediationAction: enforce - manifests: - - path: manifests/gitops-alerting/base/ - configurationPolicyAnnotations: - policy.open-cluster-management.io/disable-templates: "true" - # Put ESO secrets into separate policy since it's chicken and egg - # Not being used since I have a global policy that does this but included for example - # - name: policy-gitops-secrets - # remediationAction: enforce - # manifests: - # - path: manifests/gitops-secrets/base/ -policySets: - - name: "gitops" - description: "Policy for bootstrapping cluster with gitops" - policies: - - policy-eso-secret-store - - policy-gitops-subscription - - policy-gitops-instance - - policy-gitops-bootstrap - - policy-gitops-notifications - - policy-gitops-alerting - generatePolicySetPlacement: false - placement: - name: placement-policy-gitops diff --git a/tmp/acm-hub-bootstrap-old/components/policies/opa/gatekeeper-probes-livenessnotset.yaml b/tmp/acm-hub-bootstrap-old/components/policies/opa/gatekeeper-probes-livenessnotset.yaml deleted file mode 100644 index 1871622..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/opa/gatekeeper-probes-livenessnotset.yaml +++ /dev/null @@ -1,459 +0,0 @@ -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: policy-gatekeeper-livenessprobe - annotations: - policy.open-cluster-management.io/standards: NIST SP 800-53 - policy.open-cluster-management.io/categories: CM Configuration Management - policy.open-cluster-management.io/controls: CM-2 Baseline Configuration -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: policy-gatekeeper-containerlivenessprobenotset - spec: - remediationAction: enforce - severity: low - object-templates: - - complianceType: musthave - objectDefinition: - apiVersion: templates.gatekeeper.sh/v1beta1 - kind: ConstraintTemplate - metadata: - creationTimestamp: null - name: containerlivenessprobenotset - spec: - crd: - spec: - names: - kind: ContainerLivenessprobeNotset - targets: - - libs: - - | - package lib.konstraint - - default is_gatekeeper = false - - is_gatekeeper { - has_field(input, "review") - has_field(input.review, "object") - } - - object = input { - not is_gatekeeper - } - - object = input.review.object { - is_gatekeeper - } - - format(msg) = gatekeeper_format { - is_gatekeeper - gatekeeper_format = {"msg": msg} - } - - format(msg) = msg { - not is_gatekeeper - } - - name = object.metadata.name - - kind = object.kind - - has_field(obj, field) { - obj[field] - } - - missing_field(obj, field) = true { - obj[field] == "" - } - - missing_field(obj, field) = true { - not has_field(obj, field) - } - - is_service { - lower(kind) == "service" - } - - is_statefulset { - lower(kind) == "statefulset" - } - - is_daemonset { - lower(kind) == "daemonset" - } - - is_deployment { - lower(kind) == "deployment" - } - - is_pod { - lower(kind) == "pod" - } - - is_namespace { - lower(kind) == "namespace" - } - - is_workload { - containers[_] - } - - pod_containers(pod) = all_containers { - keys = {"containers", "initContainers"} - all_containers = [c | keys[k]; c = pod.spec[k][_]] - } - - containers[container] { - pods[pod] - all_containers = pod_containers(pod) - container = all_containers[_] - } - - containers[container] { - all_containers = pod_containers(object) - container = all_containers[_] - } - - container_images[image] { - containers[container] - image = container.image - } - - container_images[image] { - image = object.spec.image - } - - split_image(image) = [image, "latest"] { - not contains(image, ":") - } - - split_image(image) = [image_name, tag] { - [image_name, tag] = split(image, ":") - } - - pods[pod] { - is_statefulset - pod = object.spec.template - } - - pods[pod] { - is_daemonset - pod = object.spec.template - } - - pods[pod] { - is_deployment - pod = object.spec.template - } - - pods[pod] { - is_pod - pod = object - } - - volumes[volume] { - pods[pod] - volume = pod.spec.volumes[_] - } - - mem_multiple("E") = 1000000000000000000000 { true } - - mem_multiple("P") = 1000000000000000000 { true } - - mem_multiple("T") = 1000000000000000 { true } - - mem_multiple("G") = 1000000000000 { true } - - mem_multiple("M") = 1000000000 { true } - - mem_multiple("k") = 1000000 { true } - - mem_multiple("") = 1000 { true } - - mem_multiple("m") = 1 { true } - - mem_multiple("Ki") = 1024000 { true } - - mem_multiple("Mi") = 1048576000 { true } - - mem_multiple("Gi") = 1073741824000 { true } - - mem_multiple("Ti") = 1099511627776000 { true } - - mem_multiple("Pi") = 1125899906842624000 { true } - - mem_multiple("Ei") = 1152921504606846976000 { true } - - get_suffix(mem) = suffix { - not is_string(mem) - suffix := "" - } - - get_suffix(mem) = suffix { - is_string(mem) - count(mem) > 0 - suffix := substring(mem, count(mem) - 1, -1) - mem_multiple(suffix) - } - - get_suffix(mem) = suffix { - is_string(mem) - count(mem) > 1 - suffix := substring(mem, count(mem) - 2, -1) - mem_multiple(suffix) - } - - get_suffix(mem) = suffix { - is_string(mem) - count(mem) > 1 - not mem_multiple(substring(mem, count(mem) - 1, -1)) - not mem_multiple(substring(mem, count(mem) - 2, -1)) - suffix := "" - } - - get_suffix(mem) = suffix { - is_string(mem) - count(mem) == 1 - not mem_multiple(substring(mem, count(mem) - 1, -1)) - suffix := "" - } - - get_suffix(mem) = suffix { - is_string(mem) - count(mem) == 0 - suffix := "" - } - - canonify_mem(orig) = new { - is_number(orig) - new := orig * 1000 - } - - canonify_mem(orig) = new { - not is_number(orig) - suffix := get_suffix(orig) - raw := replace(orig, suffix, "") - re_match("^[0-9]+$", raw) - new := to_number(raw) * mem_multiple(suffix) - } - - canonify_storage(orig) = new { - is_number(orig) - new := orig - } - - canonify_storage(orig) = new { - not is_number(orig) - suffix := get_suffix(orig) - raw := replace(orig, suffix, "") - re_match("^[0-9]+$", raw) - new := to_number(raw) * mem_multiple(suffix) - } - - canonify_cpu(orig) = new { - is_number(orig) - new := orig * 1000 - } - - canonify_cpu(orig) = new { - not is_number(orig) - endswith(orig, "m") - new := to_number(replace(orig, "m", "")) - } - - canonify_cpu(orig) = new { - not is_number(orig) - not endswith(orig, "m") - re_match("^[0-9]+$", orig) - new := to_number(orig) * 1000 - } - - dropped_capability(container, cap) { - container.securityContext.capabilities.drop[_] == cap - } - - added_capability(container, cap) { - container.securityContext.capabilities.add[_] == cap - } - - no_read_only_filesystem(c) { - not has_field(c, "securityContext") - } - - no_read_only_filesystem(c) { - has_field(c, "securityContext") - not has_field(c.securityContext, "readOnlyRootFilesystem") - } - - priviledge_escalation_allowed(c) { - not has_field(c, "securityContext") - } - - priviledge_escalation_allowed(c) { - has_field(c, "securityContext") - has_field(c.securityContext, "allowPrivilegeEscalation") - } - - |- - package lib.openshift - - import data.lib.konstraint - - is_deploymentconfig { - lower(konstraint.object.apiVersion) == "apps.openshift.io/v1" - lower(konstraint.object.kind) == "deploymentconfig" - } - - is_route { - lower(konstraint.object.apiVersion) == "route.openshift.io/v1" - lower(konstraint.object.kind) == "route" - } - - is_workload_kind { - is_deploymentconfig - } - - is_workload_kind { - konstraint.is_statefulset - } - - is_workload_kind { - konstraint.is_daemonset - } - - is_workload_kind { - konstraint.is_deployment - } - - is_all_kind { - is_workload_kind - } - - is_all_kind { - konstraint.is_service - } - - is_all_kind { - is_route - } - - pods[pod] { - is_deploymentconfig - pod = konstraint.object.spec.template - } - - pods[pod] { - pod = konstraint.pods[_] - } - - containers[container] { - pods[pod] - all_containers = konstraint.pod_containers(pod) - container = all_containers[_] - } - - containers[container] { - container = konstraint.containers[_] - } - rego: |- - package ocp.bestpractices.container_livenessprobe_notset - - import data.lib.konstraint - import data.lib.openshift - - violation[msg] { - openshift.is_workload_kind - - container := openshift.containers[_] - - konstraint.missing_field(container, "livenessProbe") - obj := konstraint.object - - msg := konstraint.format(sprintf("%s/%s: container '%s' has no livenessProbe. See: https://docs.openshift.com/container-platform/latest/applications/application-health.html", [obj.kind, obj.metadata.name, container.name])) - } - target: admission.k8s.gatekeeper.sh - - complianceType: musthave - objectDefinition: - apiVersion: constraints.gatekeeper.sh/v1beta1 - kind: ContainerLivenessprobeNotset - metadata: - name: containerlivenessprobenotset - spec: - enforcementAction: dryrun - match: - kinds: - - apiGroups: - - apps.openshift.io - - apps - kinds: - - DeploymentConfig - - DaemonSet - - Deployment - - StatefulSet - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: policy-gatekeeper-audit-liveness - spec: - remediationAction: inform # will be overridden by remediationAction in parent policy - severity: low - object-templates: - - complianceType: musthave - objectDefinition: - apiVersion: constraints.gatekeeper.sh/v1beta1 - kind: ContainerLivenessprobeNotset - metadata: - name: containerlivenessprobenotset - status: - totalViolations: 0 - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: policy-gatekeeper-admission-liveness - spec: - remediationAction: inform # will be overridden by remediationAction in parent policy - severity: low - object-templates: - - complianceType: mustnothave - objectDefinition: - apiVersion: v1 - kind: Event - metadata: - namespace: openshift-gatekeeper-system # set it to the actual namespace where gatekeeper is running if different - annotations: - constraint_action: deny - constraint_kind: ContainerLivenessprobeNotset - constraint_name: containerlivenessprobenotset - event_type: violation ---- -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: binding-policy-gatekeeper-containerlivenessprobenotset -placementRef: - name: placement-policy-gatekeeper-containerlivenessprobenotset - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: policy-gatekeeper-livenessprobe - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: placement-policy-gatekeeper-containerlivenessprobenotset -spec: - clusterConditions: - - status: "True" - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - { key: policy, operator: In, values: ["opa"] } \ No newline at end of file diff --git a/tmp/acm-hub-bootstrap-old/components/policies/opa/gatekeeper-probes-readinessnotset.yaml b/tmp/acm-hub-bootstrap-old/components/policies/opa/gatekeeper-probes-readinessnotset.yaml deleted file mode 100644 index 3b1386d..0000000 --- a/tmp/acm-hub-bootstrap-old/components/policies/opa/gatekeeper-probes-readinessnotset.yaml +++ /dev/null @@ -1,459 +0,0 @@ -apiVersion: policy.open-cluster-management.io/v1 -kind: Policy -metadata: - name: policy-gatekeeper-readinessprobe - annotations: - policy.open-cluster-management.io/standards: NIST SP 800-53 - policy.open-cluster-management.io/categories: CM Configuration Management - policy.open-cluster-management.io/controls: CM-2 Baseline Configuration -spec: - remediationAction: enforce - disabled: false - policy-templates: - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: policy-gatekeeper-containerreadinessprobenotset - spec: - remediationAction: enforce - severity: low - object-templates: - - complianceType: musthave - objectDefinition: - apiVersion: templates.gatekeeper.sh/v1beta1 - kind: ConstraintTemplate - metadata: - creationTimestamp: null - name: containerreadinessprobenotset - spec: - crd: - spec: - names: - kind: ContainerReadinessprobeNotset - targets: - - libs: - - | - package lib.konstraint - - default is_gatekeeper = false - - is_gatekeeper { - has_field(input, "review") - has_field(input.review, "object") - } - - object = input { - not is_gatekeeper - } - - object = input.review.object { - is_gatekeeper - } - - format(msg) = gatekeeper_format { - is_gatekeeper - gatekeeper_format = {"msg": msg} - } - - format(msg) = msg { - not is_gatekeeper - } - - name = object.metadata.name - - kind = object.kind - - has_field(obj, field) { - obj[field] - } - - missing_field(obj, field) = true { - obj[field] == "" - } - - missing_field(obj, field) = true { - not has_field(obj, field) - } - - is_service { - lower(kind) == "service" - } - - is_statefulset { - lower(kind) == "statefulset" - } - - is_daemonset { - lower(kind) == "daemonset" - } - - is_deployment { - lower(kind) == "deployment" - } - - is_pod { - lower(kind) == "pod" - } - - is_namespace { - lower(kind) == "namespace" - } - - is_workload { - containers[_] - } - - pod_containers(pod) = all_containers { - keys = {"containers", "initContainers"} - all_containers = [c | keys[k]; c = pod.spec[k][_]] - } - - containers[container] { - pods[pod] - all_containers = pod_containers(pod) - container = all_containers[_] - } - - containers[container] { - all_containers = pod_containers(object) - container = all_containers[_] - } - - container_images[image] { - containers[container] - image = container.image - } - - container_images[image] { - image = object.spec.image - } - - split_image(image) = [image, "latest"] { - not contains(image, ":") - } - - split_image(image) = [image_name, tag] { - [image_name, tag] = split(image, ":") - } - - pods[pod] { - is_statefulset - pod = object.spec.template - } - - pods[pod] { - is_daemonset - pod = object.spec.template - } - - pods[pod] { - is_deployment - pod = object.spec.template - } - - pods[pod] { - is_pod - pod = object - } - - volumes[volume] { - pods[pod] - volume = pod.spec.volumes[_] - } - - mem_multiple("E") = 1000000000000000000000 { true } - - mem_multiple("P") = 1000000000000000000 { true } - - mem_multiple("T") = 1000000000000000 { true } - - mem_multiple("G") = 1000000000000 { true } - - mem_multiple("M") = 1000000000 { true } - - mem_multiple("k") = 1000000 { true } - - mem_multiple("") = 1000 { true } - - mem_multiple("m") = 1 { true } - - mem_multiple("Ki") = 1024000 { true } - - mem_multiple("Mi") = 1048576000 { true } - - mem_multiple("Gi") = 1073741824000 { true } - - mem_multiple("Ti") = 1099511627776000 { true } - - mem_multiple("Pi") = 1125899906842624000 { true } - - mem_multiple("Ei") = 1152921504606846976000 { true } - - get_suffix(mem) = suffix { - not is_string(mem) - suffix := "" - } - - get_suffix(mem) = suffix { - is_string(mem) - count(mem) > 0 - suffix := substring(mem, count(mem) - 1, -1) - mem_multiple(suffix) - } - - get_suffix(mem) = suffix { - is_string(mem) - count(mem) > 1 - suffix := substring(mem, count(mem) - 2, -1) - mem_multiple(suffix) - } - - get_suffix(mem) = suffix { - is_string(mem) - count(mem) > 1 - not mem_multiple(substring(mem, count(mem) - 1, -1)) - not mem_multiple(substring(mem, count(mem) - 2, -1)) - suffix := "" - } - - get_suffix(mem) = suffix { - is_string(mem) - count(mem) == 1 - not mem_multiple(substring(mem, count(mem) - 1, -1)) - suffix := "" - } - - get_suffix(mem) = suffix { - is_string(mem) - count(mem) == 0 - suffix := "" - } - - canonify_mem(orig) = new { - is_number(orig) - new := orig * 1000 - } - - canonify_mem(orig) = new { - not is_number(orig) - suffix := get_suffix(orig) - raw := replace(orig, suffix, "") - re_match("^[0-9]+$", raw) - new := to_number(raw) * mem_multiple(suffix) - } - - canonify_storage(orig) = new { - is_number(orig) - new := orig - } - - canonify_storage(orig) = new { - not is_number(orig) - suffix := get_suffix(orig) - raw := replace(orig, suffix, "") - re_match("^[0-9]+$", raw) - new := to_number(raw) * mem_multiple(suffix) - } - - canonify_cpu(orig) = new { - is_number(orig) - new := orig * 1000 - } - - canonify_cpu(orig) = new { - not is_number(orig) - endswith(orig, "m") - new := to_number(replace(orig, "m", "")) - } - - canonify_cpu(orig) = new { - not is_number(orig) - not endswith(orig, "m") - re_match("^[0-9]+$", orig) - new := to_number(orig) * 1000 - } - - dropped_capability(container, cap) { - container.securityContext.capabilities.drop[_] == cap - } - - added_capability(container, cap) { - container.securityContext.capabilities.add[_] == cap - } - - no_read_only_filesystem(c) { - not has_field(c, "securityContext") - } - - no_read_only_filesystem(c) { - has_field(c, "securityContext") - not has_field(c.securityContext, "readOnlyRootFilesystem") - } - - priviledge_escalation_allowed(c) { - not has_field(c, "securityContext") - } - - priviledge_escalation_allowed(c) { - has_field(c, "securityContext") - has_field(c.securityContext, "allowPrivilegeEscalation") - } - - |- - package lib.openshift - - import data.lib.konstraint - - is_deploymentconfig { - lower(konstraint.object.apiVersion) == "apps.openshift.io/v1" - lower(konstraint.object.kind) == "deploymentconfig" - } - - is_route { - lower(konstraint.object.apiVersion) == "route.openshift.io/v1" - lower(konstraint.object.kind) == "route" - } - - is_workload_kind { - is_deploymentconfig - } - - is_workload_kind { - konstraint.is_statefulset - } - - is_workload_kind { - konstraint.is_daemonset - } - - is_workload_kind { - konstraint.is_deployment - } - - is_all_kind { - is_workload_kind - } - - is_all_kind { - konstraint.is_service - } - - is_all_kind { - is_route - } - - pods[pod] { - is_deploymentconfig - pod = konstraint.object.spec.template - } - - pods[pod] { - pod = konstraint.pods[_] - } - - containers[container] { - pods[pod] - all_containers = konstraint.pod_containers(pod) - container = all_containers[_] - } - - containers[container] { - container = konstraint.containers[_] - } - rego: |- - package ocp.bestpractices.container_readinessprobe_notset - - import data.lib.konstraint - import data.lib.openshift - - violation[msg] { - openshift.is_workload_kind - - container := openshift.containers[_] - - konstraint.missing_field(container, "readinessProbe") - obj := konstraint.object - - msg := konstraint.format(sprintf("%s/%s: container '%s' has no readinessProbe. See: https://docs.openshift.com/container-platform/4.4/applications/application-health.html", [obj.kind, obj.metadata.name, container.name])) - } - target: admission.k8s.gatekeeper.sh - - complianceType: musthave - objectDefinition: - apiVersion: constraints.gatekeeper.sh/v1beta1 - kind: ContainerReadinessprobeNotset - metadata: - name: containerreadinessprobenotset - spec: - enforcementAction: dryrun - match: - kinds: - - apiGroups: - - apps.openshift.io - - apps - kinds: - - DeploymentConfig - - DaemonSet - - Deployment - - StatefulSet - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: policy-gatekeeper-audit-readiness - spec: - remediationAction: inform # will be overridden by remediationAction in parent policy - severity: low - object-templates: - - complianceType: musthave - objectDefinition: - apiVersion: constraints.gatekeeper.sh/v1beta1 - kind: ContainerReadinessprobeNotset - metadata: - name: containerreadinessprobenotset - status: - totalViolations: 0 - - objectDefinition: - apiVersion: policy.open-cluster-management.io/v1 - kind: ConfigurationPolicy - metadata: - name: policy-gatekeeper-admission-readiness - spec: - remediationAction: inform # will be overridden by remediationAction in parent policy - severity: low - object-templates: - - complianceType: mustnothave - objectDefinition: - apiVersion: v1 - kind: Event - metadata: - namespace: openshift-gatekeeper-system # set it to the actual namespace where gatekeeper is running if different - annotations: - constraint_action: deny - constraint_kind: ContainerReadinessprobeNotset - constraint_name: containerreadinessprobenotset - event_type: violation ---- -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding -metadata: - name: binding-policy-gatekeeper-containerreadinessprobenotset -placementRef: - name: placement-policy-gatekeeper-containerreadinessprobenotset - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: policy-gatekeeper-readinessprobe - kind: Policy - apiGroup: policy.open-cluster-management.io ---- -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule -metadata: - name: placement-policy-gatekeeper-containerreadinessprobenotset -spec: - clusterConditions: - - status: "True" - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - { key: policy, operator: In, values: ["opa"] } \ No newline at end of file diff --git a/tmp/acm-hub-bootstrap/.ansible-lint b/tmp/acm-hub-bootstrap/.ansible-lint deleted file mode 100644 index 040b390..0000000 --- a/tmp/acm-hub-bootstrap/.ansible-lint +++ /dev/null @@ -1,18 +0,0 @@ -# Vim filetype=yaml ---- -offline: false -#requirements: ansible/execution_environment/requirements.yml - -exclude_paths: - - .cache/ - - .github/ - - charts/ - - common/ - - tests/ - -# warn_list: -# - yaml -# - schema -# - experimental -# - risky-file-permissions -# - var-spacing diff --git a/tmp/acm-hub-bootstrap/.github/dependabot.yml b/tmp/acm-hub-bootstrap/.github/dependabot.yml deleted file mode 100644 index a175e66..0000000 --- a/tmp/acm-hub-bootstrap/.github/dependabot.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- -version: 2 -updates: - # Check for updates to GitHub Actions every week - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "weekly" - diff --git a/tmp/acm-hub-bootstrap/.github/linters/.gitleaks.toml b/tmp/acm-hub-bootstrap/.github/linters/.gitleaks.toml deleted file mode 100644 index 3386909..0000000 --- a/tmp/acm-hub-bootstrap/.github/linters/.gitleaks.toml +++ /dev/null @@ -1,9 +0,0 @@ -[whitelist] -# As of v4, gitleaks only matches against filename, not path in the -# files directive. Leaving content for backwards compatibility. -files = [ - "ansible/plugins/modules/*.py", - "ansible/tests/unit/test_*.py", - "ansible/tests/unit/*.yaml", - "ansible/tests/unit/v2/*.yaml", -] diff --git a/tmp/acm-hub-bootstrap/.github/linters/.markdown-lint.yml b/tmp/acm-hub-bootstrap/.github/linters/.markdown-lint.yml deleted file mode 100644 index a0bc47d..0000000 --- a/tmp/acm-hub-bootstrap/.github/linters/.markdown-lint.yml +++ /dev/null @@ -1,6 +0,0 @@ -{ - "default": true, - "MD003": false, - "MD013": false, - "MD033": false -} \ No newline at end of file diff --git a/tmp/acm-hub-bootstrap/.github/workflows/ansible-lint.yml b/tmp/acm-hub-bootstrap/.github/workflows/ansible-lint.yml deleted file mode 100644 index c2b2981..0000000 --- a/tmp/acm-hub-bootstrap/.github/workflows/ansible-lint.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: Ansible Lint # feel free to pick your own name - -on: [push, pull_request] - -jobs: - build: - runs-on: ubuntu-latest - - steps: - # Important: This sets up your GITHUB_WORKSPACE environment variable - - uses: actions/checkout@v4 - - - name: Lint Ansible Playbook - uses: ansible/ansible-lint-action@v6 - # Let's point it to the path - with: - path: "ansible/" diff --git a/tmp/acm-hub-bootstrap/.github/workflows/jsonschema.yaml b/tmp/acm-hub-bootstrap/.github/workflows/jsonschema.yaml deleted file mode 100644 index 64ce8f8..0000000 --- a/tmp/acm-hub-bootstrap/.github/workflows/jsonschema.yaml +++ /dev/null @@ -1,49 +0,0 @@ ---- -name: Verify json schema - -on: [push, pull_request] - -jobs: - jsonschema_tests: - name: Json Schema tests - strategy: - matrix: - python-version: [3.11] - runs-on: ubuntu-latest - - steps: - - name: Checkout Code - uses: actions/checkout@v4 - - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install check-jsonschema - - - name: Install yq - uses: chrisdickinson/setup-yq@latest - with: - yq-version: v4.30.7 - - - name: Verify secrets json schema against templates - run: | - cp ./values-secret.yaml.template ./values-secret.yaml - check-jsonschema --fill-defaults --schemafile https://raw.githubusercontent.com/validatedpatterns/rhvp.cluster_utils/refs/heads/main/roles/vault_utils/values-secrets.v2.schema.json values-secret.yaml - rm -f ./values-secret.yaml - - - name: Verify ClusterGroup values.schema.json against values-*yaml files - run: | - set -e; for i in values-hub.yaml values-group-one.yaml; do - echo "$i" - # disable shellcheck of single quotes in yq - # shellcheck disable=2016 - yq eval-all '. as $item ireduce ({}; . * $item )' values-global.yaml "$i" > tmp.yaml - check-jsonschema --fill-defaults --schemafile https://raw.githubusercontent.com/validatedpatterns/clustergroup-chart/refs/heads/main/values.schema.json tmp.yaml - rm -f tmp.yaml - done - diff --git a/tmp/acm-hub-bootstrap/.github/workflows/superlinter.yml b/tmp/acm-hub-bootstrap/.github/workflows/superlinter.yml deleted file mode 100644 index 03b6fff..0000000 --- a/tmp/acm-hub-bootstrap/.github/workflows/superlinter.yml +++ /dev/null @@ -1,44 +0,0 @@ ---- -name: Super linter - -on: [push, pull_request] - -jobs: - build: - # Name the Job - name: Super linter - # Set the agent to run on - runs-on: ubuntu-latest - - steps: - - name: Checkout Code - uses: actions/checkout@v4 - with: - # Full git history is needed to get a proper list of changed files within `super-linter` - fetch-depth: 0 - - ################################ - # Run Linter against code base # - ################################ - - name: Lint Code Base - uses: super-linter/super-linter/slim@v7 - env: - VALIDATE_ALL_CODEBASE: true - DEFAULT_BRANCH: main - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # These are the validation we disable atm - VALIDATE_ANSIBLE: false - VALIDATE_BASH: false - VALIDATE_CHECKOV: false - VALIDATE_JSCPD: false - VALIDATE_JSON_PRETTIER: false - VALIDATE_MARKDOWN_PRETTIER: false - VALIDATE_KUBERNETES_KUBECONFORM: false - VALIDATE_PYTHON_PYLINT: false - VALIDATE_SHELL_SHFMT: false - VALIDATE_YAML: false - VALIDATE_YAML_PRETTIER: false - # VALIDATE_DOCKERFILE_HADOLINT: false - # VALIDATE_MARKDOWN: false - # VALIDATE_NATURAL_LANGUAGE: false - # VALIDATE_TEKTON: false diff --git a/tmp/acm-hub-bootstrap/.github/workflows/update-metadata.yml b/tmp/acm-hub-bootstrap/.github/workflows/update-metadata.yml deleted file mode 100644 index 39f5889..0000000 --- a/tmp/acm-hub-bootstrap/.github/workflows/update-metadata.yml +++ /dev/null @@ -1,23 +0,0 @@ -# This job requires a secret called DOCS_TOKEN which should be a PAT token -# that has the permissions described in: -# validatedpatterns/docs/.github/workflows/metadata-docs.yml@main ---- -name: Update docs pattern metadata - -on: - push: - paths: - - "pattern-metadata.yaml" - - ".github/workflows/update-metadata.yml" - -jobs: - update-metadata: - uses: validatedpatterns/docs/.github/workflows/metadata-docs.yml@main - permissions: # Workflow-level permissions - contents: read # Required for "read-all" - packages: write # Allows writing to packages - id-token: write # Allows creating OpenID Connect (OIDC) tokens - secrets: inherit - # For testing you can point to a different branch in the docs repository - # with: - # DOCS_BRANCH: "main" diff --git a/tmp/acm-hub-bootstrap/.gitignore b/tmp/acm-hub-bootstrap/.gitignore deleted file mode 100644 index 3f3db95..0000000 --- a/tmp/acm-hub-bootstrap/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -*~ -*.swp -*.swo -values-secret* -.*.expected.yaml -pattern-vault.init -vault.init -super-linter.log -common/pattern-vault.init diff --git a/tmp/acm-hub-bootstrap/.gitleaks.toml b/tmp/acm-hub-bootstrap/.gitleaks.toml deleted file mode 120000 index c05303b..0000000 --- a/tmp/acm-hub-bootstrap/.gitleaks.toml +++ /dev/null @@ -1 +0,0 @@ -.github/linters/.gitleaks.toml \ No newline at end of file diff --git a/tmp/acm-hub-bootstrap/LICENSE b/tmp/acm-hub-bootstrap/LICENSE deleted file mode 100644 index d645695..0000000 --- a/tmp/acm-hub-bootstrap/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. diff --git a/tmp/acm-hub-bootstrap/Makefile b/tmp/acm-hub-bootstrap/Makefile deleted file mode 100644 index 39d07b7..0000000 --- a/tmp/acm-hub-bootstrap/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -.PHONY: default -default: help - -.PHONY: help -##@ Pattern tasks - -# No need to add a comment here as help is described in common/ -help: - @make -f common/Makefile MAKEFILE_LIST="Makefile common/Makefile" help - -%: - make -f common/Makefile $* - -.PHONY: install -install: operator-deploy post-install ## installs the pattern and loads the secrets - @echo "Installed" - -.PHONY: post-install -post-install: ## Post-install tasks - make load-secrets - @echo "Done" - -.PHONY: test -test: - @make -f common/Makefile PATTERN_OPTS="-f values-global.yaml -f values-hub.yaml" test diff --git a/tmp/acm-hub-bootstrap/README.md b/tmp/acm-hub-bootstrap/README.md deleted file mode 100644 index e09fd81..0000000 --- a/tmp/acm-hub-bootstrap/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# Multicloud Gitops - -[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) - -[Live build status](https://validatedpatterns.io/ci/?pattern=mcgitops) - -## Start Here - -If you've followed a link to this repository, but are not really sure what it contains -or how to use it, head over to [Multicloud GitOps](https://validatedpatterns.io/patterns/multicloud-gitops/) -for additional context and installation instructions - -## Rationale - -The goal for this pattern is to: - -* Use a GitOps approach to manage hybrid and multi-cloud deployments across both public and private clouds. -* Enable cross-cluster governance and application lifecycle management. -* Securely manage secrets across the deployment. diff --git a/tmp/acm-hub-bootstrap/ansible.cfg b/tmp/acm-hub-bootstrap/ansible.cfg deleted file mode 100644 index 516f8b8..0000000 --- a/tmp/acm-hub-bootstrap/ansible.cfg +++ /dev/null @@ -1,6 +0,0 @@ -[defaults] -localhost_warning=False -retry_files_enabled=False -library=~/.ansible/plugins/modules:./ansible/plugins/modules:./common/ansible/plugins/modules:/usr/share/ansible/plugins/modules -roles_path=~/.ansible/roles:./ansible/roles:./common/ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles -filter_plugins=~/.ansible/plugins/filter:./ansible/plugins/filter:./common/ansible/plugins/filter:/usr/share/ansible/plugins/filter diff --git a/tmp/acm-hub-bootstrap/ansible/site.yaml b/tmp/acm-hub-bootstrap/ansible/site.yaml deleted file mode 100644 index f0b7c28..0000000 --- a/tmp/acm-hub-bootstrap/ansible/site.yaml +++ /dev/null @@ -1,17 +0,0 @@ -# This is only needed for RHPDS -- name: MultiCloud-GitOps RHPDS bootstrap - hosts: localhost - connection: local - tasks: - # We cannot use .package or .dnf modules because python3 that is used comes - # from a virtualenv - - name: Launch the installation - ansible.builtin.command: ./pattern.sh make install - args: - chdir: "{{ lookup('env', 'PWD') }}" - register: output - changed_when: false - - - name: Print output of installation - ansible.builtin.debug: - msg: "{{ output }}" diff --git a/tmp/acm-hub-bootstrap/charts/all/config-demo/Chart.yaml b/tmp/acm-hub-bootstrap/charts/all/config-demo/Chart.yaml deleted file mode 100644 index abe0f0b..0000000 --- a/tmp/acm-hub-bootstrap/charts/all/config-demo/Chart.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v2 -description: A Helm chart to build and deploy a use of remote configuration enabled by ACM and Vault -keywords: -- pattern -name: config-demo -version: 0.0.1 diff --git a/tmp/acm-hub-bootstrap/charts/all/config-demo/templates/config-demo-cm.yaml b/tmp/acm-hub-bootstrap/charts/all/config-demo/templates/config-demo-cm.yaml deleted file mode 100644 index ac7fe99..0000000 --- a/tmp/acm-hub-bootstrap/charts/all/config-demo/templates/config-demo-cm.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: config-demo-configmap - labels: - app.kubernetes.io/instance: config-demo -data: - "index.html": |- - - - - - Config Demo - - -

- Hub Cluster domain is '{{ .Values.global.hubClusterDomain }}'
- Pod is running on Local Cluster Domain '{{ .Values.global.localClusterDomain }}'
-

-

- The secret is secret -

- - diff --git a/tmp/acm-hub-bootstrap/charts/all/config-demo/templates/config-demo-deployment.yaml b/tmp/acm-hub-bootstrap/charts/all/config-demo/templates/config-demo-deployment.yaml deleted file mode 100644 index 9deee70..0000000 --- a/tmp/acm-hub-bootstrap/charts/all/config-demo/templates/config-demo-deployment.yaml +++ /dev/null @@ -1,65 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - application: config-demo - name: config-demo -spec: - replicas: 2 - revisionHistoryLimit: 3 - selector: - matchLabels: - deploymentconfig: config-demo - template: - metadata: - creationTimestamp: null - labels: - app: config-demo - deploymentconfig: config-demo - name: config-demo - spec: - containers: - - name: apache - image: registry.access.redhat.com/ubi8/httpd-24:1-226 - #imagePullPolicy: Always - ports: - - containerPort: 8080 - name: http - protocol: TCP - volumeMounts: - - mountPath: /var/www/html - name: config-demo-configmap - - mountPath: /var/www/html/secret - readOnly: true - name: config-demo-secret - resources: {} - terminationMessagePath: /dev/termination-log - terminationMessagePolicy: File - livenessProbe: - httpGet: - path: /index.html - port: 8080 - scheme: HTTP - initialDelaySeconds: 5 - timeoutSeconds: 1 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - readinessProbe: - httpGet: - path: /index.html - port: 8080 - scheme: HTTP - initialDelaySeconds: 5 - timeoutSeconds: 1 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - volumes: - - name: config-demo-configmap - configMap: - defaultMode: 438 - name: config-demo-configmap - - name: config-demo-secret - secret: - secretName: config-demo-secret diff --git a/tmp/acm-hub-bootstrap/charts/all/config-demo/templates/config-demo-external-secret.yaml b/tmp/acm-hub-bootstrap/charts/all/config-demo/templates/config-demo-external-secret.yaml deleted file mode 100644 index 0081dd8..0000000 --- a/tmp/acm-hub-bootstrap/charts/all/config-demo/templates/config-demo-external-secret.yaml +++ /dev/null @@ -1,18 +0,0 @@ ---- -apiVersion: "external-secrets.io/v1beta1" -kind: ExternalSecret -metadata: - name: config-demo-secret - namespace: config-demo -spec: - refreshInterval: 15s - secretStoreRef: - name: {{ .Values.secretStore.name }} - kind: {{ .Values.secretStore.kind }} - target: - name: config-demo-secret - template: - type: Opaque - dataFrom: - - extract: - key: {{ .Values.configdemosecret.key }} diff --git a/tmp/acm-hub-bootstrap/charts/all/config-demo/templates/config-demo-is.yaml b/tmp/acm-hub-bootstrap/charts/all/config-demo/templates/config-demo-is.yaml deleted file mode 100644 index 6a1aea4..0000000 --- a/tmp/acm-hub-bootstrap/charts/all/config-demo/templates/config-demo-is.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: image.openshift.io/v1 -kind: ImageStream -metadata: - name: config-demo -spec: - lookupPolicy: - local: true - tags: - - name: registry.access.redhat.com/ubi8/httpd-24 - importPolicy: {} - referencePolicy: - type: Local diff --git a/tmp/acm-hub-bootstrap/charts/all/config-demo/templates/config-demo-route.yaml b/tmp/acm-hub-bootstrap/charts/all/config-demo/templates/config-demo-route.yaml deleted file mode 100644 index 85d2e38..0000000 --- a/tmp/acm-hub-bootstrap/charts/all/config-demo/templates/config-demo-route.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: route.openshift.io/v1 -kind: Route -metadata: - labels: - app: config-demo - name: config-demo -spec: - port: - targetPort: 8080-tcp - to: - kind: Service - name: config-demo - weight: 100 - wildcardPolicy: None diff --git a/tmp/acm-hub-bootstrap/charts/all/config-demo/templates/config-demo-svc.yaml b/tmp/acm-hub-bootstrap/charts/all/config-demo/templates/config-demo-svc.yaml deleted file mode 100644 index 517c1aa..0000000 --- a/tmp/acm-hub-bootstrap/charts/all/config-demo/templates/config-demo-svc.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - labels: - app: config-demo - name: config-demo -spec: - ports: - - name: 8080-tcp - port: 8080 - protocol: TCP - targetPort: 8080 - selector: - app: config-demo - deploymentconfig: config-demo - sessionAffinity: None - type: ClusterIP diff --git a/tmp/acm-hub-bootstrap/charts/all/config-demo/values.yaml b/tmp/acm-hub-bootstrap/charts/all/config-demo/values.yaml deleted file mode 100644 index 2dda452..0000000 --- a/tmp/acm-hub-bootstrap/charts/all/config-demo/values.yaml +++ /dev/null @@ -1,14 +0,0 @@ ---- -secretStore: - name: vault-backend - kind: ClusterSecretStore - -configdemosecret: - key: secret/data/global/config-demo - -global: - hubClusterDomain: hub.example.com - localClusterDomain: region-one.example.com - -clusterGroup: - isHubCluster: true diff --git a/tmp/acm-hub-bootstrap/charts/all/hello-world/Chart.yaml b/tmp/acm-hub-bootstrap/charts/all/hello-world/Chart.yaml deleted file mode 100644 index 6c9611e..0000000 --- a/tmp/acm-hub-bootstrap/charts/all/hello-world/Chart.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v2 -description: A Helm chart to show a webserver and with no other dependencies -keywords: -- pattern -name: hello-world -version: 0.0.1 diff --git a/tmp/acm-hub-bootstrap/charts/all/hello-world/templates/hello-world-cm.yaml b/tmp/acm-hub-bootstrap/charts/all/hello-world/templates/hello-world-cm.yaml deleted file mode 100644 index e59561c..0000000 --- a/tmp/acm-hub-bootstrap/charts/all/hello-world/templates/hello-world-cm.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: hello-world-configmap - labels: - app.kubernetes.io/instance: hello-world -data: - "index.html": |- - - - - - Hello World - - -

Hello World!

-
-

- Hub Cluster domain is '{{ .Values.global.hubClusterDomain }}'
- Pod is running on Local Cluster Domain '{{ .Values.global.localClusterDomain }}'
-

- - diff --git a/tmp/acm-hub-bootstrap/charts/all/hello-world/templates/hello-world-deployment.yaml b/tmp/acm-hub-bootstrap/charts/all/hello-world/templates/hello-world-deployment.yaml deleted file mode 100644 index 878ebf5..0000000 --- a/tmp/acm-hub-bootstrap/charts/all/hello-world/templates/hello-world-deployment.yaml +++ /dev/null @@ -1,58 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - application: hello-world - name: hello-world -spec: - replicas: 1 - revisionHistoryLimit: 3 - selector: - matchLabels: - deploymentconfig: hello-world - template: - metadata: - labels: - app: hello-world - deploymentconfig: hello-world - name: hello-world - spec: - containers: - - name: apache - image: registry.access.redhat.com/ubi8/httpd-24:1-226 - #imagePullPolicy: Always - ports: - - containerPort: 8080 - name: http - protocol: TCP - volumeMounts: - - mountPath: /var/www/html - name: hello-world-configmap - resources: {} - terminationMessagePath: /dev/termination-log - terminationMessagePolicy: File - livenessProbe: - httpGet: - path: /index.html - port: 8080 - scheme: HTTP - initialDelaySeconds: 5 - timeoutSeconds: 1 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - readinessProbe: - httpGet: - path: /index.html - port: 8080 - scheme: HTTP - initialDelaySeconds: 5 - timeoutSeconds: 1 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - volumes: - - name: hello-world-configmap - configMap: - defaultMode: 438 - name: hello-world-configmap diff --git a/tmp/acm-hub-bootstrap/charts/all/hello-world/templates/hello-world-route.yaml b/tmp/acm-hub-bootstrap/charts/all/hello-world/templates/hello-world-route.yaml deleted file mode 100644 index e321f9e..0000000 --- a/tmp/acm-hub-bootstrap/charts/all/hello-world/templates/hello-world-route.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: route.openshift.io/v1 -kind: Route -metadata: - labels: - app: hello-world - name: hello-world -spec: - port: - targetPort: 8080-tcp - to: - kind: Service - name: hello-world - weight: 100 - wildcardPolicy: None diff --git a/tmp/acm-hub-bootstrap/charts/all/hello-world/templates/hello-world-svc.yaml b/tmp/acm-hub-bootstrap/charts/all/hello-world/templates/hello-world-svc.yaml deleted file mode 100644 index 597f6d5..0000000 --- a/tmp/acm-hub-bootstrap/charts/all/hello-world/templates/hello-world-svc.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - labels: - app: hello-world - name: hello-world -spec: - ports: - - name: 8080-tcp - port: 8080 - protocol: TCP - targetPort: 8080 - selector: - app: hello-world - deploymentconfig: hello-world - sessionAffinity: None - type: ClusterIP diff --git a/tmp/acm-hub-bootstrap/charts/all/hello-world/values.yaml b/tmp/acm-hub-bootstrap/charts/all/hello-world/values.yaml deleted file mode 100644 index 55083f7..0000000 --- a/tmp/acm-hub-bootstrap/charts/all/hello-world/values.yaml +++ /dev/null @@ -1,4 +0,0 @@ ---- -global: - hubClusterDomain: hub.example.com - localCluster: local.example.com diff --git a/tmp/acm-hub-bootstrap/charts/region/.keep b/tmp/acm-hub-bootstrap/charts/region/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/tmp/acm-hub-bootstrap/common/.ansible-lint b/tmp/acm-hub-bootstrap/common/.ansible-lint deleted file mode 100644 index 0522976..0000000 --- a/tmp/acm-hub-bootstrap/common/.ansible-lint +++ /dev/null @@ -1,21 +0,0 @@ -# Vim filetype=yaml ---- -offline: false -skip_list: - - name[template] # Allow Jinja templating inside task and play names - - template-instead-of-copy # Templated files should use template instead of copy - - yaml[line-length] # too long lines - - yaml[indentation] # Forcing lists to be always indented by 2 chars is silly IMO - - var-naming[no-role-prefix] # This would be too much churn for very little gain - - no-changed-when - - var-naming[no-role-prefix] # There are too many changes now and it would be too risky - -# ansible-lint gh workflow cannot find ansible.cfg hence fails to import vault_utils role -exclude_paths: - - ./ansible/playbooks/vault/vault.yaml - - ./ansible/playbooks/iib-ci/iib-ci.yaml - - ./ansible/playbooks/k8s_secrets/k8s_secrets.yml - - ./ansible/playbooks/process_secrets/process_secrets.yml - - ./ansible/playbooks/write-token-kubeconfig/write-token-kubeconfig.yml - - ./ansible/playbooks/process_secrets/display_secrets_info.yml - - ./ansible/roles/vault_utils/tests/test.yml diff --git a/tmp/acm-hub-bootstrap/common/.github/dependabot.yml b/tmp/acm-hub-bootstrap/common/.github/dependabot.yml deleted file mode 100644 index a175e66..0000000 --- a/tmp/acm-hub-bootstrap/common/.github/dependabot.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- -version: 2 -updates: - # Check for updates to GitHub Actions every week - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "weekly" - diff --git a/tmp/acm-hub-bootstrap/common/.github/linters/.gitleaks.toml b/tmp/acm-hub-bootstrap/common/.github/linters/.gitleaks.toml deleted file mode 100644 index 9ad7434..0000000 --- a/tmp/acm-hub-bootstrap/common/.github/linters/.gitleaks.toml +++ /dev/null @@ -1,4 +0,0 @@ -[whitelist] -# As of v4, gitleaks only matches against filename, not path in the -# files directive. Leaving content for backwards compatibility. -files = [ ] diff --git a/tmp/acm-hub-bootstrap/common/.github/linters/.markdown-lint.yml b/tmp/acm-hub-bootstrap/common/.github/linters/.markdown-lint.yml deleted file mode 100644 index a0bc47d..0000000 --- a/tmp/acm-hub-bootstrap/common/.github/linters/.markdown-lint.yml +++ /dev/null @@ -1,6 +0,0 @@ -{ - "default": true, - "MD003": false, - "MD013": false, - "MD033": false -} \ No newline at end of file diff --git a/tmp/acm-hub-bootstrap/common/.github/workflows/pattern-sh-ci.yml b/tmp/acm-hub-bootstrap/common/.github/workflows/pattern-sh-ci.yml deleted file mode 100644 index ed0e6a0..0000000 --- a/tmp/acm-hub-bootstrap/common/.github/workflows/pattern-sh-ci.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: Run Bash Script on Multiple Distributions - -on: - push: - paths: - - "scripts/**" - - "Makefile" - branches: - - main - pull_request: - paths: - - "scripts/**" - - "Makefile" - -jobs: - run-script: - name: Run Bash Script - strategy: - matrix: - # Fedora is not an option yet - os: [ubuntu-latest, ubuntu-22.04] - runs-on: ${{ matrix.os }} - - steps: - - name: Checkout Repository - uses: actions/checkout@v4 - - - name: Install Podman on Ubuntu - if: contains(matrix.os, 'ubuntu') - run: | - sudo apt-get update - sudo apt-get install -y podman - - # Currently we do not do MacOSX as it is not free, maybe in the future - # - name: Install Podman on macOS - # if: contains(matrix.os, 'macos') - # run: | - # brew install podman - # podman machine init - # podman machine start - - - name: Verify Podman Installation - run: podman --version - - - name: Run pattern.sh script - run: | - export TARGET_BRANCH=main - ./scripts/pattern-util.sh make validate-origin diff --git a/tmp/acm-hub-bootstrap/common/.github/workflows/superlinter.yml b/tmp/acm-hub-bootstrap/common/.github/workflows/superlinter.yml deleted file mode 100644 index 03b6fff..0000000 --- a/tmp/acm-hub-bootstrap/common/.github/workflows/superlinter.yml +++ /dev/null @@ -1,44 +0,0 @@ ---- -name: Super linter - -on: [push, pull_request] - -jobs: - build: - # Name the Job - name: Super linter - # Set the agent to run on - runs-on: ubuntu-latest - - steps: - - name: Checkout Code - uses: actions/checkout@v4 - with: - # Full git history is needed to get a proper list of changed files within `super-linter` - fetch-depth: 0 - - ################################ - # Run Linter against code base # - ################################ - - name: Lint Code Base - uses: super-linter/super-linter/slim@v7 - env: - VALIDATE_ALL_CODEBASE: true - DEFAULT_BRANCH: main - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # These are the validation we disable atm - VALIDATE_ANSIBLE: false - VALIDATE_BASH: false - VALIDATE_CHECKOV: false - VALIDATE_JSCPD: false - VALIDATE_JSON_PRETTIER: false - VALIDATE_MARKDOWN_PRETTIER: false - VALIDATE_KUBERNETES_KUBECONFORM: false - VALIDATE_PYTHON_PYLINT: false - VALIDATE_SHELL_SHFMT: false - VALIDATE_YAML: false - VALIDATE_YAML_PRETTIER: false - # VALIDATE_DOCKERFILE_HADOLINT: false - # VALIDATE_MARKDOWN: false - # VALIDATE_NATURAL_LANGUAGE: false - # VALIDATE_TEKTON: false diff --git a/tmp/acm-hub-bootstrap/common/.gitignore b/tmp/acm-hub-bootstrap/common/.gitignore deleted file mode 100644 index 454efc9..0000000 --- a/tmp/acm-hub-bootstrap/common/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -__pycache__/ -*.py[cod] -*~ -*.swp -*.swo -values-secret.yaml -.*.expected.yaml -.vscode -pattern-vault.init -pattern-vault.init.bak -super-linter.log -golang-external-secrets/Chart.lock -hashicorp-vault/Chart.lock diff --git a/tmp/acm-hub-bootstrap/common/.gitleaks.toml b/tmp/acm-hub-bootstrap/common/.gitleaks.toml deleted file mode 120000 index c05303b..0000000 --- a/tmp/acm-hub-bootstrap/common/.gitleaks.toml +++ /dev/null @@ -1 +0,0 @@ -.github/linters/.gitleaks.toml \ No newline at end of file diff --git a/tmp/acm-hub-bootstrap/common/Changes.md b/tmp/acm-hub-bootstrap/common/Changes.md deleted file mode 100644 index c12f175..0000000 --- a/tmp/acm-hub-bootstrap/common/Changes.md +++ /dev/null @@ -1,153 +0,0 @@ -# Changes - -## Sep 24, 2024 - -* Ansible has been moved out of the common code tree, you must use a clustergroup chart that is >= 0.9.1 - -## Sep 6, 2024 - -* Most charts have been removed from the tree. To get the charts you now have to point to them - -## Sep 25, 2023 - -* Upgraded ESO to v0.9.5 - -## Aug 17, 2023 - -* Introduced support for multisource applications via .chart + .chartVersion - -## Jul 8, 2023 - -* Introduced a default of 20 for sync failures retries in argo applications (global override via global.options.applicationRetryLimit - and per-app override via .syncPolicy) - -## May 22, 2023 - -* Upgraded ESO to 0.8.2 -* *Important* we now use the newly blessed sso config for argo. This means that gitops < 1.8 are *unsupported* - -## May 18, 2023 - -* Introduce a EXTRA_HELM_OPTS env variable that will be passed to the helm invocations - -## April 21, 2023 - -* Added labels and annotation support to namespaces.yaml template - -## Apr 11, 2023 - -* Apply the ACM ocp-gitops-policy everywhere but the hub - -## Apr 7, 2023 - -* Moved to gitops-1.8 channel by default (stable is unmaintained and will be dropped starting with ocp-4.13) - -## March 20, 2023 - -* Upgraded ESO to 0.8.1 - -## February 9, 2023 - -* Add support for /values-.yaml and for /values--.yaml - -## January 29, 2023 - -* Stop extracting the HUB's CA via an imperative job running on the imported cluster. - Just use ACM to push the HUB's CA out to the managed clusters. - -## January 23, 2023 - -* Add initial support for running ESO on ACM-imported clusters - -## January 18, 2023 - -* Add validate-schema target - -## January 13, 2023 - -* Simplify the secrets paths when using argo hosted sites - -## January 10, 2023 - -* vaultPrefixes is now optional in the v2 secret spec and defaults to ["hub"] - -## December 9, 2022 - -* Dropped insecureUnsealVaultInsideCluster (and file_unseal) entirely. Now - vault is always unsealed via a cronjob in the cluster. It is recommended to - store the imperative/vaultkeys secret offline securely and then delete it. - -## December 8, 2022 - -* Removed the legacy installation targets: - `deploy upgrade legacy-deploy legacy-upgrade` - Patterns must now use the operator-based installation - -## November 29, 2022 - -* Upgraded vault-helm to 0.23.0 -* Enable vault-ssl by default - -## November 22, 2022 - -* Implemented a new format for the values-secret.yaml. Example can be found in examples/ folder -* Now the order of values-secret file lookup is the following: - 1. ~/values-secret-.yaml - 2. ~/values-secret.yaml - 3. /values-secret.yaml.template -* Add support for ansible vault encrypted values-secret files. You can now encrypt your values-secret file - at rest with `ansible-vault encrypt ~/values-secret.yaml`. When running `make load-secrets` if an encrypted - file is encountered the user will be prompted automatically for the password to decrypt it. - -## November 6, 2022 - -* Add support for /values--.yaml (e.g. /values-AWS-group-one.yaml) - -## October 28, 2022 - -* Updated vault helm chart to v0.22.1 and vault containers to 1.12.0 - -## October 25, 2022 - -* Updated External Secrets Operator to v0.6.0 -* Moved to -UBI based ESO containers - -## October 13, 2022 - -* Added global.clusterVersion as a new helm variable which represents the OCP - Major.Minor cluster version. By default now a user can add a - values--.yaml file to have specific cluster version - overrides (e.g. values-4.10-hub.yaml). Will need Validated Patterns Operator >= 0.0.6 - when deploying with the operator. Note: When using the ArgoCD Hub and spoke model, - you cannot have spokes with a different version of OCP than the hub. - -## October 4, 2022 - -* Extended the values-secret.yaml file to support multiple vault paths and re-wrote - the push_secrets feature as python module plugin. This requires the following line - in a pattern's ansible.cfg's '[defaults]' stanza: - - `library=~/.ansible/plugins/modules:./ansible/plugins/modules:./common/ansible/plugins/modules:/usr/share/ansible/plugins/modules` - -## October 3, 2022 - -* Restore the ability to install a non-default site: `make TARGET_SITE=mysite install` -* Revised tests (new output and filenames, requires adding new result files to Git) -* ACM 2.6 required for ACM-based managed sites -* Introduced global.clusterDomain template variable (without the `apps.` prefix) -* Removed the ability to send specific charts to another cluster, use hosted argo sites instead -* Added the ability to have the hub host `values-{site}.yaml` for spoke clusters. - - The following example would deploy the namespaces, subscriptions, and - applications defined in `values-group-one.yaml` to the `perth` cluster - directly from ArgoCD on the hub. - - ```yaml - managedClusterGroups: - - name: group-one - hostedArgoSites: - - name: perth - domain: perth1.beekhof.net - bearerKeyPath: secret/data/hub/cluster_perth - caKeyPath: secret/data/hub/cluster_perth_ca - ``` diff --git a/tmp/acm-hub-bootstrap/common/LICENSE b/tmp/acm-hub-bootstrap/common/LICENSE deleted file mode 100644 index d645695..0000000 --- a/tmp/acm-hub-bootstrap/common/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. diff --git a/tmp/acm-hub-bootstrap/common/Makefile b/tmp/acm-hub-bootstrap/common/Makefile deleted file mode 100644 index 84f6afc..0000000 --- a/tmp/acm-hub-bootstrap/common/Makefile +++ /dev/null @@ -1,255 +0,0 @@ -NAME ?= $(shell basename "`pwd`") - -ifneq ($(origin TARGET_SITE), undefined) - TARGET_SITE_OPT=--set main.clusterGroupName=$(TARGET_SITE) -endif - -# This variable can be set in order to pass additional helm arguments from the -# the command line. I.e. we can set things without having to tweak values files -EXTRA_HELM_OPTS ?= - -# This variable can be set in order to pass additional ansible-playbook arguments from the -# the command line. I.e. we can set -vvv for more verbose logging -EXTRA_PLAYBOOK_OPTS ?= - -# INDEX_IMAGES=registry-proxy.engineering.redhat.com/rh-osbs/iib:394248 -# or -# INDEX_IMAGES=registry-proxy.engineering.redhat.com/rh-osbs/iib:394248,registry-proxy.engineering.redhat.com/rh-osbs/iib:394249 -INDEX_IMAGES ?= - -TARGET_ORIGIN ?= origin -# This is to ensure that whether we start with a git@ or https:// URL, we end up with an https:// URL -# This is because we expect to use tokens for repo authentication as opposed to SSH keys -TARGET_REPO=$(shell git ls-remote --get-url --symref $(TARGET_ORIGIN) | sed -e 's/.*URL:[[:space:]]*//' -e 's%^git@%%' -e 's%^https://%%' -e 's%:%/%' -e 's%^%https://%') -# git branch --show-current is also available as of git 2.22, but we will use this for compatibility -TARGET_BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD) - -UUID_FILE ?= ~/.config/validated-patterns/pattern-uuid -UUID_HELM_OPTS ?= - -# --set values always take precedence over the contents of -f -ifneq ("$(wildcard $(UUID_FILE))","") - UUID := $(shell cat $(UUID_FILE)) - UUID_HELM_OPTS := --set main.analyticsUUID=$(UUID) -endif - -# Set the secret name *and* its namespace when deploying from private repositories -# The format of said secret is documented here: https://argo-cd.readthedocs.io/en/stable/operator-manual/declarative-setup/#repositories -TOKEN_SECRET ?= -TOKEN_NAMESPACE ?= - -ifeq ($(TOKEN_SECRET),) - HELM_OPTS=-f values-global.yaml --set main.git.repoURL="$(TARGET_REPO)" --set main.git.revision=$(TARGET_BRANCH) $(TARGET_SITE_OPT) $(UUID_HELM_OPTS) $(EXTRA_HELM_OPTS) -else - # When we are working with a private repository we do not escape the git URL as it might be using an ssh secret which does not use https:// - TARGET_CLEAN_REPO=$(shell git ls-remote --get-url --symref $(TARGET_ORIGIN)) - HELM_OPTS=-f values-global.yaml --set main.tokenSecret=$(TOKEN_SECRET) --set main.tokenSecretNamespace=$(TOKEN_NAMESPACE) --set main.git.repoURL="$(TARGET_CLEAN_REPO)" --set main.git.revision=$(TARGET_BRANCH) $(TARGET_SITE_OPT) $(UUID_HELM_OPTS) $(EXTRA_HELM_OPTS) -endif - -# Helm does the right thing and fetches all the tags and detects the newest one -PATTERN_INSTALL_CHART ?= oci://quay.io/hybridcloudpatterns/pattern-install - -##@ Pattern Common Tasks - -.PHONY: help -help: ## This help message - @echo "Pattern: $(NAME)" - @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^(\s|[a-zA-Z_0-9-])+:.*?##/ { printf " \033[36m%-35s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) - -# Makefiles in the individual patterns should call these targets explicitly -# e.g. from industrial-edge: make -f common/Makefile show -.PHONY: show -show: ## show the starting template without installing it - helm template $(PATTERN_INSTALL_CHART) --name-template $(NAME) $(HELM_OPTS) - -preview-all: ## (EXPERIMENTAL) Previews all applications on hub and managed clusters - @echo "NOTE: This is just a tentative approximation of rendering all hub and managed clusters templates" - @common/scripts/preview-all.sh $(TARGET_REPO) $(TARGET_BRANCH) - -preview-%: - $(eval CLUSTERGROUP ?= $(shell yq ".main.clusterGroupName" values-global.yaml)) - @common/scripts/preview.sh $(CLUSTERGROUP) $* $(TARGET_REPO) $(TARGET_BRANCH) - -.PHONY: operator-deploy -operator-deploy operator-upgrade: validate-prereq validate-origin validate-cluster ## runs helm install - @common/scripts/deploy-pattern.sh $(NAME) $(PATTERN_INSTALL_CHART) $(HELM_OPTS) - -.PHONY: uninstall -uninstall: ## runs helm uninstall - $(eval CSV := $(shell oc get subscriptions -n openshift-operators openshift-gitops-operator -ojsonpath={.status.currentCSV})) - helm uninstall $(NAME) - @oc delete csv -n openshift-operators $(CSV) - -.PHONY: load-secrets -load-secrets: ## loads the secrets into the backend determined by values-global setting - common/scripts/process-secrets.sh $(NAME) - -.PHONY: legacy-load-secrets -legacy-load-secrets: ## loads the secrets into vault (only) - common/scripts/vault-utils.sh push_secrets $(NAME) - -.PHONY: secrets-backend-vault -secrets-backend-vault: ## Edits values files to use default Vault+ESO secrets config - common/scripts/set-secret-backend.sh vault - common/scripts/manage-secret-app.sh vault present - common/scripts/manage-secret-app.sh golang-external-secrets present - common/scripts/manage-secret-namespace.sh validated-patterns-secrets absent - @git diff --exit-code || echo "Secrets backend set to vault, please review changes, commit, and push to activate in the pattern" - -.PHONY: secrets-backend-kubernetes -secrets-backend-kubernetes: ## Edits values file to use Kubernetes+ESO secrets config - common/scripts/set-secret-backend.sh kubernetes - common/scripts/manage-secret-namespace.sh validated-patterns-secrets present - common/scripts/manage-secret-app.sh vault absent - common/scripts/manage-secret-app.sh golang-external-secrets present - @git diff --exit-code || echo "Secrets backend set to kubernetes, please review changes, commit, and push to activate in the pattern" - -.PHONY: secrets-backend-none -secrets-backend-none: ## Edits values files to remove secrets manager + ESO - common/scripts/set-secret-backend.sh none - common/scripts/manage-secret-app.sh vault absent - common/scripts/manage-secret-app.sh golang-external-secrets absent - common/scripts/manage-secret-namespace.sh validated-patterns-secrets absent - @git diff --exit-code || echo "Secrets backend set to none, please review changes, commit, and push to activate in the pattern" - -.PHONY: load-iib -load-iib: ## CI target to install Index Image Bundles - @set -e; if [ x$(INDEX_IMAGES) != x ]; then \ - ansible-playbook $(EXTRA_PLAYBOOK_OPTS) rhvp.cluster_utils.iib_ci; \ - else \ - echo "No INDEX_IMAGES defined. Bailing out"; \ - exit 1; \ - fi - -.PHONY: token-kubeconfig -token-kubeconfig: ## Create a local ~/.kube/config with password (not usually needed) - common/scripts/write-token-kubeconfig.sh - -##@ Validation Tasks - -# We only check the remote ssh git branch's existance if we're not running inside a container -# as getting ssh auth working inside a container seems a bit brittle -# If the main repoUpstreamURL field is set, then we need to check against -# that and not target_repo -.PHONY: validate-origin -validate-origin: ## verify the git origin is available - @echo "Checking repository:" - $(eval UPSTREAMURL := $(shell yq -r '.main.git.repoUpstreamURL // (.main.git.repoUpstreamURL = "")' values-global.yaml)) - @if [ -z "$(UPSTREAMURL)" ]; then\ - echo -n " $(TARGET_REPO) - branch '$(TARGET_BRANCH)': ";\ - git ls-remote --exit-code --heads $(TARGET_REPO) $(TARGET_BRANCH) >/dev/null &&\ - echo "OK" || (echo "NOT FOUND"; exit 1);\ - else\ - echo "Upstream URL set to: $(UPSTREAMURL)";\ - echo -n " $(UPSTREAMURL) - branch '$(TARGET_BRANCH)': ";\ - git ls-remote --exit-code --heads $(UPSTREAMURL) $(TARGET_BRANCH) >/dev/null &&\ - echo "OK" || (echo "NOT FOUND"; exit 1);\ - fi - -.PHONY: validate-cluster -validate-cluster: ## Do some cluster validations before installing - @echo "Checking cluster:" - @echo -n " cluster-info: " - @oc cluster-info >/dev/null && echo "OK" || (echo "Error"; exit 1) - @echo -n " storageclass: " - @if [ `oc get storageclass -o go-template='{{printf "%d\n" (len .items)}}'` -eq 0 ]; then\ - echo "WARNING: No storageclass found";\ - else\ - echo "OK";\ - fi - - -.PHONY: validate-schema -validate-schema: ## validates values files against schema in common/clustergroup - $(eval VAL_PARAMS := $(shell for i in ./values-*.yaml; do echo -n "$${i} "; done)) - @echo -n "Validating clustergroup schema of: " - @set -e; for i in $(VAL_PARAMS); do echo -n " $$i"; helm template oci://quay.io/hybridcloudpatterns/clustergroup $(HELM_OPTS) -f "$${i}" >/dev/null; done - @echo - -.PHONY: validate-prereq -validate-prereq: ## verify pre-requisites - $(eval GLOBAL_PATTERN := $(shell yq -r .global.pattern values-global.yaml)) - @if [ $(NAME) != $(GLOBAL_PATTERN) ]; then\ - echo "";\ - echo "WARNING: folder directory is \"$(NAME)\" and global.pattern is set to \"$(GLOBAL_PATTERN)\"";\ - echo "this can create problems. Please make sure they are the same!";\ - echo "";\ - fi - @if [ ! -f /run/.containerenv ]; then\ - echo "Checking prerequisites:";\ - echo -n " Check for python-kubernetes: ";\ - if ! ansible -m ansible.builtin.command -a "{{ ansible_python_interpreter }} -c 'import kubernetes'" localhost > /dev/null 2>&1; then echo "Not found"; exit 1; fi;\ - echo "OK";\ - echo -n " Check for kubernetes.core collection: ";\ - if ! ansible-galaxy collection list | grep kubernetes.core > /dev/null 2>&1; then echo "Not found"; exit 1; fi;\ - echo "OK";\ - else\ - if [ -f values-global.yaml ]; then\ - OUT=`yq -r '.main.multiSourceConfig.enabled // (.main.multiSourceConfig.enabled = "false")' values-global.yaml`;\ - if [ "$${OUT,,}" = "false" ]; then\ - echo "You must set \".main.multiSourceConfig.enabled: true\" in your 'values-global.yaml' file";\ - echo "because your common subfolder is the slimmed down version with no helm charts in it";\ - exit 1;\ - fi;\ - fi;\ - fi - -.PHONY: argo-healthcheck -argo-healthcheck: ## Checks if all argo applications are synced - @echo "Checking argo applications" - $(eval APPS := $(shell oc get applications.argoproj.io -A -o jsonpath='{range .items[*]}{@.metadata.namespace}{","}{@.metadata.name}{"\n"}{end}')) - @NOTOK=0; \ - for i in $(APPS); do\ - n=`echo "$${i}" | cut -f1 -d,`;\ - a=`echo "$${i}" | cut -f2 -d,`;\ - STATUS=`oc get -n "$${n}" applications.argoproj.io/"$${a}" -o jsonpath='{.status.sync.status}'`;\ - if [[ $$STATUS != "Synced" ]]; then\ - NOTOK=$$(( $${NOTOK} + 1));\ - fi;\ - HEALTH=`oc get -n "$${n}" applications.argoproj.io/"$${a}" -o jsonpath='{.status.health.status}'`;\ - if [[ $$HEALTH != "Healthy" ]]; then\ - NOTOK=$$(( $${NOTOK} + 1));\ - fi;\ - echo "$${n} $${a} -> Sync: $${STATUS} - Health: $${HEALTH}";\ - done;\ - if [ $${NOTOK} -gt 0 ]; then\ - echo "Some applications are not synced or are unhealthy";\ - exit 1;\ - fi - - -##@ Test and Linters Tasks - -.PHONY: qe-tests -qe-tests: ## Runs the tests that QE runs - @set -e; if [ -f ./tests/interop/run_tests.sh ]; then \ - pushd ./tests/interop; ./run_tests.sh; popd; \ - else \ - echo "No ./tests/interop/run_tests.sh found skipping"; \ - fi - -.PHONY: super-linter -super-linter: ## Runs super linter locally - rm -rf .mypy_cache - podman run -e RUN_LOCAL=true -e USE_FIND_ALGORITHM=true \ - -e VALIDATE_ANSIBLE=false \ - -e VALIDATE_BASH=false \ - -e VALIDATE_CHECKOV=false \ - -e VALIDATE_DOCKERFILE_HADOLINT=false \ - -e VALIDATE_JSCPD=false \ - -e VALIDATE_JSON_PRETTIER=false \ - -e VALIDATE_MARKDOWN_PRETTIER=false \ - -e VALIDATE_KUBERNETES_KUBECONFORM=false \ - -e VALIDATE_PYTHON_PYLINT=false \ - -e VALIDATE_SHELL_SHFMT=false \ - -e VALIDATE_TEKTON=false \ - -e VALIDATE_YAML=false \ - -e VALIDATE_YAML_PRETTIER=false \ - $(DISABLE_LINTERS) \ - -v $(PWD):/tmp/lint:rw,z \ - -w /tmp/lint \ - ghcr.io/super-linter/super-linter:slim-v7 - -.PHONY: deploy upgrade legacy-deploy legacy-upgrade -deploy upgrade legacy-deploy legacy-upgrade: - @echo "UNSUPPORTED TARGET: please switch to 'operator-deploy'"; exit 1 diff --git a/tmp/acm-hub-bootstrap/common/README.md b/tmp/acm-hub-bootstrap/common/README.md deleted file mode 100644 index b36bc1a..0000000 --- a/tmp/acm-hub-bootstrap/common/README.md +++ /dev/null @@ -1,51 +0,0 @@ -# Validated Patterns common/ repository - -[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) - -## Note - -This is the `main` branch of common and it assumes that the pattern is fully -multisource (meaning that any used charts from VP is actually referenced from -either a helm chart repository or quay repository). I.e. there are no helm -charts contained in this branch of common and there is no ansible code neither. - -The helm charts now live in separate repositories under the VP -[organization](https://github.com/validatedpatterns) on GitHub. The repositories are: - -- clustergroup-chart -- pattern-install-chart -- hashicorp-vault-chart -- golang-external-secrets-chart -- acm-chart -- letsencrypt-chart - -The ansible bits live in this [repository](https://github.com/validatedpatterns/rhvp.cluster_utils) - -In order to be able to use this "slimmed-down" main branch of common you *must* -use a 0.9.* clustergroup-chart that. Add the following to your `values-global.yaml`: - -```yaml -main: - multiSourceConfig: - enabled: true - clusterGroupChartVersion: 0.9.* -``` - -## Start Here - -This repository is never used as standalone. It is usually imported in each pattern as a subtree. -In order to import the common subtree the very first time you can use the script -[make_common_subtree.sh](scripts/make-common-subtree.sh). - -In order to update your common subtree inside your pattern repository you can either use -`https://github.com/validatedpatterns/utilities/blob/main/scripts/update-common-everywhere.sh` or -do it manually with the following commands: - -```sh -git remote add -f common-upstream https://github.com/validatedpatterns/common.git -git merge -s subtree -Xtheirs -Xsubtree=common common-upstream/main -``` - -## Secrets - -There are two different secret formats parsed by the ansible bits. Both are documented [here](https://github.com/validatedpatterns/common/tree/main/ansible/roles/vault_utils/README.md) diff --git a/tmp/acm-hub-bootstrap/common/requirements.yml b/tmp/acm-hub-bootstrap/common/requirements.yml deleted file mode 100644 index cb11ca2..0000000 --- a/tmp/acm-hub-bootstrap/common/requirements.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -# Define Ansible collection requirements here -collections: - - name: git+https://github.com/validatedpatterns/rhvp.cluster_utils.git,v1 diff --git a/tmp/acm-hub-bootstrap/common/scripts/deploy-pattern.sh b/tmp/acm-hub-bootstrap/common/scripts/deploy-pattern.sh deleted file mode 100755 index 61074fe..0000000 --- a/tmp/acm-hub-bootstrap/common/scripts/deploy-pattern.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash -set -o pipefail - -RUNS=10 -WAIT=15 -# Retry five times because the CRD might not be fully installed yet -echo -n "Installing pattern: " -for i in $(seq 1 ${RUNS}); do \ - exec 3>&1 4>&2 - OUT=$( { helm template --include-crds --name-template $* 2>&4 | oc apply -f- 2>&4 1>&3; } 4>&1 3>&1) - ret=$? - exec 3>&- 4>&- - if [ ${ret} -eq 0 ]; then - break; - else - echo -n "." - sleep "${WAIT}" - fi -done - -# All the runs failed -if [ ${i} -eq ${RUNS} ]; then - echo "Installation failed [${i}/${RUNS}]. Error:" - echo "${OUT}" - exit 1 -fi -echo "Done" diff --git a/tmp/acm-hub-bootstrap/common/scripts/determine-main-clustergroup.sh b/tmp/acm-hub-bootstrap/common/scripts/determine-main-clustergroup.sh deleted file mode 100755 index 6271dba..0000000 --- a/tmp/acm-hub-bootstrap/common/scripts/determine-main-clustergroup.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -PATTERN_DIR="$1" - -if [ -z "$PATTERN_DIR" ]; then - PATTERN_DIR="." -fi - -CGNAME=$(yq '.main.clusterGroupName' "$PATTERN_DIR/values-global.yaml") - -if [ -z "$CGNAME" ] || [ "$CGNAME" == "null" ]; then - echo "Error - cannot detrmine clusterGroupName" - exit 1 -fi - -echo "$CGNAME" diff --git a/tmp/acm-hub-bootstrap/common/scripts/determine-pattern-name.sh b/tmp/acm-hub-bootstrap/common/scripts/determine-pattern-name.sh deleted file mode 100755 index fb503fe..0000000 --- a/tmp/acm-hub-bootstrap/common/scripts/determine-pattern-name.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -PATTERN_DIR="$1" - -if [ -z "$PATTERN_DIR" ]; then - PATTERN_DIR="." -fi - -PATNAME=$(yq '.global.pattern' "$PATTERN_DIR/values-global.yaml" 2>/dev/null) - -if [ -z "$PATNAME" ] || [ "$PATNAME" == "null" ]; then - PATNAME="$(basename "$PWD")" -fi - -echo "$PATNAME" diff --git a/tmp/acm-hub-bootstrap/common/scripts/determine-secretstore-backend.sh b/tmp/acm-hub-bootstrap/common/scripts/determine-secretstore-backend.sh deleted file mode 100755 index ef78479..0000000 --- a/tmp/acm-hub-bootstrap/common/scripts/determine-secretstore-backend.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -PATTERN_DIR="$1" - -if [ -z "$PATTERN_DIR" ]; then - PATTERN_DIR="." -fi - -BACKEND=$(yq '.global.secretStore.backend' "$PATTERN_DIR/values-global.yaml" 2>/dev/null) - -if [ -z "$BACKEND" -o "$BACKEND" == "null" ]; then - BACKEND="vault" -fi - -echo "$BACKEND" diff --git a/tmp/acm-hub-bootstrap/common/scripts/display-secrets-info.sh b/tmp/acm-hub-bootstrap/common/scripts/display-secrets-info.sh deleted file mode 100755 index ca0069e..0000000 --- a/tmp/acm-hub-bootstrap/common/scripts/display-secrets-info.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env bash -set -eu - -get_abs_filename() { - # $1 : relative filename - echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")" -} - -SCRIPT=$(get_abs_filename "$0") -SCRIPTPATH=$(dirname "${SCRIPT}") -COMMONPATH=$(dirname "${SCRIPTPATH}") -PATTERNPATH=$(dirname "${COMMONPATH}") - -if [ "$#" -ge 1 ]; then - export VALUES_SECRET=$(get_abs_filename "${1}") -fi - -if [[ "$#" == 2 ]]; then - SECRETS_BACKING_STORE="$2" -else - SECRETS_BACKING_STORE="$($SCRIPTPATH/determine-secretstore-backend.sh)" -fi - -PATTERN_NAME=$(basename "`pwd`") - -EXTRA_PLAYBOOK_OPTS="${EXTRA_PLAYBOOK_OPTS:-}" - -ansible-playbook -e pattern_name="${PATTERN_NAME}" -e pattern_dir="${PATTERNPATH}" -e secrets_backing_store="${SECRETS_BACKING_STORE}" -e hide_sensitive_output=false ${EXTRA_PLAYBOOK_OPTS} "rhvp.cluster_utils.display_secrets_info" diff --git a/tmp/acm-hub-bootstrap/common/scripts/load-k8s-secrets.sh b/tmp/acm-hub-bootstrap/common/scripts/load-k8s-secrets.sh deleted file mode 100755 index 707e51a..0000000 --- a/tmp/acm-hub-bootstrap/common/scripts/load-k8s-secrets.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env bash -set -eu - -get_abs_filename() { - # $1 : relative filename - echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")" -} - -SCRIPT=$(get_abs_filename "$0") -SCRIPTPATH=$(dirname "${SCRIPT}") -COMMONPATH=$(dirname "${SCRIPTPATH}") -PATTERNPATH=$(dirname "${COMMONPATH}") - -PATTERN_NAME=${1:-$(basename "`pwd`")} - -EXTRA_PLAYBOOK_OPTS="${EXTRA_PLAYBOOK_OPTS:-}" - -ansible-playbook -e pattern_name="${PATTERN_NAME}" -e pattern_dir="${PATTERNPATH}" ${EXTRA_PLAYBOOK_OPTS} "rhvp.cluster_utils.k8s_secrets" diff --git a/tmp/acm-hub-bootstrap/common/scripts/make-common-subtree.sh b/tmp/acm-hub-bootstrap/common/scripts/make-common-subtree.sh deleted file mode 100755 index 196a4c8..0000000 --- a/tmp/acm-hub-bootstrap/common/scripts/make-common-subtree.sh +++ /dev/null @@ -1,76 +0,0 @@ -#!/bin/sh - -if [ "$1" = "-h" ]; then - echo "This script will convert common into a subtree and add a remote to help manage it." - echo "The script takes three positional arguments, as follows:" - echo - echo "$0 " - echo - echo "Run without arguments, the script would run as if these arguments had been passed:" - echo "$0 https://github.com/validatedpatterns/common.git main common-upstream" - echo - echo "Please ensure the git subtree command is available. On RHEL/Fedora, the git subtree command" - echo "is in a separate package called git-subtree" - exit 1 -fi - -if [ -f '/etc/redhat-release' ]; then - rpm -qa | grep git-subtree 2>&1 - if [ ! $? = 0 ]; then - echo "you need to install git-subtree" - echo "would you like to install it now?" - select ANS in yes no - do - case $ANS in - yes) - sudo dnf install git-subtree -y - break - ;; - no) - exit - break - ;; - *) - echo "You must enter yes or no" - ;; - esac - done - fi -fi - -if [ "$1" ]; then - subtree_repo=$1 -else - subtree_repo=https://github.com/validatedpatterns/common.git -fi - -if [ "$2" ]; then - subtree_branch=$2 -else - subtree_branch=main -fi - -if [ "$3" ]; then - subtree_remote=$3 -else - subtree_remote=common-upstream -fi - -git diff --quiet || (echo "This script must be run on a clean working tree" && exit 1) - -echo "Changing directory to project root" -cd `git rev-parse --show-toplevel` - -echo "Removing existing common and replacing it with subtree from $subtree_repo $subtree_remote" -rm -rf common - -echo "Committing removal of common" -(git add -A :/ && git commit -m "Removed previous version of common to convert to subtree from $subtree_repo $subtree_branch") || exit 1 - -echo "Adding (possibly replacing) subtree remote $subtree_remote" -git remote rm "$subtree_remote" -git remote add -f "$subtree_remote" "$subtree_repo" || exit 1 -git subtree add --prefix=common "$subtree_remote" "$subtree_branch" || exit 1 - -echo "Complete. You may now push these results if you are satisfied" -exit 0 diff --git a/tmp/acm-hub-bootstrap/common/scripts/manage-secret-app.sh b/tmp/acm-hub-bootstrap/common/scripts/manage-secret-app.sh deleted file mode 100755 index 18a986e..0000000 --- a/tmp/acm-hub-bootstrap/common/scripts/manage-secret-app.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/sh - -APP=$1 -STATE=$2 - -MAIN_CLUSTERGROUP_FILE="./values-$(common/scripts/determine-main-clustergroup.sh).yaml" -MAIN_CLUSTERGROUP_PROJECT="$(common/scripts/determine-main-clustergroup.sh)" - -case "$APP" in - "vault") - APP_NAME="vault" - NAMESPACE="vault" - PROJECT="$MAIN_CLUSTERGROUP_PROJECT" - CHART_NAME="hashicorp-vault" - CHART_VERSION=0.1.* - - ;; - "golang-external-secrets") - APP_NAME="golang-external-secrets" - NAMESPACE="golang-external-secrets" - PROJECT="$MAIN_CLUSTERGROUP_PROJECT" - CHART_NAME="golang-external-secrets" - CHART_VERSION=0.1.* - - ;; - *) - echo "Error - cannot manage $APP can only manage vault and golang-external-secrets" - exit 1 - ;; -esac - -case "$STATE" in - "present") - common/scripts/manage-secret-namespace.sh "$NAMESPACE" "$STATE" - - RES=$(yq ".clusterGroup.applications[] | select(.path == \"$CHART_LOCATION\")" "$MAIN_CLUSTERGROUP_FILE" 2>/dev/null) - if [ -z "$RES" ]; then - echo "Application with chart location $CHART_LOCATION not found, adding" - yq -i ".clusterGroup.applications.$APP_NAME = { \"name\": \"$APP_NAME\", \"namespace\": \"$NAMESPACE\", \"project\": \"$PROJECT\", \"chart\": \"$CHART_NAME\", \"chartVersion\": \"$CHART_VERSION\"}" "$MAIN_CLUSTERGROUP_FILE" - fi - ;; - "absent") - common/scripts/manage-secret-namespace.sh "$NAMESPACE" "$STATE" - echo "Removing application wth chart location $CHART_LOCATION" - yq -i "del(.clusterGroup.applications[] | select(.chart == \"$CHART_NAME\"))" "$MAIN_CLUSTERGROUP_FILE" - ;; - *) - echo "$STATE not supported" - exit 1 - ;; -esac - -exit 0 diff --git a/tmp/acm-hub-bootstrap/common/scripts/manage-secret-namespace.sh b/tmp/acm-hub-bootstrap/common/scripts/manage-secret-namespace.sh deleted file mode 100755 index bcb0674..0000000 --- a/tmp/acm-hub-bootstrap/common/scripts/manage-secret-namespace.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh - -NAMESPACE=$1 -STATE=$2 - -MAIN_CLUSTERGROUP_FILE="./values-$(common/scripts/determine-main-clustergroup.sh).yaml" -MAIN_CLUSTERGROUP_PROJECT="$(common/scripts/determine-main-clustergroup.sh)" - -case "$STATE" in - "present") - - RES=$(yq ".clusterGroup.namespaces[] | select(. == \"$NAMESPACE\")" "$MAIN_CLUSTERGROUP_FILE" 2>/dev/null) - if [ -z "$RES" ]; then - echo "Namespace $NAMESPACE not found, adding" - yq -i ".clusterGroup.namespaces += [ \"$NAMESPACE\" ]" "$MAIN_CLUSTERGROUP_FILE" - fi - ;; - "absent") - echo "Removing namespace $NAMESPACE" - yq -i "del(.clusterGroup.namespaces[] | select(. == \"$NAMESPACE\"))" "$MAIN_CLUSTERGROUP_FILE" - ;; - *) - echo "$STATE not supported" - exit 1 - ;; -esac - -exit 0 diff --git a/tmp/acm-hub-bootstrap/common/scripts/pattern-util.sh b/tmp/acm-hub-bootstrap/common/scripts/pattern-util.sh deleted file mode 100755 index 8258d46..0000000 --- a/tmp/acm-hub-bootstrap/common/scripts/pattern-util.sh +++ /dev/null @@ -1,112 +0,0 @@ -#!/bin/bash - -function is_available { - command -v $1 >/dev/null 2>&1 || { echo >&2 "$1 is required but it's not installed. Aborting."; exit 1; } -} - -function version { - echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }' -} - -if [ -z "$PATTERN_UTILITY_CONTAINER" ]; then - PATTERN_UTILITY_CONTAINER="quay.io/hybridcloudpatterns/utility-container" -fi -# If PATTERN_DISCONNECTED_HOME is set it will be used to populate both PATTERN_UTILITY_CONTAINER -# and PATTERN_INSTALL_CHART automatically -if [ -n "${PATTERN_DISCONNECTED_HOME}" ]; then - PATTERN_UTILITY_CONTAINER="${PATTERN_DISCONNECTED_HOME}/utility-container" - PATTERN_INSTALL_CHART="oci://${PATTERN_DISCONNECTED_HOME}/pattern-install" - echo "PATTERN_DISCONNECTED_HOME is set to ${PATTERN_DISCONNECTED_HOME}" - echo "Setting the following variables:" - echo " PATTERN_UTILITY_CONTAINER: ${PATTERN_UTILITY_CONTAINER}" - echo " PATTERN_INSTALL_CHART: ${PATTERN_INSTALL_CHART}" -fi - -readonly commands=(podman) -for cmd in ${commands[@]}; do is_available "$cmd"; done - -UNSUPPORTED_PODMAN_VERSIONS="1.6 1.5" -PODMAN_VERSION_STR=$(podman --version) -for i in ${UNSUPPORTED_PODMAN_VERSIONS}; do - # We add a space - if echo "${PODMAN_VERSION_STR}" | grep -q -E "\b${i}"; then - echo "Unsupported podman version. We recommend > 4.3.0" - podman --version - exit 1 - fi -done - -# podman --version outputs: -# podman version 4.8.2 -PODMAN_VERSION=$(echo "${PODMAN_VERSION_STR}" | awk '{ print $NF }') - -# podman < 4.3.0 do not support keep-id:uid=... -if [ $(version "${PODMAN_VERSION}") -lt $(version "4.3.0") ]; then - PODMAN_ARGS="-v ${HOME}:/root" -else - # We do not rely on bash's $UID and $GID because on MacOSX $GID is not set - MYNAME=$(id -n -u) - MYUID=$(id -u) - MYGID=$(id -g) - PODMAN_ARGS="--passwd-entry ${MYNAME}:x:${MYUID}:${MYGID}::/pattern-home:/bin/bash --user ${MYUID}:${MYGID} --userns keep-id:uid=${MYUID},gid=${MYGID}" - -fi - -if [ -n "$KUBECONFIG" ]; then - if [[ ! "${KUBECONFIG}" =~ ^$HOME* ]]; then - echo "${KUBECONFIG} is pointing outside of the HOME folder, this will make it unavailable from the container." - echo "Please move it somewhere inside your $HOME folder, as that is what gets bind-mounted inside the container" - exit 1 - fi -fi - -# Detect if we use podman machine. If we do not then we bind mount local host ssl folders -# if we are using podman machine then we do not bind mount anything (for now!) -REMOTE_PODMAN=$(podman system connection list -q | wc -l) -if [ $REMOTE_PODMAN -eq 0 ]; then # If we are not using podman machine we check the hosts folders - # We check /etc/pki/tls because on ubuntu /etc/pki/fwupd sometimes - # exists but not /etc/pki/tls and we do not want to bind mount in such a case - # as it would find no certificates at all. - if [ -d /etc/pki/tls ]; then - PKI_HOST_MOUNT_ARGS="-v /etc/pki:/etc/pki:ro" - elif [ -d /etc/ssl ]; then - PKI_HOST_MOUNT_ARGS="-v /etc/ssl:/etc/ssl:ro" - else - PKI_HOST_MOUNT_ARGS="-v /usr/share/ca-certificates:/usr/share/ca-certificates:ro" - fi -else - PKI_HOST_MOUNT_ARGS="" -fi - -# Copy Kubeconfig from current environment. The utilities will pick up ~/.kube/config if set so it's not mandatory -# $HOME is mounted as itself for any files that are referenced with absolute paths -# $HOME is mounted to /root because the UID in the container is 0 and that's where SSH looks for credentials - -podman run -it --rm --pull=newer \ - --security-opt label=disable \ - -e EXTRA_HELM_OPTS \ - -e EXTRA_PLAYBOOK_OPTS \ - -e TARGET_ORIGIN \ - -e TARGET_SITE \ - -e TARGET_BRANCH \ - -e NAME \ - -e TOKEN_SECRET \ - -e TOKEN_NAMESPACE \ - -e VALUES_SECRET \ - -e KUBECONFIG \ - -e PATTERN_INSTALL_CHART \ - -e PATTERN_DISCONNECTED_HOME \ - -e K8S_AUTH_HOST \ - -e K8S_AUTH_VERIFY_SSL \ - -e K8S_AUTH_SSL_CA_CERT \ - -e K8S_AUTH_USERNAME \ - -e K8S_AUTH_PASSWORD \ - -e K8S_AUTH_TOKEN \ - ${PKI_HOST_MOUNT_ARGS} \ - -v "${HOME}":"${HOME}" \ - -v "${HOME}":/pattern-home \ - ${PODMAN_ARGS} \ - ${EXTRA_ARGS} \ - -w "$(pwd)" \ - "$PATTERN_UTILITY_CONTAINER" \ - $@ diff --git a/tmp/acm-hub-bootstrap/common/scripts/preview-all.sh b/tmp/acm-hub-bootstrap/common/scripts/preview-all.sh deleted file mode 100755 index 4bf5932..0000000 --- a/tmp/acm-hub-bootstrap/common/scripts/preview-all.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -REPO=$1; shift; -TARGET_BRANCH=$1; shift - -HUB=$( yq ".main.clusterGroupName" values-global.yaml ) -MANAGED_CLUSTERS=$( yq ".clusterGroup.managedClusterGroups.[].name" values-$HUB.yaml ) -ALL_CLUSTERS=( $HUB $MANAGED_CLUSTERS ) - -CLUSTER_INFO_OUT=$(oc cluster-info 2>&1) -CLUSTER_INFO_RET=$? -if [ $CLUSTER_INFO_RET -ne 0 ]; then - echo "Could not access the cluster:" - echo "${CLUSTER_INFO_OUT}" - exit 1 -fi - -for cluster in ${ALL_CLUSTERS[@]}; do - # We always add clustergroup as it is the entry point and it gets special cased in preview.sh. - APPS="clustergroup $( yq ".clusterGroup.applications.[].name" values-$cluster.yaml )" - for app in $APPS; do - printf "# Parsing application $app from cluster $cluster\n" - common/scripts/preview.sh $cluster $app $REPO $TARGET_BRANCH - done -done diff --git a/tmp/acm-hub-bootstrap/common/scripts/preview.sh b/tmp/acm-hub-bootstrap/common/scripts/preview.sh deleted file mode 100755 index 6da4578..0000000 --- a/tmp/acm-hub-bootstrap/common/scripts/preview.sh +++ /dev/null @@ -1,118 +0,0 @@ -#!/bin/bash - -# DISCLAIMER -# -# - Parsing of applications needs to be more clever. -# - There is currently not a mechanism to actually preview against multiple clusters -# (i.e. a hub and a remote). All previews will be done against the current. -# - Make output can be included in the YAML. - -SITE=$1; shift -APPNAME=$1; shift -GIT_REPO=$1; shift -GIT_BRANCH=$1; shift - -if [ "${APPNAME}" != "clustergroup" ]; then - # This covers the following case: - # foobar: - # name: foo - # namespace: foo - # project: foo - # path: charts/all/foo - # So we retrieve the actual index ("foobar") given the name attribute of the application - APP=$(yq ".clusterGroup.applications | with_entries(select(.value.name == \"$APPNAME\")) | keys | .[0]" values-$SITE.yaml) - isLocalHelmChart=$(yq ".clusterGroup.applications.$APP.path" values-$SITE.yaml) - if [ $isLocalHelmChart != "null" ]; then - chart=$(yq ".clusterGroup.applications.$APP.path" values-$SITE.yaml) - else - helmrepo=$(yq ".clusterGroup.applications.$APP.repoURL" values-$SITE.yaml) - helmrepo="${helmrepo:+oci://quay.io/hybridcloudpatterns}" - chartversion=$(yq ".clusterGroup.applications.$APP.chartVersion" values-$SITE.yaml) - chartname=$(yq ".clusterGroup.applications.$APP.chart" values-$SITE.yaml) - chart="${helmrepo}/${chartname} --version ${chartversion}" - fi - namespace=$(yq ".clusterGroup.applications.$APP.namespace" values-$SITE.yaml) -else - APP=$APPNAME - clusterGroupChartVersion=$(yq ".main.multiSourceConfig.clusterGroupChartVersion" values-global.yaml) - helmrepo="oci://quay.io/hybridcloudpatterns" - chart="${helmrepo}/clustergroup --version ${clusterGroupChartVersion}" - namespace="openshift-operators" -fi -pattern=$(yq ".global.pattern" values-global.yaml) - -# You can override the default lookups by using OCP_{PLATFORM,VERSION,DOMAIN} -# Note that when using the utility container you need to pass in the above variables -# by export EXTRA_ARGS="-e OCP_PLATFORM -e OCP_VERSION -e OCP_DOMAIN" before -# invoking pattern-util.sh -platform=${OCP_PLATFORM:-$(oc get Infrastructure.config.openshift.io/cluster -o jsonpath='{.spec.platformSpec.type}')} -ocpversion=${OCP_VERSION:-$(oc get clusterversion/version -o jsonpath='{.status.desired.version}' | awk -F. '{print $1"."$2}')} -domain=${OCP_DOMAIN:-$(oc get Ingress.config.openshift.io/cluster -o jsonpath='{.spec.domain}' | sed 's/^apps.//')} - -function replaceGlobals() { - output=$( echo $1 | sed -e 's/ //g' -e 's/\$//g' -e s@^-@@g -e s@\'@@g ) - - output=$(echo $output | sed "s@{{.Values.global.clusterPlatform}}@${platform}@g") - output=$(echo $output | sed "s@{{.Values.global.clusterVersion}}@${ocpversion}@g") - output=$(echo $output | sed "s@{{.Values.global.clusterDomain}}@${domain}@g") - - echo $output -} - -function getOverrides() { - overrides='' - overrides=$( yq ".clusterGroup.applications.$APP.overrides[]" "values-$SITE.yaml" ) - overrides=$( echo "$overrides" | tr -d '\n' ) - overrides=$( echo "$overrides" | sed -e 's/name:/ --set/g; s/value: /=/g' ) - if [ -n "$overrides" ]; then - echo "$overrides" - fi -} - - -CLUSTER_OPTS="" -CLUSTER_OPTS="$CLUSTER_OPTS --set global.pattern=$pattern" -CLUSTER_OPTS="$CLUSTER_OPTS --set global.repoURL=$GIT_REPO" -CLUSTER_OPTS="$CLUSTER_OPTS --set main.git.repoURL=$GIT_REPO" -CLUSTER_OPTS="$CLUSTER_OPTS --set main.git.revision=$GIT_BRANCH" -CLUSTER_OPTS="$CLUSTER_OPTS --set global.namespace=$namespace" -CLUSTER_OPTS="$CLUSTER_OPTS --set global.hubClusterDomain=apps.$domain" -CLUSTER_OPTS="$CLUSTER_OPTS --set global.localClusterDomain=apps.$domain" -CLUSTER_OPTS="$CLUSTER_OPTS --set global.clusterDomain=$domain" -CLUSTER_OPTS="$CLUSTER_OPTS --set global.clusterVersion=$ocpversion" -CLUSTER_OPTS="$CLUSTER_OPTS --set global.clusterPlatform=$platform" - - -sharedValueFiles=$(yq ".clusterGroup.sharedValueFiles" values-$SITE.yaml) -appValueFiles=$(yq ".clusterGroup.applications.$APP.extraValueFiles" values-$SITE.yaml) -isKustomize=$(yq ".clusterGroup.applications.$APP.kustomize" values-$SITE.yaml) -OVERRIDES=$( getOverrides ) - -VALUE_FILES="-f values-global.yaml -f values-$SITE.yaml" -IFS=$'\n' -for line in $sharedValueFiles; do - if [ $line != "null" ] && [ -f $line ]; then - file=$(replaceGlobals $line) - VALUE_FILES="$VALUE_FILES -f $PWD$file" - fi -done - -for line in $appValueFiles; do - if [ $line != "null" ] && [ -f $line ]; then - file=$(replaceGlobals $line) - VALUE_FILES="$VALUE_FILES -f $PWD$file" - fi -done - -if [ $isKustomize == "true" ]; then - kustomizePath=$(yq ".clusterGroup.applications.$APP.path" values-$SITE.yaml) - repoURL=$(yq ".clusterGroup.applications.$APP.repoURL" values-$SITE.yaml) - if [[ $repoURL == http* ]] || [[ $repoURL == git@ ]]; then - kustomizePath="${repoURL}/${kustomizePath}" - fi - cmd="oc kustomize ${kustomizePath}" - eval "$cmd" -else - cmd="helm template $chart --name-template ${APP} -n ${namespace} ${VALUE_FILES} ${OVERRIDES} ${CLUSTER_OPTS}" - eval "$cmd" -fi diff --git a/tmp/acm-hub-bootstrap/common/scripts/process-secrets.sh b/tmp/acm-hub-bootstrap/common/scripts/process-secrets.sh deleted file mode 100755 index a0d34f8..0000000 --- a/tmp/acm-hub-bootstrap/common/scripts/process-secrets.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env bash -set -eu - -get_abs_filename() { - # $1 : relative filename - echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")" -} - -SCRIPT=$(get_abs_filename "$0") -SCRIPTPATH=$(dirname "${SCRIPT}") -COMMONPATH=$(dirname "${SCRIPTPATH}") -PATTERNPATH=$(dirname "${COMMONPATH}") - -PATTERN_NAME=${1:-$(basename "`pwd`")} -SECRETS_BACKING_STORE="$($SCRIPTPATH/determine-secretstore-backend.sh)" - -EXTRA_PLAYBOOK_OPTS="${EXTRA_PLAYBOOK_OPTS:-}" - -ansible-playbook -e pattern_name="${PATTERN_NAME}" -e pattern_dir="${PATTERNPATH}" -e secrets_backing_store="${SECRETS_BACKING_STORE}" ${EXTRA_PLAYBOOK_OPTS} "rhvp.cluster_utils.process_secrets" diff --git a/tmp/acm-hub-bootstrap/common/scripts/set-secret-backend.sh b/tmp/acm-hub-bootstrap/common/scripts/set-secret-backend.sh deleted file mode 100755 index e07b15b..0000000 --- a/tmp/acm-hub-bootstrap/common/scripts/set-secret-backend.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -BACKEND=$1 - -yq -i ".global.secretStore.backend = \"$BACKEND\"" values-global.yaml diff --git a/tmp/acm-hub-bootstrap/common/scripts/vault-utils.sh b/tmp/acm-hub-bootstrap/common/scripts/vault-utils.sh deleted file mode 100755 index 2f76649..0000000 --- a/tmp/acm-hub-bootstrap/common/scripts/vault-utils.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash -set -eu - -get_abs_filename() { - # $1 : relative filename - echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")" -} - -SCRIPT=$(get_abs_filename "$0") -SCRIPTPATH=$(dirname "${SCRIPT}") -COMMONPATH=$(dirname "${SCRIPTPATH}") -PATTERNPATH=$(dirname "${COMMONPATH}") - -# Parse arguments -if [ $# -lt 1 ]; then - echo "Specify at least the command ($#): $*" - exit 1 -fi - -TASK="${1}" -PATTERN_NAME=${2:-$(basename "`pwd`")} - -if [ -z ${TASK} ]; then - echo "Task is unset" - exit 1 -fi - -EXTRA_PLAYBOOK_OPTS="${EXTRA_PLAYBOOK_OPTS:-}" - -ansible-playbook -t "${TASK}" -e pattern_name="${PATTERN_NAME}" -e pattern_dir="${PATTERNPATH}" ${EXTRA_PLAYBOOK_OPTS} "rhvp.cluster_utils.vault" diff --git a/tmp/acm-hub-bootstrap/common/scripts/write-token-kubeconfig.sh b/tmp/acm-hub-bootstrap/common/scripts/write-token-kubeconfig.sh deleted file mode 100755 index e7913e5..0000000 --- a/tmp/acm-hub-bootstrap/common/scripts/write-token-kubeconfig.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env bash -set -eu - -OUTPUTFILE=${1:-"~/.kube/config"} - -get_abs_filename() { - # $1 : relative filename - echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")" -} - -SCRIPT=$(get_abs_filename "$0") -SCRIPTPATH=$(dirname "${SCRIPT}") -COMMONPATH=$(dirname "${SCRIPTPATH}") -PATTERNPATH=$(dirname "${COMMONPATH}") - -EXTRA_PLAYBOOK_OPTS="${EXTRA_PLAYBOOK_OPTS:-}" - -ansible-playbook -e pattern_dir="${PATTERNPATH}" -e kubeconfig_file="${OUTPUTFILE}" ${EXTRA_PLAYBOOK_OPTS} "rhvp.cluster_utils.write-token-kubeconfig" diff --git a/tmp/acm-hub-bootstrap/overrides/values-AWS.yaml b/tmp/acm-hub-bootstrap/overrides/values-AWS.yaml deleted file mode 100644 index 03fa077..0000000 --- a/tmp/acm-hub-bootstrap/overrides/values-AWS.yaml +++ /dev/null @@ -1,26 +0,0 @@ -# The following snippet can be commented out in oroder -# to enable letsencrypt certificates on API endpoint and default -# ingress of the cluster -# It is currently very experimental and unsupported. -# PLEASE read https://github.com/hybrid-cloud-patterns/common/tree/main/letsencrypt#readme -# for all the limitations around it - - -# letsencrypt: -# enabled: true -# api_endpoint: true -# # FIXME: tweak this to match your region -# region: eu-central-1 -# server: https://acme-v02.api.letsencrypt.org/directory -# # server: https://acme-staging-v02.api.letsencrypt.org/directory -# # FIXME: set this to your correct email -# email: iwashere@iwashere.com -# -# clusterGroup: -# applications: -# letsencrypt: -# name: letsencrypt -# namespace: letsencrypt -# # Using 'default' as that exists everywhere -# project: default -# path: common/letsencrypt diff --git a/tmp/acm-hub-bootstrap/overrides/values-IBMCloud.yaml b/tmp/acm-hub-bootstrap/overrides/values-IBMCloud.yaml deleted file mode 100644 index 38d7be7..0000000 --- a/tmp/acm-hub-bootstrap/overrides/values-IBMCloud.yaml +++ /dev/null @@ -1,10 +0,0 @@ -# When using IBM ROKS the route certificates are signed by letsencrypt -# By default the ESO configuration uses the kube-root-ca.crt configmap -# to validate the connection to vault. Since this configmap will not contain -# the letsencrypt CA, ESO will be unable to connect to the vault and return an -# x509 CA unknown error. -# Uncomment the following if you are using IBM ROKS (IPI installs on IBM Cloud are unaffected) - -# golangExternalSecrets: -# caProvider: -# enabled: false diff --git a/tmp/acm-hub-bootstrap/pattern-metadata.yaml b/tmp/acm-hub-bootstrap/pattern-metadata.yaml deleted file mode 100644 index fdb3a0d..0000000 --- a/tmp/acm-hub-bootstrap/pattern-metadata.yaml +++ /dev/null @@ -1,70 +0,0 @@ -# This goal of this metadata is mainly used as a source of truth for -# documentation and qe -metadata_version: "1.0" -name: multicloud-gitops -pattern_version: "1.0" -display_name: Multicloud Gitops -repo_url: https://github.com/validatedpatterns/multicloud-gitops -docs_repo_url: https://github.com/validatedpatterns/docs -issues_url: https://github.com/validatedpatterns/multicloud-gitops/issues -docs_url: https://validatedpatterns.io/patterns/multicloud-gitops/ -ci_url: https://validatedpatterns.io/ci/?pattern=mcgitops -# can be sandbox, tested or maintained -tier: maintained -owners: mbaldessari, darkdoc -requirements: - hub: # Main cluster - compute: - platform: - gcp: - replicas: 3 - type: n1-standard-8 - azure: - replicas: 3 - type: Standard_D8s_v3 - aws: - replicas: 3 - type: m5.2xlarge - controlPlane: - platform: - gcp: - replicas: 3 - type: n1-standard-4 - azure: - replicas: 3 - type: Standard_D4s_v3 - aws: - replicas: 3 - type: m5.xlarge - spoke: # optional - represents the clusters imported into ACM - compute: - platform: - gcp: - replicas: 0 - type: n1-standard-8 - azure: - replicas: 0 - type: Standard_D8s_v3 - aws: - replicas: 0 - type: m5.2xlarge - controlPlane: - platform: - gcp: - replicas: 3 - type: n1-standard-8 - azure: - replicas: 3 - type: Standard_D8s_v3 - aws: - replicas: 3 - type: m5.2xlarge - -# Loosely defined extra features like hypershift support, non-openshift -# kubernetes support, spoke support -extra_features: - hypershift_support: true - spoke_support: true - -external_requirements: -# external quay, s3 bucket, agof tokens to access paywalled material, manifests, rag-llm hw (only selected regions) diff --git a/tmp/acm-hub-bootstrap/pattern.sh b/tmp/acm-hub-bootstrap/pattern.sh deleted file mode 120000 index 223a550..0000000 --- a/tmp/acm-hub-bootstrap/pattern.sh +++ /dev/null @@ -1 +0,0 @@ -./common/scripts/pattern-util.sh \ No newline at end of file diff --git a/tmp/acm-hub-bootstrap/tests/interop/README.md b/tmp/acm-hub-bootstrap/tests/interop/README.md deleted file mode 100644 index 54560a1..0000000 --- a/tmp/acm-hub-bootstrap/tests/interop/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# Running tests - -## Prerequisites - -* Openshift clusters with multicloud-gitops pattern installed - * factory cluster is managed via rhacm -* kubeconfig files for Openshift clusters -* oc client installed at ~/oc_client/oc - -## Steps - -* create python3 venv, clone multicloud-gitops repository -* export KUBECONFIG=\ -* export KUBECONFIG_EDGE=\ -* export INFRA_PROVIDER=\ -* (optional) export WORKSPACE=\ (defaults to /tmp) -* cd multicloud-gitops/tests/interop -* pip install -r requirements.txt -* ./run_tests.sh - -## Results - -* results .xml files will be placed at $WORKSPACE -* test logs will be placed at $WORKSPACE/.results/test_execution_logs/ -* CI badge file will be placed at $WORKSPACE diff --git a/tmp/acm-hub-bootstrap/tests/interop/__init__.py b/tmp/acm-hub-bootstrap/tests/interop/__init__.py deleted file mode 100644 index 890362c..0000000 --- a/tmp/acm-hub-bootstrap/tests/interop/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -__version__ = "0.1.0" -__loggername__ = "css_logger" diff --git a/tmp/acm-hub-bootstrap/tests/interop/conftest.py b/tmp/acm-hub-bootstrap/tests/interop/conftest.py deleted file mode 100644 index fb301d5..0000000 --- a/tmp/acm-hub-bootstrap/tests/interop/conftest.py +++ /dev/null @@ -1,2 +0,0 @@ -from validatedpatterns_tests.interop.conftest_logger import * # noqa: F401, F403 -from validatedpatterns_tests.interop.conftest_openshift import * # noqa: F401, F403 diff --git a/tmp/acm-hub-bootstrap/tests/interop/create_ci_badge.py b/tmp/acm-hub-bootstrap/tests/interop/create_ci_badge.py deleted file mode 100644 index 8ed179a..0000000 --- a/tmp/acm-hub-bootstrap/tests/interop/create_ci_badge.py +++ /dev/null @@ -1,84 +0,0 @@ -import json -import os -import subprocess -from datetime import datetime - -from junitparser import JUnitXml - -oc = os.environ["HOME"] + "/oc_client/oc" - -ci_badge = { - "schemaVersion": 1, - "label": "Community test", - "message": "", - "color": "red", - "openshiftVersion": "", - "infraProvider": os.environ.get("INFRA_PROVIDER"), - "patternName": os.environ.get("PATTERN_NAME"), - "patternRepo": "", - "patternBranch": "", - "date": datetime.today().strftime("%Y-%m-%d"), - "testSource": "Community", - "debugInfo": None, -} - - -def get_openshift_version(): - try: - version_ret = subprocess.run([oc, "version", "-o", "json"], capture_output=True) - version_out = version_ret.stdout.decode("utf-8") - openshift_version = json.loads(version_out)["openshiftVersion"] - major_minor = ".".join(openshift_version.split(".")[:-1]) - return openshift_version, major_minor - except KeyError as e: - print("KeyError:" + str(e)) - return None - - -if __name__ == "__main__": - versions = get_openshift_version() - ci_badge["openshiftVersion"] = versions[0] - - pattern_repo = subprocess.run( - ["git", "config", "--get", "remote.origin.url"], capture_output=True, text=True - ) - pattern_branch = subprocess.run( - ["git", "branch", "--show-current"], capture_output=True, text=True - ) - - ci_badge["patternRepo"] = pattern_repo.stdout.strip() - ci_badge["patternBranch"] = pattern_branch.stdout.strip() - - # Check each xml file for failures - results_dir = os.environ.get("WORKSPACE") - failures = 0 - - for file in os.listdir(results_dir): - if file.startswith("test_") and file.endswith(".xml"): - with open(os.path.join(results_dir, file), "r") as result_file: # type: ignore - xml = JUnitXml.fromfile(result_file) # type: ignore - for suite in xml: - for case in suite: - if case.result: - failures += 1 - - # Determine badge color from results - if failures == 0: - ci_badge["color"] = "green" - - # For now we assume `message` is the same as patternBranch - ci_badge["message"] = ci_badge["patternBranch"] - - ci_badge_json_basename = ( - os.environ.get("PATTERN_SHORTNAME") # type: ignore - + "-" - + os.environ.get("INFRA_PROVIDER") - + "-" - + versions[1] - + "-stable-badge.json" - ) - ci_badge_json_filename = os.path.join(results_dir, ci_badge_json_basename) # type: ignore - print(f"Creating CI badge file at: {ci_badge_json_filename}") - - with open(ci_badge_json_filename, "w") as ci_badge_file: - json.dump(ci_badge, ci_badge_file) diff --git a/tmp/acm-hub-bootstrap/tests/interop/requirements.txt b/tmp/acm-hub-bootstrap/tests/interop/requirements.txt deleted file mode 100644 index 3b20852..0000000 --- a/tmp/acm-hub-bootstrap/tests/interop/requirements.txt +++ /dev/null @@ -1,6 +0,0 @@ -pytest -kubernetes -openshift -openshift-python-wrapper -junitparser -git+https://github.com/validatedpatterns/vp-qe-test-common.git@development#egg=vp-qe-test-common \ No newline at end of file diff --git a/tmp/acm-hub-bootstrap/tests/interop/run_tests.sh b/tmp/acm-hub-bootstrap/tests/interop/run_tests.sh deleted file mode 100755 index a1af3b4..0000000 --- a/tmp/acm-hub-bootstrap/tests/interop/run_tests.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/bash - -export EXTERNAL_TEST="true" -export PATTERN_NAME="MultiCloudGitops" -export PATTERN_SHORTNAME="mcgitops" - -if [ -z "${KUBECONFIG}" ]; then - echo "No kubeconfig file set for hub cluster" - exit 1 -fi - -if [ -z "${KUBECONFIG_EDGE}" ]; then - echo "No kubeconfig file set for edge cluster" - exit 1 -fi - -if [ -z "${INFRA_PROVIDER}" ]; then - echo "INFRA_PROVIDER is not defined" - exit 1 -fi - -if [ -z "${WORKSPACE}" ]; then - export WORKSPACE=/tmp -fi - -pytest -lv --disable-warnings test_subscription_status_hub.py --kubeconfig $KUBECONFIG --junit-xml $WORKSPACE/test_subscription_status_hub.xml - -pytest -lv --disable-warnings test_subscription_status_edge.py --kubeconfig $KUBECONFIG_EDGE --junit-xml $WORKSPACE/test_subscription_status_edge.xml - -pytest -lv --disable-warnings test_validate_hub_site_components.py --kubeconfig $KUBECONFIG --junit-xml $WORKSPACE/test_validate_hub_site_components.xml - -pytest -lv --disable-warnings test_validate_edge_site_components.py --kubeconfig $KUBECONFIG_EDGE --junit-xml $WORKSPACE/test_validate_edge_site_components.xml - -pytest -lv --disable-warnings test_modify_web_content.py --kubeconfig $KUBECONFIG --junit-xml $WORKSPACE/test_modify_web_content.xml - -python3 create_ci_badge.py diff --git a/tmp/acm-hub-bootstrap/tests/interop/test_modify_web_content.py b/tmp/acm-hub-bootstrap/tests/interop/test_modify_web_content.py deleted file mode 100644 index 44cf045..0000000 --- a/tmp/acm-hub-bootstrap/tests/interop/test_modify_web_content.py +++ /dev/null @@ -1,89 +0,0 @@ -import logging -import os -import re -import subprocess -import time - -import pytest -import requests -from ocp_resources.route import Route -from openshift.dynamic.exceptions import NotFoundError -from validatedpatterns_tests.interop.edge_util import modify_file_content - -from . import __loggername__ - -logger = logging.getLogger(__loggername__) - - -@pytest.mark.modify_web_content -def test_modify_web_content(openshift_dyn_client): - logger.info("Find the url for the hello-world route") - try: - for route in Route.get( - dyn_client=openshift_dyn_client, - namespace="hello-world", - name="hello-world", - ): - logger.info(route.instance.spec.host) - except NotFoundError: - err_msg = "hello-world url/route is missing in hello-world namespace" - logger.error(f"FAIL: {err_msg}") - assert False, err_msg - - url = "http://" + route.instance.spec.host - response = requests.get(url) - logger.info(f"Current page content: {response.content}") - - if os.getenv("EXTERNAL_TEST") != "true": - chart = ( - f"{os.environ['HOME']}" - + "/validated_patterns/multicloud-gitops/charts/" - + "all/hello-world/templates/hello-world-cm.yaml" - ) - else: - chart = "../../charts/all/hello-world/templates/hello-world-cm.yaml" - - logger.info("Modify the file content") - orig_heading = "

Hello World!

" - new_heading = "

Validated Patterns QE was here!

" - modify_file_content( - file_name=chart, orig_content=orig_heading, new_content=new_heading - ) - - logger.info("Merge the change") - patterns_repo = f"{os.environ['HOME']}/validated_patterns/multicloud-gitops" - if os.getenv("EXTERNAL_TEST") != "true": - subprocess.run(["git", "add", chart], cwd=f"{patterns_repo}") - subprocess.run( - ["git", "commit", "-m", "Updating 'hello-world'"], cwd=f"{patterns_repo}" - ) - push = subprocess.run( - ["git", "push"], cwd=f"{patterns_repo}", capture_output=True, text=True - ) - else: - subprocess.run(["git", "add", chart]) - subprocess.run(["git", "commit", "-m", "Updating 'hello-world'"]) - push = subprocess.run(["git", "push"], capture_output=True, text=True) - logger.info(push.stdout) - logger.info(push.stderr) - - logger.info("Checking for updated page content") - timeout = time.time() + 60 * 10 - while time.time() < timeout: - time.sleep(30) - response = requests.get(url) - logger.info(response.content) - - new_content = re.search(new_heading, str(response.content)) - - logger.info(new_content) - if (new_content is None) or (new_content.group() != new_heading): - continue - break - - if (new_content is None) or (new_content.group() != new_heading): - err_msg = "Did not find updated page content" - logger.error(f"FAIL: {err_msg}") - assert False, err_msg - else: - logger.info("PASS: Found updated page content") diff --git a/tmp/acm-hub-bootstrap/tests/interop/test_subscription_status_edge.py b/tmp/acm-hub-bootstrap/tests/interop/test_subscription_status_edge.py deleted file mode 100644 index d8ef34a..0000000 --- a/tmp/acm-hub-bootstrap/tests/interop/test_subscription_status_edge.py +++ /dev/null @@ -1,25 +0,0 @@ -import logging - -import pytest -from validatedpatterns_tests.interop import subscription - -from . import __loggername__ - -logger = logging.getLogger(__loggername__) - - -@pytest.mark.subscription_status_edge -def test_subscription_status_edge(openshift_dyn_client): - # These are the operator subscriptions and their associated namespaces - expected_subs = { - "openshift-gitops-operator": ["openshift-operators"], - } - - err_msg = subscription.subscription_status( - openshift_dyn_client, expected_subs, diff=False - ) - if err_msg: - logger.error(f"FAIL: {err_msg}") - assert False, err_msg - else: - logger.info("PASS: Subscription status check passed") diff --git a/tmp/acm-hub-bootstrap/tests/interop/test_subscription_status_hub.py b/tmp/acm-hub-bootstrap/tests/interop/test_subscription_status_hub.py deleted file mode 100644 index 90083a9..0000000 --- a/tmp/acm-hub-bootstrap/tests/interop/test_subscription_status_hub.py +++ /dev/null @@ -1,27 +0,0 @@ -import logging - -import pytest -from validatedpatterns_tests.interop import subscription - -from . import __loggername__ - -logger = logging.getLogger(__loggername__) - - -@pytest.mark.subscription_status_hub -def test_subscription_status_hub(openshift_dyn_client): - # These are the operator subscriptions and their associated namespaces - expected_subs = { - "openshift-gitops-operator": ["openshift-operators"], - "advanced-cluster-management": ["open-cluster-management"], - "multicluster-engine": ["multicluster-engine"], - } - - err_msg = subscription.subscription_status( - openshift_dyn_client, expected_subs, diff=True - ) - if err_msg: - logger.error(f"FAIL: {err_msg}") - assert False, err_msg - else: - logger.info("PASS: Subscription status check passed") diff --git a/tmp/acm-hub-bootstrap/tests/interop/test_validate_edge_site_components.py b/tmp/acm-hub-bootstrap/tests/interop/test_validate_edge_site_components.py deleted file mode 100644 index 3f4c91e..0000000 --- a/tmp/acm-hub-bootstrap/tests/interop/test_validate_edge_site_components.py +++ /dev/null @@ -1,72 +0,0 @@ -import logging -import os - -import pytest -from validatedpatterns_tests.interop import application, components - -from . import __loggername__ - -logger = logging.getLogger(__loggername__) - -oc = os.environ["HOME"] + "/oc_client/oc" - - -@pytest.mark.test_validate_edge_site_components -def test_validate_edge_site_components(): - logger.info("Checking Openshift version on edge site") - version_out = components.dump_openshift_version() - logger.info(f"Openshift version:\n{version_out}") - - -@pytest.mark.validate_edge_site_reachable -def test_validate_edge_site_reachable(kube_config, openshift_dyn_client): - logger.info("Check if edge site API end point is reachable") - err_msg = components.validate_site_reachable(kube_config, openshift_dyn_client) - if err_msg: - logger.error(f"FAIL: {err_msg}") - assert False, err_msg - else: - logger.info("PASS: Edge site is reachable") - - -@pytest.mark.validate_argocd_reachable_edge_site -def test_validate_argocd_reachable_edge_site(openshift_dyn_client): - logger.info("Check if argocd route/url on edge site is reachable") - err_msg = components.validate_argocd_reachable(openshift_dyn_client) - if err_msg: - logger.error(f"FAIL: {err_msg}") - assert False, err_msg - else: - logger.info("PASS: Argocd is reachable") - - -@pytest.mark.check_pod_status_edge -def test_check_pod_status(openshift_dyn_client): - logger.info("Checking pod status") - projects = [ - "openshift-operators", - "open-cluster-management-agent", - "open-cluster-management-agent-addon", - "openshift-gitops", - ] - err_msg = components.check_pod_status(openshift_dyn_client, projects) - if err_msg: - logger.error(f"FAIL: {err_msg}") - assert False, err_msg - else: - logger.info("PASS: Pod status check succeeded.") - - -@pytest.mark.validate_argocd_applications_health_edge_site -def test_validate_argocd_applications_health_edge_site(openshift_dyn_client): - logger.info("Get all applications deployed by argocd on edge site") - projects = ["openshift-gitops"] - unhealthy_apps = application.get_argocd_application_status( - openshift_dyn_client, projects - ) - if unhealthy_apps: - err_msg = "Some or all applications deployed on edge site are unhealthy" - logger.error(f"FAIL: {err_msg}:\n{unhealthy_apps}") - assert False, err_msg - else: - logger.info("PASS: All applications deployed on edge site are healthy.") diff --git a/tmp/acm-hub-bootstrap/tests/interop/test_validate_hub_site_components.py b/tmp/acm-hub-bootstrap/tests/interop/test_validate_hub_site_components.py deleted file mode 100644 index b5bec91..0000000 --- a/tmp/acm-hub-bootstrap/tests/interop/test_validate_hub_site_components.py +++ /dev/null @@ -1,95 +0,0 @@ -import logging -import os - -import pytest -from ocp_resources.storage_class import StorageClass -from validatedpatterns_tests.interop import application, components - -from . import __loggername__ - -logger = logging.getLogger(__loggername__) - -oc = os.environ["HOME"] + "/oc_client/oc" - - -@pytest.mark.test_validate_hub_site_components -def test_validate_hub_site_components(openshift_dyn_client): - logger.info("Checking Openshift version on hub site") - version_out = components.dump_openshift_version() - logger.info(f"Openshift version:\n{version_out}") - - logger.info("Dump PVC and storageclass info") - pvcs_out = components.dump_pvc() - logger.info(f"PVCs:\n{pvcs_out}") - - for sc in StorageClass.get(dyn_client=openshift_dyn_client): - logger.info(sc.instance) - - -@pytest.mark.validate_hub_site_reachable -def test_validate_hub_site_reachable(kube_config, openshift_dyn_client): - logger.info("Check if hub site API end point is reachable") - err_msg = components.validate_site_reachable(kube_config, openshift_dyn_client) - if err_msg: - logger.error(f"FAIL: {err_msg}") - assert False, err_msg - else: - logger.info("PASS: Hub site is reachable") - - -@pytest.mark.check_pod_status_hub -def test_check_pod_status(openshift_dyn_client): - logger.info("Checking pod status") - projects = [ - "openshift-operators", - "open-cluster-management", - "open-cluster-management-hub", - "openshift-gitops", - "vault", - ] - err_msg = components.check_pod_status(openshift_dyn_client, projects) - if err_msg: - logger.error(f"FAIL: {err_msg}") - assert False, err_msg - else: - logger.info("PASS: Pod status check succeeded.") - - -@pytest.mark.validate_acm_self_registration_managed_clusters -def test_validate_acm_self_registration_managed_clusters(openshift_dyn_client): - logger.info("Check ACM self registration for edge site") - kubefiles = [os.getenv("KUBECONFIG_EDGE")] - err_msg = components.validate_acm_self_registration_managed_clusters( - openshift_dyn_client, kubefiles - ) - if err_msg: - logger.error(f"FAIL: {err_msg}") - assert False, err_msg - else: - logger.info("PASS: Edge site is self registered") - - -@pytest.mark.validate_argocd_reachable_hub_site -def test_validate_argocd_reachable_hub_site(openshift_dyn_client): - logger.info("Check if argocd route/url on hub site is reachable") - err_msg = components.validate_argocd_reachable(openshift_dyn_client) - if err_msg: - logger.error(f"FAIL: {err_msg}") - assert False, err_msg - else: - logger.info("PASS: Argocd is reachable") - - -@pytest.mark.validate_argocd_applications_health_hub_site -def test_validate_argocd_applications_health_hub_site(openshift_dyn_client): - logger.info("Get all applications deployed by argocd on hub site") - projects = ["openshift-gitops", "multicloud-gitops-hub"] - unhealthy_apps = application.get_argocd_application_status( - openshift_dyn_client, projects - ) - if unhealthy_apps: - err_msg = "Some or all applications deployed on hub site are unhealthy" - logger.error(f"FAIL: {err_msg}:\n{unhealthy_apps}") - assert False, err_msg - else: - logger.info("PASS: All applications deployed on hub site are healthy.") diff --git a/tmp/acm-hub-bootstrap/values-4.18-hub.yaml b/tmp/acm-hub-bootstrap/values-4.18-hub.yaml deleted file mode 100644 index e582c25..0000000 --- a/tmp/acm-hub-bootstrap/values-4.18-hub.yaml +++ /dev/null @@ -1,6 +0,0 @@ -clusterGroup: - subscriptions: - acm: - name: advanced-cluster-management - namespace: open-cluster-management - channel: release-2.13 diff --git a/tmp/acm-hub-bootstrap/values-global.yaml b/tmp/acm-hub-bootstrap/values-global.yaml deleted file mode 100644 index c01a319..0000000 --- a/tmp/acm-hub-bootstrap/values-global.yaml +++ /dev/null @@ -1,12 +0,0 @@ ---- -global: - pattern: multicloud-gitops - options: - useCSV: false - syncPolicy: Automatic - installPlanApproval: Automatic -main: - clusterGroupName: hub - multiSourceConfig: - enabled: true - clusterGroupChartVersion: "0.9.*" diff --git a/tmp/acm-hub-bootstrap/values-group-one.yaml b/tmp/acm-hub-bootstrap/values-group-one.yaml deleted file mode 100644 index f17a726..0000000 --- a/tmp/acm-hub-bootstrap/values-group-one.yaml +++ /dev/null @@ -1,108 +0,0 @@ -global: - options: - useCSV: False - syncPolicy: Automatic - installPlanApproval: Automatic -clusterGroup: - name: group-one - isHubCluster: false - namespaces: - - config-demo - - hello-world - - golang-external-secrets - # The only subscription on spokes is gitops which gets managed by ACM - # subscriptions: - projects: - - eso - - config-demo - - hello-world - applications: - golang-external-secrets: - name: golang-external-secrets - namespace: golang-external-secrets - project: eso - chart: golang-external-secrets - chartVersion: 0.1.* - config-demo: - name: config-demo - namespace: config-demo - project: config-demo - path: charts/all/config-demo - hello-world: - name: hello-world - namespace: hello-world - project: hello-world - path: charts/all/hello-world - imperative: - # NOTE: We *must* use lists and not hashes. As hashes lose ordering once parsed by helm - # The default schedule is every 10 minutes: imperative.schedule - # Total timeout of all jobs is 1h: imperative.activeDeadlineSeconds - # imagePullPolicy is set to always: imperative.imagePullPolicy - # For additional overrides that apply to the jobs, please refer to - # https://hybrid-cloud-patterns.io/imperative-actions/#additional-job-customizations - jobs: - - name: hello-world - # ansible playbook to be run - playbook: rhvp.cluster_utils.hello_world - # per playbook timeout in seconds - timeout: 234 - # verbosity: "-v" - # Explicitly mention the cluster-state based overrides we plan to use for this pattern. - # We can use self-referential variables because the chart calls the tpl function with these variables defined - sharedValueFiles: - - '/overrides/values-{{ $.Values.global.clusterPlatform }}.yaml' - # To mirror the "Classic" magic include structure, the clusterGroup would need all of these: - # sharedValueFiles: - # - '/overrides/values-{{ $.Values.global.clusterPlatform }}.yaml' - # - '/overrides/values-{{ $.Values.global.clusterPlatform }}-{{ $.Values.global.clusterVersion }}.yaml' - # - '/overrides/values-{{ $.Values.global.clusterPlatform }}-{{ $.Values.clusterGroup.name }}.yaml' - # - '/overrides/values-{{ $.Values.global.clusterVersion }}-{{ $.Values.clusterGroup.name }}.yaml" -# To have apps in multiple flavors, use namespaces and use helm overrides as appropriate -# -# pipelines: -# name: pipelines -# namespace: production -# project: datacenter -# path: applications/pipeline -# repoURL: https://github.com/you/applications.git -# targetRevision: stable -# overrides: -# - name: myparam -# value: myparam -# -# pipelines_staging: -# - name: pipelines -# namespace: staging -# project: datacenter -# path: applications/pipeline -# repoURL: https://github.com/you/applications.git -# targetRevision: main -# -# Additional applications -# Be sure to include additional resources your apps will require -# +X machines -# +Y RAM -# +Z CPU -# vendor-app: -# name: vendor-app -# namespace: default -# project: vendor -# path: path/to/myapp -# repoURL: https://github.com/vendor/applications.git -# targetRevision: main - -# managedSites: -# factory: -# name: factory -# # repoURL: https://github.com/dagger-refuse-cool/manuela-factory.git -# targetRevision: main -# path: applications/factory -# helmOverrides: -# - name: site.isHubCluster -# value: false -# clusterSelector: -# matchExpressions: -# - key: vendor -# operator: In -# values: -# - OpenShift diff --git a/tmp/acm-hub-bootstrap/values-hub.yaml b/tmp/acm-hub-bootstrap/values-hub.yaml deleted file mode 100644 index 3f08449..0000000 --- a/tmp/acm-hub-bootstrap/values-hub.yaml +++ /dev/null @@ -1,171 +0,0 @@ -clusterGroup: - name: hub - isHubCluster: true - namespaces: - - open-cluster-management - - vault - - golang-external-secrets - - config-demo - - hello-world - subscriptions: - acm: - name: advanced-cluster-management - namespace: open-cluster-management - channel: release-2.13 - #csv: advanced-cluster-management.v2.6.1 - projects: - - hub - - config-demo - - hello-world - # Explicitly mention the cluster-state based overrides we plan to use for this pattern. - # We can use self-referential variables because the chart calls the tpl function with these variables defined - sharedValueFiles: - - '/overrides/values-{{ $.Values.global.clusterPlatform }}.yaml' - # sharedValueFiles is a flexible mechanism that will add the listed valuefiles to every app defined in the - # applications section. We intend this to supplement and possibly even replace previous "magic" mechanisms, though - # we do not at present have a target date for removal. - # - # To replicate the "classic" magic include structure, the clusterGroup would need all of these - # sharedValueFiles, in this order: - # - '/overrides/values-{{ $.Values.global.clusterPlatform }}.yaml' - # - '/overrides/values-{{ $.Values.global.clusterPlatform }}-{{ $.Values.global.clusterVersion }}.yaml' - # - '/overrides/values-{{ $.Values.global.clusterPlatform }}-{{ $.Values.clusterGroup.name }}.yaml' - # - '/overrides/values-{{ $.Values.global.clusterVersion }}-{{ $.Values.clusterGroup.name }}.yaml" - # - '/overrides/values-{{ $.Values.global.localClusterName }}.yaml' - - # This kind of variable substitution will work with any of the variables the Validated Patterns operator knows - # about and sets, so this is also possible, for example: - # - '/overrides/values-{{ $.Values.global.hubClusterDomain }}.yaml' - # - '/overrides/values-{{ $.Values.global.localClusterDomain }}.yaml' - applications: - acm: - name: acm - namespace: open-cluster-management - project: hub - chart: acm - chartVersion: 0.1.* - ignoreDifferences: - - group: internal.open-cluster-management.io - kind: ManagedClusterInfo - jsonPointers: - - /spec/loggingCA - vault: - name: vault - namespace: vault - project: hub - chart: hashicorp-vault - chartVersion: 0.1.* - golang-external-secrets: - name: golang-external-secrets - namespace: golang-external-secrets - project: hub - chart: golang-external-secrets - chartVersion: 0.1.* - config-demo: - name: config-demo - namespace: config-demo - project: config-demo - path: charts/all/config-demo - hello-world: - name: hello-world - namespace: hello-world - project: hello-world - path: charts/all/hello-world - imperative: - # NOTE: We *must* use lists and not hashes. As hashes lose ordering once parsed by helm - # The default schedule is every 10 minutes: imperative.schedule - # Total timeout of all jobs is 1h: imperative.activeDeadlineSeconds - # imagePullPolicy is set to always: imperative.imagePullPolicy - # For additional overrides that apply to the jobs, please refer to - # https://hybrid-cloud-patterns.io/imperative-actions/#additional-job-customizations - jobs: - - name: hello-world - # ansible playbook to be run - playbook: rhvp.cluster_utils.hello_world - # per playbook timeout in seconds - timeout: 234 - # verbosity: "-v" - managedClusterGroups: - exampleRegion: - name: group-one - acmlabels: - - name: clusterGroup - value: group-one - helmOverrides: - - name: clusterGroup.isHubCluster - value: false - # Before enabling cluster provisioning, ensure AWS and/or Azure - # credentials and OCP pull secrets are defined in Vault. - # See values-secret.yaml.template - # - #clusterPools: - # exampleAWSPool: - # name: aws-ap - # openshiftVersion: 4.10.18 - # baseDomain: blueprints.rhecoeng.com - # platform: - # aws: - # region: ap-southeast-2 - # clusters: - # - One - # - # exampleAzurePool: - # name: azure-us - # openshiftVersion: 4.10.18 - # baseDomain: blueprints.rhecoeng.com - # platform: - # azure: - # baseDomainResourceGroupName: dojo-dns-zones - # region: eastus - # clusters: - # - Two - # - Three -# To have apps in multiple flavors, use namespaces and use helm overrides as appropriate -# -# pipelines: -# name: pipelines -# namespace: production -# project: datacenter -# path: applications/pipeline -# repoURL: https://github.com/you/applications.git -# targetRevision: stable -# overrides: -# - name: myparam -# value: myparam -# -# pipelines_staging: -# - name: pipelines -# namespace: staging -# project: datacenter -# path: applications/pipeline -# repoURL: https://github.com/you/applications.git -# targetRevision: main -# -# Additional applications -# Be sure to include additional resources your apps will require -# +X machines -# +Y RAM -# +Z CPU -# vendor-app: -# name: vendor-app -# namespace: default -# project: vendor -# path: path/to/myapp -# repoURL: https://github.com/vendor/applications.git -# targetRevision: main - -# managedSites: -# factory: -# name: factory -# # repoURL: https://github.com/dagger-refuse-cool/manuela-factory.git -# targetRevision: main -# path: applications/factory -# helmOverrides: -# - name: site.isHubCluster -# value: false -# clusterSelector: -# matchExpressions: -# - key: vendor -# operator: In -# values: -# - OpenShift diff --git a/tmp/acm-hub-bootstrap/values-standalone.yaml b/tmp/acm-hub-bootstrap/values-standalone.yaml deleted file mode 100644 index 41744ed..0000000 --- a/tmp/acm-hub-bootstrap/values-standalone.yaml +++ /dev/null @@ -1,61 +0,0 @@ -clusterGroup: - name: standalone - isHubCluster: false - namespaces: - - vault - - golang-external-secrets - - config-demo - - hello-world - subscriptions: {} - projects: - - hub - - config-demo - - hello-world - # Explicitly mention the cluster-state based overrides we plan to use for this pattern. - # We can use self-referential variables because the chart calls the tpl function with these variables defined - sharedValueFiles: - - '/overrides/values-{{ $.Values.global.clusterPlatform }}.yaml' - # sharedValueFiles is a flexible mechanism that will add the listed valuefiles to every app defined in the - # applications section. - # - # This kind of variable substitution will work with any of the variables the Validated Patterns operator knows - # about and sets, so this is also possible, for example: - # - '/overrides/values-{{ $.Values.global.hubClusterDomain }}.yaml' - # - '/overrides/values-{{ $.Values.global.localClusterDomain }}.yaml' - applications: - vault: - name: vault - namespace: vault - project: hub - chart: hashicorp-vault - chartVersion: 0.1.* - golang-external-secrets: - name: golang-external-secrets - namespace: golang-external-secrets - project: hub - chart: golang-external-secrets - chartVersion: 0.1.* - config-demo: - name: config-demo - namespace: config-demo - project: config-demo - path: charts/all/config-demo - hello-world: - name: hello-world - namespace: hello-world - project: hello-world - path: charts/all/hello-world - imperative: - # NOTE: We *must* use lists and not hashes. As hashes lose ordering once parsed by helm - # The default schedule is every 10 minutes: imperative.schedule - # Total timeout of all jobs is 1h: imperative.activeDeadlineSeconds - # imagePullPolicy is set to always: imperative.imagePullPolicy - # For additional overrides that apply to the jobs, please refer to - # https://hybrid-cloud-patterns.io/imperative-actions/#additional-job-customizations - jobs: - - name: hello-world - # ansible playbook to be run - playbook: rhvp.cluster_utils.hello_world - # per playbook timeout in seconds - timeout: 234 - # verbosity: "-v" diff --git a/tmp/groups.tf b/tmp/groups.tf deleted file mode 100644 index a550ed1..0000000 --- a/tmp/groups.tf +++ /dev/null @@ -1,8 +0,0 @@ -// Matcher group for OCP Internal machinesmachines -resource "matchbox_group" "ocp-hub" { - name = "ocp-hub" # Physical Server - profile = matchbox_profile.openshift-agent-install.name - selector = { - mac = "98:b7:85:1e:c6:f1" # PXE boots and installs to 10GbE NIC - } -} diff --git a/tmp/install-config.yaml b/tmp/install-config.yaml deleted file mode 100644 index 548b2d1..0000000 --- a/tmp/install-config.yaml +++ /dev/null @@ -1,25 +0,0 @@ -apiVersion: v1 -baseDomain: int.mk-labs.cloud -compute: -- name: worker - replicas: 0 -controlPlane: - hyperthreading: Enabled - name: master - replicas: 1 -metadata: - name: hub -networking: - clusterNetwork: - - cidr: 10.128.0.0/14 #<== Internal node network. Not available externally. - hostPrefix: 23 - machineNetwork: - - cidr: 10.1.71.0/24 #<== Real world host network. - networkType: OVNKubernetes - serviceNetwork: - - 172.30.0.0/16 #<== Internal cluster overlay. Not available externally. -platform: - none: {} -fips: false -pullSecret: '{"auths":{"cloud.openshift.com":{"auth":"b3BlbnNoaWZ0LXJlbGVhc2UtZGV2K29jbV9hY2Nlc3NfY2ZlYjYxMjE5ZmFiNDA1OWIwZWZmZDJlZTUxZTNlOTc6UjhaUEs2UEQyTjlBNURERUxHUjE0UDdLQ1pWR1ZPME1KUDYzUTUzQ0hBMTlIVjE4STJETzBHMkdGNzg2QjQxOA==","email":"rblundon@redhat.com"},"quay.io":{"auth":"b3BlbnNoaWZ0LXJlbGVhc2UtZGV2K29jbV9hY2Nlc3NfY2ZlYjYxMjE5ZmFiNDA1OWIwZWZmZDJlZTUxZTNlOTc6UjhaUEs2UEQyTjlBNURERUxHUjE0UDdLQ1pWR1ZPME1KUDYzUTUzQ0hBMTlIVjE4STJETzBHMkdGNzg2QjQxOA==","email":"rblundon@redhat.com"},"registry.connect.redhat.com":{"auth":"fHVoYy1wb29sLTk0ZGM3NWFiLTEyYzAtNGRhMC1hMjI5LTBmOTZiY2Y2NGZhMDpleUpoYkdjaU9pSlNVelV4TWlKOS5leUp6ZFdJaU9pSmhabVppWWpRMFpqWXlPVEkwTVRKaFlqWTBaVFl3T1RSaFpqRmpabUk0WlNKOS5tS3RLNnYxa1ZEZjZOcXJweTBXTjRubEQ1bDFhTG9sbWtvV3YzYzcwdTJJb29iODBsZGEtanJHYV85LWVVUU1IM1dsU3BvdEQzQzFBdi1wUE5pT0tKM2paSGJGOEoxTlNtSmdsb0hSR214NDZXb2FGYlh5c2JuUVhwamNBU0l4MnpZQ1hFSWlaNkZrRzFwUUMzWHlISTdsMVh6dEZ1TG5yWFBGUUhUdHFJcm5KNDA5R2c2Uk5jNXhnOEpMWEY4UmFWM2x1SGZqdWY2RHJRaGdzc3Vla1BOcDc0Q0g1Y0k4T3pYVWVLMy1xelZkQ3FaSDhZYXp5dHVJRDFmQkxyUDV4Nnh5a3U3NFd6dEJXaE9rMFRBdnVldkNHSVlLOV91MGlFSVl0bll5TTJndnpWSTl4YXBUckkwMW9DcF9NXzh2YU1YVzJjb2ZUNEE5b2VrZDM0ZmdkUGs4MFU0UzBBN0RabWpiMFZCT211Y0xuX1F6U2FQMkZjMmtGNDExenBfb2I5ZHl1MEZhSXN5bF9YTG5kZDF3S21JU2N6N04tZDBpM244QkpvYnh6YUJwZzJxUEdhV2VvTXJNWmYwRGdzVEo4VmhBSWlBNTVwUDYwSGVpRzdzMUhUQ1Rudl9kTlpaMWY0TzMwUTBNVnRTQWl6Q3Q0azdnbHd5VzZVamU4czd2WVZPekFvUEFvTEZKQVZVcUcwWUNUYXJodnBsZ204MWlzWHhwWk5nMEQwUkZISmRIYXFmRXQtVE5wVHplZzlBOEZ6QkVQaG5ZTU1ZMEhzUVpONHFNbE1kTHBHOHJrZU04azRoWGIyQ08wcFZvMUluY1d2aFQ5cDgxV1M0QlNfMHR6bG1EckdTbXJYN3JNTnN1V2RZbmlpNm16WFJuRUlIV25FelNUc2hhLUtRcw==","email":"rblundon@redhat.com"},"registry.redhat.io":{"auth":"fHVoYy1wb29sLTk0ZGM3NWFiLTEyYzAtNGRhMC1hMjI5LTBmOTZiY2Y2NGZhMDpleUpoYkdjaU9pSlNVelV4TWlKOS5leUp6ZFdJaU9pSmhabVppWWpRMFpqWXlPVEkwTVRKaFlqWTBaVFl3T1RSaFpqRmpabUk0WlNKOS5tS3RLNnYxa1ZEZjZOcXJweTBXTjRubEQ1bDFhTG9sbWtvV3YzYzcwdTJJb29iODBsZGEtanJHYV85LWVVUU1IM1dsU3BvdEQzQzFBdi1wUE5pT0tKM2paSGJGOEoxTlNtSmdsb0hSR214NDZXb2FGYlh5c2JuUVhwamNBU0l4MnpZQ1hFSWlaNkZrRzFwUUMzWHlISTdsMVh6dEZ1TG5yWFBGUUhUdHFJcm5KNDA5R2c2Uk5jNXhnOEpMWEY4UmFWM2x1SGZqdWY2RHJRaGdzc3Vla1BOcDc0Q0g1Y0k4T3pYVWVLMy1xelZkQ3FaSDhZYXp5dHVJRDFmQkxyUDV4Nnh5a3U3NFd6dEJXaE9rMFRBdnVldkNHSVlLOV91MGlFSVl0bll5TTJndnpWSTl4YXBUckkwMW9DcF9NXzh2YU1YVzJjb2ZUNEE5b2VrZDM0ZmdkUGs4MFU0UzBBN0RabWpiMFZCT211Y0xuX1F6U2FQMkZjMmtGNDExenBfb2I5ZHl1MEZhSXN5bF9YTG5kZDF3S21JU2N6N04tZDBpM244QkpvYnh6YUJwZzJxUEdhV2VvTXJNWmYwRGdzVEo4VmhBSWlBNTVwUDYwSGVpRzdzMUhUQ1Rudl9kTlpaMWY0TzMwUTBNVnRTQWl6Q3Q0azdnbHd5VzZVamU4czd2WVZPekFvUEFvTEZKQVZVcUcwWUNUYXJodnBsZ204MWlzWHhwWk5nMEQwUkZISmRIYXFmRXQtVE5wVHplZzlBOEZ6QkVQaG5ZTU1ZMEhzUVpONHFNbE1kTHBHOHJrZU04azRoWGIyQ08wcFZvMUluY1d2aFQ5cDgxV1M0QlNfMHR6bG1EckdTbXJYN3JNTnN1V2RZbmlpNm16WFJuRUlIV25FelNUc2hhLUtRcw==","email":"rblundon@redhat.com"}}}' -sshKey: 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICB/UfNTK2JX8Lq0H75yHrWgr32vhLFBcE7r+cEC6hvd rblundon@rblundon-mac' diff --git a/tmp/profiles.tf b/tmp/profiles.tf deleted file mode 100644 index bf187a8..0000000 --- a/tmp/profiles.tf +++ /dev/null @@ -1,16 +0,0 @@ -// Fedora CoreOS profile -resource "matchbox_profile" "openshift-agent-install" { - name = "hub" - kernel = "/assets/hub/agent.x86_64-vmlinuz" - initrd = [ - "--name initrd /assets/hub/agent.x86_64-initrd.img" - ] - - args = [ - "initrd=initrd", - "coreos.live.rootfs_url=${var.matchbox_http_endpoint}/assets/hub/agent.x86_64-rootfs.img", - "rw", - "ignition.firstboot", - "ignition.platform.id=metal", - ] -} diff --git a/tmp/provider.tf b/tmp/provider.tf deleted file mode 100644 index 1d0559b..0000000 --- a/tmp/provider.tf +++ /dev/null @@ -1,20 +0,0 @@ -// Configure the matchbox provider -provider "matchbox" { - endpoint = var.matchbox_rpc_endpoint - client_cert = file("/etc/matchbox/client.crt") - client_key = file("/etc/matchbox/client.key") - ca = file("/etc/matchbox/ca.crt") -} - -terraform { - required_providers { - ct = { - source = "poseidon/ct" - version = "0.13.0" - } - matchbox = { - source = "poseidon/matchbox" - version = "0.5.4" - } - } -} diff --git a/tmp/routercopy.yaml b/tmp/routercopy.yaml deleted file mode 100644 index 7577c84..0000000 --- a/tmp/routercopy.yaml +++ /dev/null @@ -1,28 +0,0 @@ - ---- -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: router-cert - namespace: openshift-ingress - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -spec: - commonName: apps.hub.mk-labs.cloud - dnsNames: - - apps.hub.mk-labs.cloud - - "*.apps.hub.mk-labs.cloud" - issuerRef: - group: cert-manager.io - kind: ClusterIssuer - name: letsencrypt-prod - secretName: router-cert ---- -apiVersion: operator.openshift.io/v1 -kind: IngressController -metadata: - name: default - namespace: openshift-ingress-operator -spec: - defaultCertificate: - name: router-cert diff --git a/tmp/terraform.tfvars b/tmp/terraform.tfvars deleted file mode 100644 index 1b72fe6..0000000 --- a/tmp/terraform.tfvars +++ /dev/null @@ -1,2 +0,0 @@ -matchbox_http_endpoint = "http://matchbox.int.mk-labs.cloud:8080" -matchbox_rpc_endpoint = "matchbox.int.mk-labs.cloud:8081" diff --git a/tmp/test-cert.yaml b/tmp/test-cert.yaml deleted file mode 100644 index ab9b92c..0000000 --- a/tmp/test-cert.yaml +++ /dev/null @@ -1,13 +0,0 @@ ---- -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: test-hub-mklabs-cloud - namespace: default -spec: - secretName: test-hub-mklabs-cloud-tls - issuerRef: - name: letsencrypt-staging - kind: ClusterIssuer - dnsNames: - - "test.mklabs.cloud" \ No newline at end of file diff --git a/tmp/values-hub.yaml b/tmp/values-hub.yaml deleted file mode 100644 index dc3d2fd..0000000 --- a/tmp/values-hub.yaml +++ /dev/null @@ -1,31 +0,0 @@ -# https://github.com/external-secrets/external-secrets/blob/main/deploy/charts/external-secrets/values.yaml - -external-secrets: - enabled: true # Default: true - - resources: - requests: - cpu: 10m - memory: 32Mi - - createOperator: true - # -- if true, the operator will process cluster external secret. Else, it will ignore them. - processClusterExternalSecret: true - - # -- if true, the operator will process cluster push secret. Else, it will ignore them. - processClusterPushSecret: false #true - - # -- if true, the operator will process cluster store. Else, it will ignore them. - processClusterStore: false #true - - # -- if true, the operator will process push secret. Else, it will ignore them. - processPushSecret: false #true - - webhook: - # -- Specifies whether a webhook deployment be created. If set to false, crds.conversion.enabled should also be set to false otherwise the kubeapi will be hammered because the conversion is looking for a webhook endpoint. - create: false #true - - certController: - # -- Specifies whether a certificate controller deployment be created. - create: false #true - diff --git a/tmp/variables.tf b/tmp/variables.tf deleted file mode 100644 index 2917854..0000000 --- a/tmp/variables.tf +++ /dev/null @@ -1,10 +0,0 @@ -variable "matchbox_http_endpoint" { - type = string - description = "Matchbox HTTP read-only endpoint (e.g. http://matchbox.example.com:8080)" -} - -variable "matchbox_rpc_endpoint" { - type = string - description = "Matchbox gRPC API endpoint, without the protocol (e.g. matchbox.example.com:8081)" -} - diff --git a/~/Documents/git/applescript-calendar-sync/.gitignore b/~/Documents/git/applescript-calendar-sync/.gitignore new file mode 100644 index 0000000..15575cf --- /dev/null +++ b/~/Documents/git/applescript-calendar-sync/.gitignore @@ -0,0 +1,40 @@ +# macOS +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# AppleScript compiled files +*.scpt + +# Logs +*.log + +# IDE files +.vscode/ +.idea/ + +# Backup files +*.backup +*~ \ No newline at end of file diff --git a/~/Documents/git/applescript-calendar-sync/README.md b/~/Documents/git/applescript-calendar-sync/README.md new file mode 100644 index 0000000..37f9af8 --- /dev/null +++ b/~/Documents/git/applescript-calendar-sync/README.md @@ -0,0 +1,52 @@ +# AppleScript Calendar Sync + +An AppleScript utility that synchronizes calendar events between two calendar accounts for the current day. + +## Overview + +This script reads events from a source calendar and mirrors them to a destination calendar, including removal of events that no longer exist in the source. It's designed to keep two calendars in sync automatically. + +## Features + +- Synchronizes events for the current day only +- Configurable source and destination calendars +- Comprehensive logging and error handling +- Progress tracking and user notifications +- Handles event creation, updates, and removal + +## Configuration + +Edit the configuration properties at the top of `calendar-sync.applescript`: + +```applescript +property sourceAccountName : "Work Account" +property sourceCalendarName : "Main Calendar" +property destinationAccountName : "Personal Account" +property destinationCalendarName : "Synced Events" +property enableLogging : true +property enableDebugMode : false +``` + +## Usage + +1. Configure the source and destination calendar settings +2. Run the script using Script Editor or from the command line with `osascript` +3. The script will sync today's events and display a summary + +## Documentation + +The `docs/` directory contains the complete specification: + +- `requirements.md` - Detailed requirements and user stories +- `design.md` - Technical design and architecture +- `tasks.md` - Implementation plan and task breakdown + +## Development Status + +This project is currently in development. See `docs/tasks.md` for the current implementation progress. + +## Requirements + +- macOS with Calendar app +- AppleScript support +- Access to both source and destination calendar accounts \ No newline at end of file