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

extbldr: added mock subcommand with basic options #18

Merged
merged 1 commit into from
Sep 13, 2022
Merged
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
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
1 change: 1 addition & 0 deletions extbldr/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ COPY *.go ./
COPY cmd/ cmd/
COPY impl/ impl/
COPY util/ util/
COPY testutil/ testutil/
COPY manifest/ manifest/
RUN go build -o /home/extbldr-robot/bin/extbldr && \
go test ./... && \
Expand Down
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 <WorkingDir>/<package>/RPMS.`,
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)
}
75 changes: 75 additions & 0 deletions extbldr/cmd/mock_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// 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"
"testing"

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

func testMock(t *testing.T, pkgName string, quiet bool) {
/* viper.Set("WorkingDir", workingDir)
viper.Set("SrcDir", "testData")
args := []string{"createSrpm", "--package", pkgName}
rootCmd.SetArgs(args)

cmdErr := rootCmd.Execute()
assert.NoError(t, cmdErr)
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)
}
baseName := "mrtparse-1"
viper.Set("WorkingDir", workingDir)
viper.Set("SrcDir", "testData")
args := []string{"createSrpm", "--package", pkgName}
rootCmd.SetArgs(args)

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

defer os.RemoveAll(workingDir)

t.Logf("WorkingDir: %s", workingDir)
t.Log("Test mock from SRPM")
testMock(t, baseName, false)

t.Log("Test mock from SRPM quiet")
testMock(t, baseName, true)
}
25 changes: 0 additions & 25 deletions extbldr/cmd/testData/mrtparse-1/mrtparse.spec
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,6 @@ can be used to export routing protocol messages, state changes, and routing
information base contents, and is standardized in RFC6396. Programs like Quagga
/ Zebra, BIRD, OpenBGPD and PyRT can dump the MRT fotmat data.

%package -n python2-mrtparse
Summary: Tool for parsing routing information dump files in MRT format
BuildRequires: python2-devel
BuildRequires: python2-setuptools
%{?python_provide:%python_provide python2-mrtparse}
Provides: mrtparse = %{version}-%{release}
Obsoletes: mrtparse < %{version}-%{release}

%description -n python2-mrtparse
mrtprse is a module to read and analyze the MRT format data. The MRT format data
can be used to export routing protocol messages, state changes, and routing
information base contents, and is standardized in RFC6396. Programs like Quagga
/ Zebra, BIRD, OpenBGPD and PyRT can dump the MRT fotmat data.

%package -n python3-mrtparse
Summary: Tool for parsing routing information dump files in MRT format
BuildRequires: python3-devel
Expand All @@ -52,23 +38,12 @@ information base contents, and is standardized in RFC6396. Programs like Quagga
# } end Arista patches

%build
%py2_build
%py3_build

%install
%py2_install
%py3_install

%files -n python2-mrtparse
%license LICENSE
%doc README.rst
%{python2_sitelib}/mrtparse-%{version}-py%{python2_version}.egg-info
%{python2_sitelib}/mrtparse/__init__.py*
%{python2_sitelib}/mrtparse/base.py*
%{python2_sitelib}/mrtparse/params.py*

%files -n python3-mrtparse
%license LICENSE
%doc README.rst
%{python3_sitelib}/mrtparse-%{version}-py%{python3_version}.egg-info
%{python3_sitelib}/mrtparse/__init__.py*
Expand Down
103 changes: 103 additions & 0 deletions extbldr/impl/mock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright (c) 2022 Arista Networks, Inc. All rights reserved.
// Arista Networks, Inc. Confidential and Proprietary.

package impl

import (
"fmt"
"path/filepath"

"github.com/spf13/viper"

"extbldr/manifest"
"extbldr/util"
)

func mockSubPkg(arch string, pkg string) error {
var mockErr error
baseDir := viper.GetString("WorkingDir")

rpmPath := filepath.Join(baseDir, pkg, "RPMS")
logPath := filepath.Join(baseDir, pkg, "logs")
srpmPath := filepath.Join(baseDir, pkg, "rpmbuild", "SRPMS")
scratchPath := filepath.Join(baseDir, pkg, "scratch")

targetArg := "--target=" + arch

srpmName, srpmErr := util.GetMatchingFileNamesFromDir(srpmPath, "(?i).*\\.src\\.rpm")
if srpmErr != nil {
return fmt.Errorf("impl.mockSubPkg: *.src.rpm file not found in %s , error: %s", srpmPath, srpmErr)
}
srpmFullPath := filepath.Join(srpmPath, srpmName[0]) ////expecting single file

// cleanup RPM, logs, scratch from previous run
for _, path := range []string{rpmPath, logPath, scratchPath} {
cleanupErr := util.RunSystemCmd("rm", "-rf", path)
if cleanupErr != nil {
return fmt.Errorf("impl.mockSubPkg: cleanup %s errored out with %s", path, cleanupErr)
}
}

creatErr := util.MaybeCreateDir("impl.mockSubPkg", rpmPath)
if creatErr != nil {
return creatErr
}
var mockArgs []string

if util.GlobalVar.Quiet {
mockArgs = append(mockArgs, "--quiet")
}
mockArgs = append(mockArgs, fmt.Sprintf("--resultdir=%s", rpmPath), targetArg, srpmFullPath)

mockErr = util.RunSystemCmd("mock", mockArgs...)
if mockErr != nil {
return fmt.Errorf("impl.mockSubPkg: mock on %s to arch %s errored out with %s",
pkg, arch, mockErr)
}

// move out logs, srpm from resultdir to logs and scratch respectively
movePathMap := make(map[string]string)
movePathMap[scratchPath] = "(?i).*\\.src\\.rpm"
movePathMap[logPath] = "(?i).*\\.log"
moveErr := filterAndMove(movePathMap, rpmPath)
if moveErr != nil {
return moveErr
}

return nil
}

func filterAndMove(movePathMap map[string]string, srcPath string) error {
for destPath, regexStr := range movePathMap {
name, err := util.GetMatchingFileNamesFromDir(srcPath, regexStr)
if err == nil {
err = util.CopyFilesToDir(name, srcPath, destPath)
if err != nil {
return fmt.Errorf("impl.filterAndMove moving %s errored out with %s", name, err)
}
}
}
return nil
}

// Mock calls fedora mock to build the RPMS for the specified target
// from the already built SRPMs and places the results in {WorkingDir}/<pkg>/RPMS
func Mock(arch string, pkg string, subPkg string) error {
pkgManifest, loadManifestErr := manifest.LoadManifest(pkg)
if loadManifestErr != nil {
return loadManifestErr
}
var subPkgSpecified bool = (subPkg != "")
for _, subPkgSpec := range pkgManifest.SubPackage {
thisSubPkgName := subPkgSpec.Name
if subPkgSpecified && (subPkg != thisSubPkgName) {
continue
}
subPkgErr := mockSubPkg(arch, subPkgSpec.Name)
if subPkgErr != nil {
return fmt.Errorf("impl.Mock: subPkg %s mock errored out %s", subPkgSpec.Name, subPkgErr)
}
}

return nil
}
28 changes: 3 additions & 25 deletions extbldr/manifest/manifest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ package manifest
import (
"github.com/stretchr/testify/assert"
"os"
"path/filepath"
"testing"

"github.com/spf13/viper"

"extbldr/testutil"
)

func testLoad(t *testing.T, pkg string) {
Expand All @@ -18,29 +19,6 @@ func testLoad(t *testing.T, pkg string) {
assert.NotNil(t, manifest)
}

func setupManifest(t *testing.T, baseDir string, pkg string, sampleFile string) {
pkgDir := filepath.Join(baseDir, pkg)
os.RemoveAll(pkgDir)
os.Mkdir(pkgDir, 0775)

sampleManifestPath := filepath.Join("testData", sampleFile)
_, statErr := os.Stat(sampleManifestPath)
if statErr != nil {
t.Fatal(statErr)
}

targetPath, absErr := filepath.Abs(sampleManifestPath)
if absErr != nil {
t.Fatal(absErr)
}
linkPath := filepath.Join(pkgDir, "manifest.yml")
symlinkErr := os.Symlink(targetPath, linkPath)
if symlinkErr != nil {
t.Fatal(symlinkErr)
}

}

func TestManifest(t *testing.T) {
t.Log("Create temporary working directory")
dir, err := os.MkdirTemp("", "manifest-test")
Expand All @@ -53,7 +31,7 @@ func TestManifest(t *testing.T) {
defer viper.Reset()

t.Log("Copy sample manifest to test directory")
setupManifest(t, dir, "pkg1", "sampleManifest1.yml")
testutil.SetupManifest(t, dir, "pkg1", "sampleManifest1.yml")

t.Log("Testing Load")
testLoad(t, "pkg1")
Expand Down
34 changes: 34 additions & 0 deletions extbldr/testutil/testutil.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright (c) 2022 Arista Networks, Inc. All rights reserved.
// Arista Networks, Inc. Confidential and Proprietary.

package testutil

import (
"os"
"path/filepath"
"testing"
)

// SetupManifest used to setup a test manifest from testdata for manifest functionality testing
func SetupManifest(t *testing.T, baseDir string, pkg string, sampleFile string) {
pkgDir := filepath.Join(baseDir, pkg)
os.RemoveAll(pkgDir)
os.Mkdir(pkgDir, 0775)

sampleManifestPath := filepath.Join("testData", sampleFile)
_, statErr := os.Stat(sampleManifestPath)
if statErr != nil {
t.Fatal(statErr)
}

targetPath, absErr := filepath.Abs(sampleManifestPath)
if absErr != nil {
t.Fatal(absErr)
}
linkPath := filepath.Join(pkgDir, "manifest.yml")
symlinkErr := os.Symlink(targetPath, linkPath)
if symlinkErr != nil {
t.Fatal(symlinkErr)
}

}
Loading