Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🚀 Add Project controller #309

Merged
merged 11 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/helm-end-to-end-tfc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ jobs:
--set operator.syncPeriod=30s \
--set controllers.agentPool.workers=5 \
--set controllers.module.workers=5 \
--set controllers.project.workers=5 \
--set controllers.workspace.workers=5

- name: Run end-to-end test suite
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/helm-end-to-end-tfe.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ jobs:
--set operator.syncPeriod=30s \
--set controllers.agentPool.workers=5 \
--set controllers.module.workers=5 \
--set controllers.project.workers=5 \
--set controllers.workspace.workers=5

- name: Run end-to-end test suite
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
## 2.2.0 (UNRELEASED)

FEATURES:

* `Project`: add a new controller `Project` that allows managing Terraform Cloud Projects. [[GH-309](https://github.com/hashicorp/terraform-cloud-operator/pull/309)].

DEPENDENCIES:

* Bump `k8s.io/api` from 0.27.7 to 0.27.8. [[GH-306](https://github.com/hashicorp/terraform-cloud-operator/pull/306)]
Expand Down
13 changes: 13 additions & 0 deletions PROJECT
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Code generated by tool. DO NOT EDIT.
# This file is used to track the info used to scaffold your project
# and allow the plugins properly work.
# More info: https://book.kubebuilder.io/reference/project-config.html
componentConfig: true
domain: terraform.io
layout:
Expand Down Expand Up @@ -35,4 +39,13 @@ resources:
kind: AgentPool
path: github.com/hashicorp/terraform-cloud-operator/api/v1alpha2
version: v1alpha2
- api:
crdVersion: v1
namespaced: true
controller: true
domain: terraform.io
group: app
kind: Project
path: github.com/hashicorp/terraform-cloud-operator/api/v1alpha2
version: v1alpha2
version: "3"
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ The Operator can manage the following types of resources:

- `AgentPool` manages [Terraform Cloud Agent Pools](https://developer.hashicorp.com/terraform/cloud-docs/agents/agent-pools), [Terraform Cloud Agent Tokens](https://developer.hashicorp.com/terraform/cloud-docs/users-teams-organizations/api-tokens#agent-api-tokens) and can perform TFC agent scaling
- `Module` implements [API-driven Run Workflows](https://developer.hashicorp.com/terraform/cloud-docs/run/api)
- `Project` manages [Terraform Cloud Projects](https://developer.hashicorp.com/terraform/cloud-docs/workspaces/organize-workspaces-with-projects)
- `Workspace` manages [Terraform Cloud Workspaces](https://developer.hashicorp.com/terraform/cloud-docs/workspaces)

## Getting started

To get started see our tutorials on the HashiCorp Developer Portal:

- [Terraform Cloud Operator for Kubernetes overview](https://developer.hashicorp.com/terraform/cloud-docs/integrations/kubernetes)
- [Deploy infrastructure with the Terraform Cloud Kubernetes Operator v2](https://developer.hashicorp.com/terraform/tutorials/kubernetes/kubernetes-operator-v2)
- [Manage agent pools with the Terraform Cloud Kubernetes Operator v2](https://developer.hashicorp.com/terraform/tutorials/kubernetes/kubernetes-operator-v2-agentpool)
- [Terraform Cloud Kubernetes Operator v2 Migration Guide](https://developer.hashicorp.com/terraform/cloud-docs/integrations/kubernetes/ops-v2-migration)
Expand All @@ -31,7 +33,7 @@ To get started see our tutorials on the HashiCorp Developer Portal:

### Supported Features

The full list of supported Terraform Cloud features can be found [here](./docs/features.md).
The full list of supported Terraform Cloud features can be found on our [Developer portal](https://developer.hashicorp.com/terraform/cloud-docs/integrations/kubernetes#supported-terraform-cloud-features).

### Installation

Expand All @@ -55,6 +57,7 @@ Controllers usage guides:

- [AgentPool](./docs/agentpool.md)
- [Module](./docs/module.md)
- [Project](./docs/project.md)
- [Workspace](./docs/workspace.md)

### Metrics
Expand Down Expand Up @@ -106,6 +109,7 @@ If you encounter any issues with the Operator there are a number of ways how to
```console
$ kubectl get agentpool <NAME>
$ kubectl get module <NAME>
$ kubectl get project <NAME>
$ kubectl get workspace <NAME>
```

Expand All @@ -114,6 +118,7 @@ If you encounter any issues with the Operator there are a number of ways how to
```console
$ kubectl describe agentpool <NAME>
$ kubectl describe module <NAME>
$ kubectl describe project <NAME>
$ kubectl describe workspace <NAME>
```

Expand Down
8 changes: 8 additions & 0 deletions api/v1alpha2/project_helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package v1alpha2

func (p *Project) IsCreationCandidate() bool {
return p.Status.ID == ""
}
39 changes: 39 additions & 0 deletions api/v1alpha2/project_helpers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package v1alpha2

import (
"testing"
)

const (
projectFinalizer = "project.app.terraform.io/finalizer"
)

func TestIsCreationCandidate(t *testing.T) {
t.Parallel()

cases := map[string]struct {
project Project
expected bool
}{
"HasID": {
Project{Status: ProjectStatus{ID: "prj-this"}},
false,
},
"DoesNotHaveID": {
Project{Status: ProjectStatus{ID: ""}},
true,
},
}

for n, c := range cases {
t.Run(n, func(t *testing.T) {
out := c.project.IsCreationCandidate()
if out != c.expected {
t.Fatalf("Error matching output and expected: %#v vs %#v", out, c.expected)
}
})
}
}
190 changes: 190 additions & 0 deletions api/v1alpha2/project_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package v1alpha2

import (
tfc "github.com/hashicorp/go-tfe"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// Custom permissions let you assign specific, finer-grained permissions to a team than the broader fixed permission sets provide.
// More information:
// - https://developer.hashicorp.com/terraform/cloud-docs/users-teams-organizations/permissions#custom-project-permissions
// - https://developer.hashicorp.com/terraform/cloud-docs/users-teams-organizations/permissions#general-workspace-permissions
type CustomProjectPermissions struct {
// Project access.
// Must be one of the following values: `delete`, `read`, `update`.
// Default: `read`.
//
//+kubebuilder:validation:Enum:=delete;read;update
//+kubebuilder:default:=read
//+optional
ProjectAccess tfc.ProjectSettingsPermissionType `json:"projectAccess,omitempty"`
// Team management.
// Must be one of the following values: `manage`, `none`, `read`.
// Default: `none`.
//
//+kubebuilder:validation:Enum:=manage;none;read
//+kubebuilder:default:=none
//+optional
TeamManagement tfc.ProjectTeamsPermissionType `json:"teamManagement,omitempty"`
// Allow users to create workspaces in the project.
// This grants read access to all workspaces in the project.
// Default: `false`.
//
//+kubebuilder:default:=false
//+optional
CreateWorkspace bool `json:"createWorkspace,omitempty"`
// Allows users to delete workspaces in the project.
// Default: `false`.
//
//+kubebuilder:default:=false
//+optional
DeleteWorkspace bool `json:"deleteWorkspace,omitempty"`
// Allows users to move workspaces out of the project.
// A user must have this permission on both the source and destination project to successfully move a workspace from one project to another.
// Default: `false`.
//
//+kubebuilder:default:=false
//+optional
MoveWorkspace bool `json:"moveWorkspace,omitempty"`
// Allows users to manually lock the workspace to temporarily prevent runs.
// When a workspace's execution mode is set to "local", users must have this permission to perform local CLI runs using the workspace's state.
// Default: `false`.
//
//+kubebuilder:default:=false
//+optional
LockWorkspace bool `json:"lockWorkspace,omitempty"`
// Run access.
// Must be one of the following values: `apply`, `plan`, `read`.
// Default: `read`.
//
//+kubebuilder:validation:Enum:=apply;plan;read
//+kubebuilder:default:=read
//+optional
Runs tfc.WorkspaceRunsPermissionType `json:"runs,omitempty"`
// Manage Workspace Run Tasks.
// Default: `false`.
//
//+kubebuilder:validation:default:=false
//+optional
RunTasks bool `json:"runTasks,omitempty"`
// Download Sentinel mocks.
// Must be one of the following values: `none`, `read`.
// Default: `none`.
//
//+kubebuilder:validation:Enum:=none;read
//+kubebuilder:default:=none
//+optional
SentinelMocks tfc.WorkspaceSentinelMocksPermissionType `json:"sentinelMocks,omitempty"`
// State access.
// Must be one of the following values: `none`, `read`, `read-outputs`, `write`.
// Default: `none`.
//
//+kubebuilder:validation:Enum:=none;read;read-outputs;write
//+kubebuilder:default:=none
//+optional
StateVersions tfc.WorkspaceStateVersionsPermissionType `json:"stateVersions,omitempty"`
// Variable access.
// Must be one of the following values: `none`, `read`, `write`.
// Default: `none`.
//
//+kubebuilder:validation:Enum:=none;read;write
//+kubebuilder:default:=none
//+optional
Variables tfc.WorkspaceVariablesPermissionType `json:"variables,omitempty"`
}

// Terraform Cloud's access model is team-based. In order to perform an action within a Terraform Cloud organization,
// users must belong to a team that has been granted the appropriate permissions.
// You can assign project-specific permissions to teams.
// More information:
// - https://developer.hashicorp.com/terraform/cloud-docs/workspaces/organize-workspaces-with-projects#permissions
// - https://developer.hashicorp.com/terraform/cloud-docs/users-teams-organizations/permissions#project-permissions
type ProjectTeamAccess struct {
// Team to grant access.
// More information:
// - https://developer.hashicorp.com/terraform/cloud-docs/users-teams-organizations/teams
Team Team `json:"team"`
// There are two ways to choose which permissions a given team has on a project: fixed permission sets, and custom permissions.
// Must be one of the following values: `admin`, `custom`, `maintain`, `read`, `write`.
// More information:
// - https://developer.hashicorp.com/terraform/cloud-docs/users-teams-organizations/permissions#project-permissions
// - https://developer.hashicorp.com/terraform/cloud-docs/users-teams-organizations/permissions#general-project-permissions
//
//+kubebuilder:validation:Enum:=admin;custom;maintain;read;write
Access tfc.TeamProjectAccessType `json:"access"`
// Custom permissions let you assign specific, finer-grained permissions to a team than the broader fixed permission sets provide.
// More information:
// - https://developer.hashicorp.com/terraform/cloud-docs/users-teams-organizations/permissions#custom-project-permissions
//
//+optional
Custom *CustomProjectPermissions `json:"custom,omitempty"`
}

// ProjectSpec defines the desired state of Project.
// More information:
// - https://developer.hashicorp.com/terraform/cloud-docs/workspaces/organize-workspaces-with-projects
type ProjectSpec struct {
// Organization name where the Workspace will be created.
// More information:
// - https://developer.hashicorp.com/terraform/cloud-docs/users-teams-organizations/organizations
//
//+kubebuilder:validation:MinLength:=1
Organization string `json:"organization"`
// API Token to be used for API calls.
Token Token `json:"token"`
// Name of the Project.
//
//+kubebuilder:validation:MinLength:=1
Name string `json:"name"`

// Terraform Cloud's access model is team-based. In order to perform an action within a Terraform Cloud organization,
// users must belong to a team that has been granted the appropriate permissions.
// You can assign project-specific permissions to teams.
// More information:
// - https://developer.hashicorp.com/terraform/cloud-docs/workspaces/organize-workspaces-with-projects#permissions
// - https://developer.hashicorp.com/terraform/cloud-docs/users-teams-organizations/permissions#project-permissions
//
//+kubebuilder:validation:MinItems:=1
//+optional
TeamAccess []*ProjectTeamAccess `json:"teamAccess,omitempty"`
}

// ProjectStatus defines the observed state of Project.
type ProjectStatus struct {
// Real world state generation.
ObservedGeneration int64 `json:"observedGeneration"`
// Project ID.
ID string `json:"id"`
// Project name.
Name string `json:"name"`
}

//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
//+kubebuilder:printcolumn:name="Project Name",type=string,JSONPath=`.status.name`
//+kubebuilder:printcolumn:name="Project ID",type=string,JSONPath=`.status.id`

// Project is the Schema for the projects API
type Project struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec ProjectSpec `json:"spec"`
Status ProjectStatus `json:"status,omitempty"`
}

//+kubebuilder:object:root=true

// ProjectList contains a list of Project
type ProjectList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []Project `json:"items"`
}

func init() {
SchemeBuilder.Register(&Project{}, &ProjectList{})
}
Loading