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 hypershift-agent-automation cli application #3

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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
9 changes: 8 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
# Go workspace file
go.work


# editor and IDE paraphernalia
.idea
*.swp
Expand All @@ -33,3 +32,11 @@ go.work
/kubeconfig
.dockerignore
.docker

*.yaml
*.iso

bin/

env.sh
.hypershift*

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing new line.

14 changes: 14 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
GO_GCFLAGS ?= -gcflags=all='-N -l'
GO=GO111MODULE=on go
GO_BUILD_RECIPE=CGO_ENABLED=0 $(GO) build $(GO_GCFLAGS)

OUT_DIR ?= bin

all: build

.PHONY: build
build:
$(GO_BUILD_RECIPE) -o $(OUT_DIR)/hypershift-agent-automation .

clean:
rm -rf $(OUT_DIR)/*
98 changes: 97 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,97 @@
# hypershift-agent-automation
# Hypershift Agent Automation

Cli tool to create and destroy agent based hypershift hosted cluster on PowerVC platform.

## Setup:
This tool is designed only to create and destroy the agent cluster.

### Pre-Req:
- **Management Cluster** - An OCP cluster which will be used to host the agent based hosted cluster. Only x86 type of management cluster is supported as of now. Need to set up below things in management cluster.
- **MCE** - Refer this [link](https://github.com/hypershift-on-power/hack/wiki/Agent-based-Hosted-Cluster-on-PowerVM-using-MCE-with-Assisted-Service-and-Hypershift#install-the-mce-operator) to install the MCE operator.
- **AgentServiceConfig** - Refer this [link](https://github.com/hypershift-on-power/hack/wiki/Agent-based-Hosted-Cluster-on-PowerVM-using-MCE-with-Assisted-Service-and-Hypershift#create-agentserviceconfig) to configure agentserviceconfig.
- A valid [pull secret](https://cloud.redhat.com/openshift/install/aws/installer-provisioned) file.
- The OpenShift CLI (oc) or Kubernetes CLI (kubectl).
- **Hypershift**
```shell
git clone https://github.com/openshift/hypershift.git
cd hypershift
make build
sudo install -m 0755 bin/hypershift /usr/local/bin/hypershift
```
- **Hypershift Agent Automation**
```shell
git clone https://github.com/ppc64le-cloud/hypershift-agent-automation
cd hypershift-agent-automation
make build
sudo install -m 0755 bin/hypershift-agent-automation /usr/local/bin/hypershift-agent-automation
```

### Infra:
Need to set below env vars to connect HMC, VIOS and PowerVC.

```shell
# To get authenticated with PowerVC(OpenStack Client)
export OS_USERNAME=''
export OS_PASSWORD=''
export OS_IDENTITY_API_VERSION=''
export OS_AUTH_URL=''
export OS_CACERT=''
export OS_REGION_NAME=''
export OS_PROJECT_DOMAIN_NAME=''
export OS_PROJECT_NAME=''
export OS_TENANT_NAME=''
export OS_USER_DOMAIN_NAME=''

# Required PowerVC resource names
export POWERVC_STORAGE_TEMPLATE=''
export POWERVC_HOST=''
export POWERVC_NETWORK_NAME=''

# HMC details
export HMC_IP=''
export HMC_USERNAME=''
export HMC_PASSWORD=''

# VIOS details
export VIOS_IP=''
export VIOS_USERNAME=''
export VIOS_PASSWORD=''
export VIOS_HOMEDIR=''
```



## Commands:

### Create Agent Cluster:
```shell
hypershift-agent-automation cluster create \
--name $CLUSTER_NAME \
--base-domain $BASE_DOMAIN \
--pull-secret $PULL_SECRET \
--release-image $RELEASE_IMAGE \
--ssh-key $SSH_KEY_FILE \
--node-count $NODE_COUNT
```

### Destroy Agent Cluster:
```shell
hypershift-agent-automation cluster destroy \
--name $CLUSTER_NAME \
--base-domain $BASE_DOMAIN \
--pull-secret $PULL_SECRET \
--release-image $RELEASE_IMAGE \
--ssh-key $SSH_KEY_FILE \
--node-count $NODE_COUNT
```

### Running e2e:
```shell
hypershift-agent-automation e2e \
--name $CLUSTER_NAME \
--base-domain $BASE_DOMAIN \
--pull-secret $PULL_SECRET \
--release-image $RELEASE_IMAGE \
--ssh-key $SSH_KEY_FILE \
--node-count $NODE_COUNT
```
22 changes: 22 additions & 0 deletions cmd/cluster/cluster.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package cluster

import (
"github.com/spf13/cobra"

"github.com/ppc64le-cloud/hypershift-agent-automation/cmd/cluster/create"
"github.com/ppc64le-cloud/hypershift-agent-automation/cmd/cluster/destroy"
"github.com/ppc64le-cloud/hypershift-agent-automation/cmd/options"
)

func Command(opts *options.ClusterOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "cluster",
Short: "Commands to interact with hypershift agent cluster",
SilenceUsage: true,
}

cmd.AddCommand(create.Command(opts))
cmd.AddCommand(destroy.Command(opts))

return cmd
}
152 changes: 152 additions & 0 deletions cmd/cluster/create/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
package create

import (
"fmt"
"os"

"github.com/spf13/cobra"

"github.com/ppc64le-cloud/hypershift-agent-automation/cmd/options"
cmdUtil "github.com/ppc64le-cloud/hypershift-agent-automation/cmd/util"
"github.com/ppc64le-cloud/hypershift-agent-automation/log"
"github.com/ppc64le-cloud/hypershift-agent-automation/pkg/cluster"
"github.com/ppc64le-cloud/hypershift-agent-automation/util"
)

func SetupPreReq(c *cluster.Cluster) (string, string, string, int, error) {
volumeID, err := c.PowerVC.SetupEmptyBootVol(c.Name)
if err != nil {
log.Logger.Errorf("error setup empty boot volume: %v", err)
return "", "", "", -1, fmt.Errorf("error setup empty boot volume: %v", err)
}
log.Logger.Infof("%s volume id will be used", volumeID)

imageID, err := c.PowerVC.SetupPreReqImage(c.Name, volumeID)
if err != nil {
log.Logger.Errorf("error setup image %v", err)
return "", "", "", -1, fmt.Errorf("error setup image: %v", err)
}
log.Logger.Infof("%s image id will be used", imageID)

if err = c.PowerVC.SetupFlavor(c.Name); err != nil {
log.Logger.Errorf("error setup flavor: %v", err)
return "", "", "", -1, fmt.Errorf("error setup flavor: %v", err)
}
log.Logger.Infof("%s flavor id will be used", util.GenerateFlavourID(c.Name))

networkID, gatewayIP, prefix, err := c.PowerVC.GetNetworkID()
if err != nil {
log.Logger.Errorf("unable to retrieve id for network, error: %v", err)
return "", "", "", -1, fmt.Errorf("unable to retrieve id for network, error: %v", err)
}
log.Logger.Infof("%s network id will be used", networkID)

return imageID, networkID, gatewayIP, prefix, nil
}

func SetupCluster(c *cluster.Cluster, imageID, networkID, gatewayIP string, prefix int) error {
agents, err := c.PowerVC.SetupAgents(c.GetWorkerName(), imageID, networkID, util.GenerateFlavourID(c.Name), c.NodeCount)
if err != nil {
return fmt.Errorf("error setup agents: %v", err)
}
log.Logger.Infof("agent setup done. agent details: %+v", agents)

nmStateLabel := fmt.Sprintf("label: nmstate-config-%s", c.Name)
if err = os.Mkdir(util.GetManifestDir(c.Name), 0750); err != nil && !os.IsExist(err) {
log.Logger.Error("error creating output dir for manifests", err)
}
if err = c.SetupHC(); err != nil {
return fmt.Errorf("error setup hosted cluster: %v", err)
}
log.Logger.Info("hosted cluster setup done")
if err = c.SetupNMStateConfig(agents, prefix, gatewayIP, nmStateLabel); err != nil {
return fmt.Errorf("error setup nmstate config: %v", err)
}
log.Logger.Info("nmstate config setup done")

if err = c.SetupInfraEnv(nmStateLabel); err != nil {
return fmt.Errorf("error setup infraenv: %v", err)
}
log.Logger.Info("infraenv setup done")

if err = c.DownloadISO(); err != nil {
return fmt.Errorf("error download iso: %v", err)
}
log.Logger.Info("download discovery iso done")

if err = c.CopyAndMountISO(agents); err != nil {
return fmt.Errorf("error copy iso: %v", err)
}
log.Logger.Info("mount iso on agents done")

if err = c.SetupCISDNSRecords(agents[0].IP); err != nil {
return fmt.Errorf("error update cis dns records: %v", err)
}
log.Logger.Info("update cis dns records done")

if err = c.PowerVC.RestartAgents(agents); err != nil {
return fmt.Errorf("error restarting vm: %v", err)
}
log.Logger.Info("agents restarted")

if err = c.ApproveAgents(agents); err != nil {
return err
}
log.Logger.Info("agents approved")

if err = c.ScaleNodePool(); err != nil {
return err
}
log.Logger.Info("node pool scaled")

if err = c.DownloadKubeConfig(); err != nil {
return fmt.Errorf("error downloading kubeconfig: %v", err)
}
log.Logger.Info("kubeconfig downloaded")

if err = c.SetupIngressControllerNodeSelector(agents[0].Name); err != nil {
return err
}
log.Logger.Info("ingress controller patched to run on first agent")

log.Logger.Info("waiting for hosted cluster to reach completed state")
if err = c.MonitorHC(); err != nil {
return fmt.Errorf("error monitor hosted cluster to reach completed state: %v", err)
}
log.Logger.Info("hosted cluster reached completed state")

return nil
}

func Command(opts *options.ClusterOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "create",
Short: "Command to create a hypershift agent cluster",
SilenceUsage: true,
}

cmd.RunE = func(_ *cobra.Command, args []string) error {
if err := cmdUtil.ValidateCliOptions(opts); err != nil {
return err
}

c, err := cmdUtil.CreateClusterClient(opts)
if err != nil {
return fmt.Errorf("error create clients: %v", err)
}
imageID, networkID, gatewayIP, prefix, err := SetupPreReq(c)
if err != nil {
return fmt.Errorf("error setup pre req: %v", err)
}
log.Logger.Infof("retrieved prereq resource info imageID: %s, networkID: %s, gatewayIP: %s, prefix: %d", imageID, networkID, gatewayIP, prefix)

if err = SetupCluster(c, imageID, networkID, gatewayIP, prefix); err != nil {
return fmt.Errorf("error setup cluster: %v", err)
}
log.Logger.Info("setup cluster done")

return nil
}

return cmd
}
Loading