Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/harbor/root/project/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func Project() *cobra.Command {
SearchProjectCommand(),
Robot(),
Member(),
Preheat(),
)

return cmd
Expand Down
37 changes: 37 additions & 0 deletions cmd/harbor/root/project/preheat.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright Project Harbor Authors
//
// 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.
package project

import (
"github.com/goharbor/harbor-cli/cmd/harbor/root/project/preheat"
"github.com/spf13/cobra"
)

func Preheat() *cobra.Command {
cmd := &cobra.Command{
Use: "preheat",
Aliases: []string{"p2p"},
Short: "Manage project preheat resources",
Long: "Manage project-scoped P2P preheat policies, executions, and tasks in Harbor",
Example: ` harbor project preheat policy list [PROJECT_NAME]
harbor project preheat policy list [PROJECT_ID] --id
harbor project preheat policy create -f [CONFIG_FILE]
harbor project preheat policy start [PROJECT_NAME] [POLICY_NAME]`,
}
cmd.AddCommand(
preheat.PolicyCommand(),
)

return cmd
}
44 changes: 44 additions & 0 deletions cmd/harbor/root/project/preheat/policy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright Project Harbor Authors
//
// 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.
package preheat

import (
"github.com/goharbor/harbor-cli/cmd/harbor/root/project/preheat/policy"
"github.com/spf13/cobra"
)

func PolicyCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "policy",
Aliases: []string{"pol"},
Short: "Manage preheat policies",
Long: "Manage P2P preheat policies under a project",
Example: ` harbor project preheat policy list [PROJECT_NAME]
harbor project preheat policy list [PROJECT_ID] --id
harbor project preheat policy create -f [CONFIG_FILE]
harbor project preheat policy view [PROJECT_NAME] [POLICY_NAME]
harbor project preheat policy start [PROJECT_NAME] [POLICY_NAME]`,
}

cmd.AddCommand(
policy.ListPolicyCommand(),
policy.ViewPolicyCommand(),
policy.CreatePolicyCommand(),
policy.UpdatePolicyCommand(),
policy.DeletePolicyCommand(),
policy.StartPolicyCommand(),
)

return cmd
}
194 changes: 194 additions & 0 deletions cmd/harbor/root/project/preheat/policy/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
// Copyright Project Harbor Authors
//
// 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.
package policy

import (
"encoding/json"
"fmt"

"github.com/goharbor/go-client/pkg/sdk/v2.0/models"
"github.com/goharbor/harbor-cli/pkg/api"
config "github.com/goharbor/harbor-cli/pkg/config/preheat"
"github.com/goharbor/harbor-cli/pkg/prompt"
"github.com/goharbor/harbor-cli/pkg/utils"
"github.com/goharbor/harbor-cli/pkg/views/preheat/policy/create"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

func CreatePolicyCommand() *cobra.Command {
var isID bool
var configFile string
var err error
var opts *create.CreateView

cmd := &cobra.Command{
Use: "create",
Short: "Create a preheat policy",
Long: "Create a new P2P preheat policy under a project",
Example: ` harbor project preheat policy create [PROJECT_NAME]
harbor project preheat policy create [PROJECT_ID] --id
harbor project preheat policy create -f [CONFIG_FILE]`,
Args: cobra.MaximumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
log.Debug("Starting preheat policy create command")

if configFile != "" {
if len(args) > 0 {
return fmt.Errorf("arguments are not supported with --policy-config-file")
}

log.Debugf("Loading preheat policy configuration from file: %s", configFile)
opts, err = config.LoadConfigFromFile(configFile)
if err != nil {
return fmt.Errorf("failed to load preheat policy configuration: %v", err)
}
} else {
opts = &create.CreateView{
Enabled: true,
}

if isID && len(args) == 0 {
return fmt.Errorf("project ID must be provided when using --id")
}

if len(args) > 0 {
log.Debugf("Project name provided: %s", args[0])
opts.ProjectName = args[0]
} else {
log.Debug("No project name provided, prompting user")
opts.ProjectName, err = prompt.GetProjectNameFromUser()
if err != nil {
return fmt.Errorf("failed to get project name: %v", utils.ParseHarborErrorMsg(err))
}
}

if isID {
project, err := api.GetProject(opts.ProjectName, true)
if err != nil {
if utils.ParseHarborErrorCode(err) == "404" {
return fmt.Errorf("project %s does not exist", opts.ProjectName)
}
return fmt.Errorf("failed to get project: %v", utils.ParseHarborErrorMsg(err))
}
opts.ProjectName = project.Payload.Name
}
}

_, err = api.GetProject(opts.ProjectName, false)
if err != nil {
if utils.ParseHarborErrorCode(err) == "404" {
return fmt.Errorf("project %s does not exist. If you entered a project ID, use --id", opts.ProjectName)
}
return fmt.Errorf("failed to verify project: %v", utils.ParseHarborErrorMsg(err))
}

log.Debug("Fetching available providers...")
providers, err := api.ListProvidersUnderProject(opts.ProjectName)
if err != nil {
return fmt.Errorf("failed to list providers: %v", utils.ParseHarborErrorMsg(err))
}

if len(providers) == 0 {
return fmt.Errorf("no P2P provider instances available for project '%s'. Please create a provider instance first", opts.ProjectName)
}

if configFile == "" {
create.CreatePreheatPolicyView(opts, providers)
}

providerID, err := resolveProviderID(providers, opts.ProviderName, opts.ProjectName)
if err != nil {
return err
}

policy, err := ConvertToPolicy(opts, providerID)
if err != nil {
return err
}

log.Debug("Creating preheat policy...")
response, err := api.CreatePreheatPolicy(opts.ProjectName, policy)
if err != nil {
if utils.ParseHarborErrorCode(err) == "409" {
return fmt.Errorf("preheat policy '%s' already exists in project '%s'", opts.Name, opts.ProjectName)
}
return fmt.Errorf("failed to create preheat policy: %v", utils.ParseHarborErrorMsg(err))
}

fmt.Println("Preheat policy created successfully with ID:", response.Location)
return nil
},
}

flags := cmd.Flags()
flags.BoolVar(&isID, "id", false, "Use project id instead of name")
flags.StringVarP(&configFile, "policy-config-file", "f", "", "YAML/JSON file with preheat policy configuration")

return cmd
}

func resolveProviderID(providers []*models.ProviderUnderProject, providerName, projectName string) (int64, error) {
for _, provider := range providers {
if provider.Provider == providerName && provider.Enabled {
return provider.ID, nil
}
}

return 0, fmt.Errorf("provider '%s' not found or not enabled for project '%s'", providerName, projectName)
}

func ConvertToPolicy(view *create.CreateView, providerID int64) (*models.PreheatPolicy, error) {
type filter struct {
Type string `json:"type"`
Value string `json:"value"`
}
filters := []filter{
{Type: "repository", Value: view.RepositoryFilter},
{Type: "tag", Value: view.TagFilter},
}
if view.LabelFilter != "" {
filters = append(filters, filter{Type: "label", Value: view.LabelFilter})
}
filtersJSON, err := json.Marshal(filters)
if err != nil {
return nil, fmt.Errorf("failed to marshal filters: %v", err)
}

type triggerSetting struct {
Cron string `json:"cron"`
}
type trigger struct {
Type string `json:"type"`
TriggerSetting *triggerSetting `json:"trigger_setting,omitempty"`
}
t := trigger{Type: view.TriggerType}
if view.TriggerType == "scheduled" {
t.TriggerSetting = &triggerSetting{Cron: view.CronString}
}
triggerJSON, err := json.Marshal(t)
if err != nil {
return nil, fmt.Errorf("failed to marshal trigger: %v", err)
}

return &models.PreheatPolicy{
Name: view.Name,
Description: view.Description,
ProviderID: providerID,
ProviderName: view.ProviderName,
Filters: string(filtersJSON),
Trigger: string(triggerJSON),
Enabled: view.Enabled,
}, nil
}
92 changes: 92 additions & 0 deletions cmd/harbor/root/project/preheat/policy/delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright Project Harbor Authors
//
// 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.
package policy

import (
"fmt"

"github.com/goharbor/harbor-cli/pkg/api"
"github.com/goharbor/harbor-cli/pkg/prompt"
"github.com/goharbor/harbor-cli/pkg/utils"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

func DeletePolicyCommand() *cobra.Command {
var isID bool

cmd := &cobra.Command{
Use: "delete",
Short: "Delete a preheat policy",
Long: "Delete a specific P2P preheat policy under a project",
Example: ` harbor project preheat policy delete [PROJECT_NAME] [POLICY_NAME]
harbor project preheat policy delete [PROJECT_ID] [POLICY_NAME] --id`,
Args: cobra.MaximumNArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
var err error
var projectName, policyName string

if isID && len(args) == 0 {
return fmt.Errorf("project ID must be provided when using --id")
}

if len(args) >= 1 {
log.Debugf("Project name provided: %s", args[0])
projectName = args[0]
} else {
log.Debug("No project name provided, prompting user")
projectName, err = prompt.GetProjectNameFromUser()
if err != nil {
return fmt.Errorf("failed to get project name: %v", utils.ParseHarborErrorMsg(err))
}
}

if isID {
project, err := api.GetProject(projectName, true)
if err != nil {
return fmt.Errorf("failed to resolve project ID: %v", utils.ParseHarborErrorMsg(err))
}
projectName = project.Payload.Name
}

if len(args) >= 2 {
log.Debugf("Policy name provided: %s", args[1])
policyName = args[1]
} else {
log.Debug("No policy name provided, prompting user")
policyName, err = prompt.GetPreheatPolicyNameFromUser(projectName)
if err != nil {
return fmt.Errorf("failed to get policy name: %v", utils.ParseHarborErrorMsg(err))
}
}

log.Debug("Deleting preheat policy...")
err = api.DeletePreheatPolicy(projectName, policyName)
if err != nil {
if utils.ParseHarborErrorCode(err) == "404" {
return fmt.Errorf("preheat policy %s not found in project %s", policyName, projectName)
}
return fmt.Errorf("failed to delete preheat policy: %v", utils.ParseHarborErrorMsg(err))
}

fmt.Printf("Preheat policy '%s' deleted successfully from project '%s'\n", policyName, projectName)
return nil
},
}

flags := cmd.Flags()
flags.BoolVar(&isID, "id", false, "Delete preheat policy by project id")

return cmd
}
Loading
Loading