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 6, 2022
1 parent f531a48 commit efcf64a
Show file tree
Hide file tree
Showing 5 changed files with 241 additions and 0 deletions.
21 changes: 21 additions & 0 deletions .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 @@ -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 --privileged \
${{ 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
29 changes: 29 additions & 0 deletions extbldr/cmd/mock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// 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

var mockcmd = &cobra.Command{
Use: "mock -t <Arch> -p <Package>",
Short: "Use mock to build the RPMS from the SRPMS built previously.",
Long: `Use mock to build The RPMS for the specified architecture from the specified SRPM package in <SrcDir>/<package>/rpmbuild/SRPMS and output placed inside <SrcDir>/<package>/RPM.`,
RunE: func(cmd *cobra.Command, args []string) error {
pkg, _ := cmd.Flags().GetString("package")
subpkg, _ := cmd.Flags().GetString("subpackage")
err := impl.Mock(arch, pkg, subpkg)
return err
},
}

func init() {
mockcmd.Flags().StringVarP(&arch, "target", "t", "", "target architecture for the RPM")
rootCmd.AddCommand(mockcmd)
}
82 changes: 82 additions & 0 deletions extbldr/cmd/mock_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Copyright (c) 2022 Arista Networks, Inc. All rights reserved.
// Arista Networks, Inc. Confidential and Proprietary.

//go:build privileged
// +build privileged

package cmd

import (
"io/ioutil"
"os"
"path/filepath"
"testing"

"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
)

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.
109 changes: 109 additions & 0 deletions extbldr/impl/mock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Copyright (c) 2022 Arista Networks, Inc. All rights reserved.
// Arista Networks, Inc. Confidential and Proprietary.

package impl

import (
"fmt"
"os"
"path/filepath"
"regexp"

"github.com/spf13/viper"

"extbldr/manifest"
"extbldr/util"
)

// type can take SRPM or RPM
func getRpmFileNamesFromDir(dirPath string, isSRPM bool) ([]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, err := regexp.Compile("(?i).*[^(\\.src)]\\.rpm")
if err != nil {
return rpmFileNames, fmt.Errorf("impl.Mock: regexp.compile for RPM returned %v", err)
}
srpmRegex, err := regexp.Compile("(?i).*\\.src\\.rpm")
if err != nil {
return rpmFileNames, fmt.Errorf("impl.Mock: regexp.compile for SRPM returned %v", err)
}
var matchRegex *regexp.Regexp
if isSRPM {
matchRegex = srpmRegex
} else {
matchRegex = rpmRegex
}
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, subpkg string) error {
baseDir := viper.GetString("WorkingDir")
srpmPath := filepath.Join(baseDir, pkg, "rpmbuild", "SRPMs")
srpmName, srpmerr := getRpmFileNamesFromDir(srpmPath, true)
pkgManifest, loadManifestErr := manifest.LoadManifest(pkg)
if loadManifestErr != nil {
return loadManifestErr
}
var subPkgSpecified bool = (subpkg != "")
//found := !subPkgSpecified
for _, subPkgSpec := range pkgManifest.SubPackage {
thisSubPkgName := subPkgSpec.Name
if subPkgSpecified && (subpkg != thisSubPkgName) {
continue
}
subPkgErr := Mock(arch, subpkg, "")
if subPkgErr != nil {
return fmt.Errorf("impl.Mock: subpkg %s mock errored out %s", subpkg, subPkgErr)
}
}

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
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)
}

var mockErr error
if util.GlobalVar.Quiet {
mockErr = util.RunSystemCmd("mock", "--quiet", fmt.Sprintf("--resultdir=%s", rpmPath), targetArg, srpmFullPath)
} else {
mockErr = util.RunSystemCmd("mock", fmt.Sprintf("--resultdir=%s", rpmPath), targetArg, srpmFullPath)
}
if mockErr != nil {
return fmt.Errorf("impl.Mock: mock on %s to arch %s errored out with %s",
pkg, arch, mockErr)
}
//TBD : remove srpm from mresultdir and move out logs
/* mockResultPath := "/var/lib/mock/rocky+epel-9-x86_64/result/" //hardcoded path will change with config option addition
rpmFiles, rpmerr := getRpmFileNamesFromDir(mockResultPath, false)
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 efcf64a

Please sign in to comment.