Skip to content

Commit

Permalink
pipeline run improvements
Browse files Browse the repository at this point in the history
* command is a string array
* rename variables to env and value to configRef
* pass ctx and handle signals

Signed-off-by: Gerd Oberlechner <[email protected]>
  • Loading branch information
geoberle committed Nov 14, 2024
1 parent 7443b78 commit 2029e10
Show file tree
Hide file tree
Showing 11 changed files with 253 additions and 175 deletions.
4 changes: 4 additions & 0 deletions maestro/server/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ else
USE_DATABASE_SSL = disabled
endif

hi:
@echo "Hello, World!"
kubectl get ns

deploy:
kubectl create namespace maestro --dry-run=client -o json | kubectl apply -f -
ISTO_VERSION=$(shell az aks show -n ${AKS_NAME} -g ${SVC_RG} --query serviceMeshProfile.istio.revisions[-1] -o tsv) && \
Expand Down
23 changes: 12 additions & 11 deletions maestro/server/pipeline.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,27 @@ steps:
- name: deploy
subscription: {{ .serviceClusterSubscription }}
resourceGroup: {{ .serviceClusterRG }}
aksCluster: {{ .aksName }}
action:
type: Shell
command: "make deploy"
command: ["/bin/bash", "-c", "make hi"]
# we could infer the pwd from the location of this file and could avoid make -C
variables:
env:
- name: EVENTGRID_NAME
value: maestroEventgridName
configRef: maestroEventgridName
- name: REGION_RG
value: regionRG
configRef: regionRG
- name: SVC_RG
value: serviceClusterRG
configRef: serviceClusterRG
- name: AKS_NAME
value: aksName
configRef: aksName
- name: IMAGE_BASE
value: maestroImageBase
configRef: maestroImageBase
- name: IMAGE_TAG
value: maestroImageTag
configRef: maestroImageTag
- name: USE_AZURE_DB
value: maestroPostgresDeploy
configRef: maestroPostgresDeploy
- name: ISTIO_RESTRICT_INGRESS
value: maestroRestrictIstioIngress
configRef: maestroRestrictIstioIngress
- name: KEYVAULT_NAME
value: maestroKeyVaultName
configRef: maestroKeyVaultName
17 changes: 12 additions & 5 deletions tooling/templatize/cmd/run/cmd.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package run

import (
"context"
"log"
"os"
"os/signal"
"syscall"

"github.com/spf13/cobra"
)
Expand All @@ -10,10 +14,13 @@ func NewCommand() *cobra.Command {
opts := DefaultOptions()
cmd := &cobra.Command{
Use: "run-pipeline",
Short: "run a pipeline.yaml file towards a target cluster or infrastructure",
Long: "run a pipeline.yaml file towards a target cluster or infrastructure",
Short: "run a pipeline.yaml file towards an Azure Resourcegroup / AKS cluster",
Long: "run a pipeline.yaml file towards an Azure Resourcegroup / AKS cluster",
RunE: func(cmd *cobra.Command, args []string) error {
return runPipeline(opts)
ctx, stop := signal.NotifyContext(cmd.Context(), os.Interrupt, syscall.SIGTERM)
defer stop()

return runPipeline(ctx, opts)
},
}
if err := BindOptions(opts, cmd); err != nil {
Expand All @@ -22,7 +29,7 @@ func NewCommand() *cobra.Command {
return cmd
}

func runPipeline(opts *RawRunOptions) error {
func runPipeline(ctx context.Context, opts *RawRunOptions) error {
validated, err := opts.Validate()
if err != nil {
return err
Expand All @@ -31,5 +38,5 @@ func runPipeline(opts *RawRunOptions) error {
if err != nil {
return err
}
return completed.RunPipeline()
return completed.RunPipeline(ctx)
}
11 changes: 6 additions & 5 deletions tooling/templatize/cmd/run/options.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package run

import (
"context"
"fmt"
"os"

Expand All @@ -22,9 +23,9 @@ func BindOptions(opts *RawRunOptions, cmd *cobra.Command) error {
if err != nil {
return fmt.Errorf("failed to bind options: %w", err)
}
cmd.Flags().StringVar(&opts.PipelineFile, "pipeline-config", opts.PipelineFile, "pipeline file path")
cmd.Flags().StringVar(&opts.PipelineFile, "pipeline-file", opts.PipelineFile, "pipeline file path")

for _, flag := range []string{"pipeline-config"} {
for _, flag := range []string{"pipeline-file"} {
if err := cmd.MarkFlagFilename(flag); err != nil {
return fmt.Errorf("failed to mark flag %q as a file: %w", flag, err)
}
Expand Down Expand Up @@ -87,7 +88,7 @@ func (o *ValidatedRunOptions) Complete() (*RunOptions, error) {
return nil, err
}

pipeline, err := pipeline.LoadPipeline(o.PipelineFile, completed.Config)
pipeline, err := pipeline.NewPipelineFromFile(o.PipelineFile, completed.Config)
if err != nil {
return nil, fmt.Errorf("failed to load pipeline file %s: %w", o.PipelineFile, err)
}
Expand All @@ -100,7 +101,7 @@ func (o *ValidatedRunOptions) Complete() (*RunOptions, error) {
}, nil
}

func (o *RunOptions) RunPipeline() error {
func (o *RunOptions) RunPipeline(ctx context.Context) error {
variables, err := o.RolloutOptions.Options.ConfigProvider.GetVariables(
o.RolloutOptions.Cloud,
o.RolloutOptions.DeployEnv,
Expand All @@ -114,5 +115,5 @@ func (o *RunOptions) RunPipeline() error {
if err != nil {
return err
}
return o.Pipeline.Run(variables)
return o.Pipeline.Run(ctx, variables)
}
3 changes: 2 additions & 1 deletion tooling/templatize/pkg/ev2/mapping_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ package ev2
import (
"testing"

"github.com/Azure/ARO-HCP/tooling/templatize/pkg/config"
"github.com/google/go-cmp/cmp"

"github.com/Azure/ARO-HCP/tooling/templatize/pkg/config"
)

func TestMapping(t *testing.T) {
Expand Down
103 changes: 103 additions & 0 deletions tooling/templatize/pkg/pipeline/executiontarget.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package pipeline

import (
"context"
"fmt"
"os"
"os/exec"

"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions"
)

func lookupSubscriptionID(ctx context.Context, subscriptionName string) (string, error) {
// Create a new Azure identity client
cred, err := azidentity.NewDefaultAzureCredential(nil)
if err != nil {
return "", fmt.Errorf("failed to obtain a credential: %v", err)
}

// Create a new subscriptions client
client, err := armsubscriptions.NewClient(cred, nil)
if err != nil {
return "", fmt.Errorf("failed to create subscriptions client: %v", err)
}

// List subscriptions and find the one with the matching name
pager := client.NewListPager(nil)
for pager.More() {
page, err := pager.NextPage(ctx)
if err != nil {
return "", fmt.Errorf("failed to get next page of subscriptions: %v", err)
}
for _, sub := range page.Value {
if *sub.DisplayName == subscriptionName {
return *sub.SubscriptionID, nil
}
}
}

return "", fmt.Errorf("subscription with name %q not found", subscriptionName)
}

type StepExecutionTarget struct {
SubscriptionName string
SubscriptionID string
ResourceGroup string
AKSClusterName string
}

func (target *StepExecutionTarget) KubeConfig(ctx context.Context) (string, error) {
if target.AKSClusterName == "" {
return "", fmt.Errorf("AKSClusterName is required to build a kubeconfig")
}

// Create a new Azure identity client
cred, err := azidentity.NewDefaultAzureCredential(nil)
if err != nil {
return "", fmt.Errorf("failed to obtain a credential: %v", err)
}

// Create a new AKS client
client, err := armcontainerservice.NewManagedClustersClient(target.SubscriptionID, cred, nil)
if err != nil {
return "", fmt.Errorf("failed to create AKS client: %v", err)
}

// Get the cluster access credentials
resp, err := client.ListClusterUserCredentials(ctx, target.ResourceGroup, target.AKSClusterName, nil)
if err != nil {
return "", fmt.Errorf("failed to get cluster access credentials: %v", err)
}
if len(resp.Kubeconfigs) == 0 {
return "", fmt.Errorf("no kubeconfig found")
}
kubeconfigContent := resp.Kubeconfigs[0].Value

// store the kubeconfig content into a temporary file
// generate a unique temporary filename
tmpfile, err := os.CreateTemp("", "kubeconfig-*.yaml")
if err != nil {
return "", fmt.Errorf("failed to create temporary file for kubeconfig: %v", err)
}
defer tmpfile.Close()

// store the kubeconfig content into the temporary file
if _, err := tmpfile.Write([]byte(kubeconfigContent)); err != nil {
return "", fmt.Errorf("failed to write to temporary kubeconfigfile %s: %v", tmpfile.Name(), err)
}

// Run kubelogin to transform the kubeconfig
cmd := exec.CommandContext(ctx, "kubelogin", "convert-kubeconfig", "-l", "azurecli", "--kubeconfig", tmpfile.Name())
output, err := cmd.CombinedOutput()
if err != nil {
return "", fmt.Errorf("failed to run kubelogin: %s %v", output, err)
}

return tmpfile.Name(), nil
}

func (target *StepExecutionTarget) Name() string {
return fmt.Sprintf("Subscription: %s (%s) / RG: %s / AKS: %s", target.SubscriptionName, target.SubscriptionID, target.ResourceGroup, target.AKSClusterName)
}
Loading

0 comments on commit 2029e10

Please sign in to comment.