Skip to content

Commit

Permalink
extbldr: added mock subcommand with basic options
Browse files Browse the repository at this point in the history
added mock subcommand to build RPM from SRPMs. This internally calls the
mock tool to build the RPM in the architecture specified.
works with default config as of now. quiet option added for mock
  • Loading branch information
shyammohan-arista committed Sep 2, 2022
1 parent f531a48 commit e415af0
Show file tree
Hide file tree
Showing 5 changed files with 231 additions and 1 deletion.
23 changes: 22 additions & 1 deletion .github/workflows/extbldr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ on: # yamllint disable-line rule:truthy
branches:
- 'main'

env:
TEST_TAG: extbldr:test

jobs:
gobuild:
name: Go lint and build
Expand Down Expand Up @@ -56,7 +59,7 @@ jobs:
- name: Setup buildx with docker-container driver
uses: docker/setup-buildx-action@v2

- name: Docker build
- name: Docker build and test privileged
uses: docker/build-push-action@v3
with:
# Dockerfile is within subdirectory
Expand All @@ -66,6 +69,24 @@ jobs:
secrets: |
GIT_AUTH_TOKEN=${{ secrets.GITHUB_TOKEN }}
load: true
tags: ${{ env.TEST_TAG }}
target: builder
- name: Test privileged
run: |
docker run --rm --cap-add SYS_ADMIN \
${{ env.TEST_TAG }} sh -c 'go test ./... -tags=privileged'
- name: Dockerfile build without publish
uses: docker/build-push-action@v3
with:
# Dockerfile is within subdirectory
context: "{{defaultContext}}:extbldr"

# GIT_AUTH_TOKEN is unset for non-default context
secrets: |
GIT_AUTH_TOKEN=${{ secrets.GITHUB_TOKEN }}
# Publish is done by Arista docker-library to push to on-prem registry
# This just checks the docker build and can work off-prem.
target: deploy
push: false
44 changes: 44 additions & 0 deletions extbldr/cmd/mock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (c) 2022 Arista Networks, Inc. All rights reserved.
// Arista Networks, Inc. Confidential and Proprietary.

package cmd

import (
"github.com/spf13/cobra"

"extbldr/impl"
)

var arch string

// mockcmd represents the mock command
var mockcmd = &cobra.Command{
Use: "mock -t <Arch> -p <Package>",
Short: "Use mock to build the RPM from the SRPM",
Long: `The RPM for the specified architecture is built from the specified SRPM package in /var/extbldr/<Packagename>/rpmbuild/SRPMs and placed inside /var/extbldr/<Packagename>/RPM.
The local directory is <BASE_PATH>/<package>.
<BASE_PATH> is specified by the SrcDir configuration or the EXTBLDR_SRCDIR env var.`,
Args: func(cmd *cobra.Command, args []string) error {
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
pkg, _ := cmd.Flags().GetString("package")
err := impl.Mock(arch, pkg)
return err
},
}

func init() {
mockcmd.Flags().StringVarP(&arch, "target", "t", "", "target architecture for the rpm")
rootCmd.AddCommand(mockcmd)

// Here you will define your flags and configuration settings.

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// cloneCmd.PersistentFlags().String("foo", "", "A help for foo")

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// cloneCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
81 changes: 81 additions & 0 deletions extbldr/cmd/mock_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright (c) 2022 Arista Networks, Inc. All rights reserved.
// Arista Networks, Inc. Confidential and Proprietary.

//go:build privileged
// +build privileged

package cmd

import (
"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
"io/ioutil"
"os"
"path/filepath"
"testing"
)

func testMock(t *testing.T, workingDir string, pkgName string, quiet bool) {
viper.Set("WorkingDir", workingDir)
defer viper.Reset()
args := []string{"mock", "--target", "x86_64", "--package", pkgName}
rescueStdout := os.Stdout
r, w, _ := os.Pipe()
if quiet {
args = append(args, "--quiet")
os.Stdout = w
}
rootCmd.SetArgs(args)

cmdErr := rootCmd.Execute()
assert.NoError(t, cmdErr)

if quiet {
w.Close()
out, err := ioutil.ReadAll(r)
if err != nil {
t.Fatal(err)
}
assert.Empty(t, out)
os.Stdout = rescueStdout
}
}

func TestMock(t *testing.T) {
t.Log("Create temporary working directory")

workingDir, err := os.MkdirTemp("", "mock-test")
if err != nil {
t.Fatal(err)
}
srpmpath := filepath.Join(workingDir, "debugedit-1", "rpmbuild", "SRPMs")
err = os.MkdirAll(srpmpath, os.ModePerm)
if err != nil {
t.Fatal(err)
}

sampleSRPMPath := filepath.Join("testData", "mock-1", "debugedit-5.0-3.el9.src.rpm")
_, statErr := os.Stat(sampleSRPMPath)
if statErr != nil {
t.Fatal(statErr)
}

targetPath, absErr := filepath.Abs(sampleSRPMPath)
if absErr != nil {
t.Fatal(absErr)
}
linkPath := filepath.Join(srpmpath, "debugedit-5.0-3.el9.src.rpm")
symlinkErr := os.Symlink(targetPath, linkPath)
if symlinkErr != nil {
t.Fatal(symlinkErr)
}

defer os.RemoveAll(workingDir)
baseName := "debugedit-1"
t.Logf("WorkingDir: %s", workingDir)
t.Log("Test mock from SRPM")
testMock(t, workingDir, baseName, false)

t.Log("Test mock from SRPM quiet")
testMock(t, workingDir, baseName, true)
}
Binary file not shown.
84 changes: 84 additions & 0 deletions extbldr/impl/mock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright (c) 2022 Arista Networks, Inc. All rights reserved.
// Arista Networks, Inc. Confidential and Proprietary.

package impl

import (
"extbldr/util"
"fmt"
"github.com/spf13/viper"
"os"
"path/filepath"
"regexp"
)

// type can take SRPM or RPM
func getRpmFileNamesFromDir(dirPath string, rpmType string) ([]string, error) {
var rpmFileNames []string
files, err := os.ReadDir(dirPath)
if err != nil {
return rpmFileNames, fmt.Errorf("impl.Mock: os.ReadDir returned %v", err)
}

rpmRegex, _ := regexp.Compile("(?i).*[^(\\.src)]\\.rpm")
srpmRegex, _ := regexp.Compile("(?i).*\\.src\\.rpm")
var matchRegex *regexp.Regexp
if rpmType == "SRPM" {
matchRegex = srpmRegex
} else if rpmType == "RPM" {
matchRegex = rpmRegex
} else {
return rpmFileNames, fmt.Errorf("impl.Mock: unknown type: %s", rpmType)
}
var matched bool
for _, file := range files {
matched = matchRegex.MatchString(file.Name())
if matched {
rpmFileNames = append(rpmFileNames, file.Name())
}
}
return rpmFileNames, nil
}

// Mock builds the RPM in specified architecture and
// copies it to /var/extbldr/<pkg>/RPM
func Mock(arch string, pkg string) error {
baseDir := viper.GetString("WorkingDir")
srpmPath := filepath.Join(baseDir, pkg, "rpmbuild", "SRPMs")
srpmName, srpmerr := getRpmFileNamesFromDir(srpmPath, "SRPM")
if srpmerr != nil {
return fmt.Errorf("impl.Mock: reading SRPMs errored out with %s", srpmerr)
}
srpmFullPath := filepath.Join(srpmPath, srpmName[0]) ////expecting single file

targetArg := "--target=" + arch

var mockErr error
if util.GlobalVar.Quiet {
mockErr = util.RunSystemCmd("mock", "--quiet", targetArg, srpmFullPath)
} else {
mockErr = util.RunSystemCmd("mock", targetArg, srpmFullPath)
}
if mockErr != nil {
return fmt.Errorf("impl.Mock:36: mock on %s to arch %s errored out with %s",
pkg, arch, mockErr)
}

rpmPath := filepath.Join(baseDir, pkg, "RPM")
creatErr := util.MaybeCreateDir("impl.mock", rpmPath)
if creatErr != nil {
return fmt.Errorf("impl.Mock: Creating %s errored out with %s", rpmPath, creatErr)
}
mockResultPath := "/var/lib/mock/rocky+epel-9-x86_64/result/" //hardcoded path will change with config option addition
rpmFiles, rpmerr := getRpmFileNamesFromDir(mockResultPath, "RPM")
if rpmerr != nil {
return fmt.Errorf("impl.Mock: reading RPMs errored out with %s", rpmerr)
}
for _, file := range rpmFiles {
mockErr = util.RunSystemCmd("mv", "-f", filepath.Join(mockResultPath, file), rpmPath)
if mockErr != nil {
return fmt.Errorf("impl.Mock: move rpm file errored out with %s", mockErr)
}
}
return nil
}

0 comments on commit e415af0

Please sign in to comment.