diff --git a/.gitignore b/.gitignore index 210f4188..47405867 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ old/ tmp/ *_stringer.go mgmt +rpmbuild/ diff --git a/Makefile b/Makefile index 62f99a05..4ea3e5d2 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,41 @@ +# Mgmt +# Copyright (C) 2013-2016+ James Shubin and the project contributors +# Written by James Shubin and the project contributors +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + SHELL = /bin/bash -.PHONY: all version path deps run race build clean test format docs +.PHONY: all version program path deps run race build clean test format docs rpmbuild rpm srpm spec tar upload upload-sources upload-srpms upload-rpms copr .SILENT: clean -VERSION := $(shell git describe --match '[0-9]*\.[0-9]*\.[0-9]*' --tags --dirty --always) -PROGRAM := $(notdir $(CURDIR)) +SVERSION := $(shell git describe --match '[0-9]*\.[0-9]*\.[0-9]*' --tags --dirty --always) +VERSION := $(shell git describe --match '[0-9]*\.[0-9]*\.[0-9]*' --tags --abbrev=0) +PROGRAM := $(shell basename --suffix=-$(VERSION) $(notdir $(CURDIR))) +ifeq ($(VERSION),$(SVERSION)) + RELEASE = 1 +else + RELEASE = untagged +endif +ARCH = $(shell arch) +SPEC = rpmbuild/SPECS/mgmt.spec +SOURCE = rpmbuild/SOURCES/mgmt-$(VERSION).tar.bz2 +SRPM = rpmbuild/SRPMS/mgmt-$(VERSION)-$(RELEASE).src.rpm +SRPM_BASE = mgmt-$(VERSION)-$(RELEASE).src.rpm +RPM = rpmbuild/RPMS/mgmt-$(VERSION)-$(RELEASE).$(ARCH).rpm +USERNAME := $(shell cat ~/.config/copr 2>/dev/null | grep username | awk -F '=' '{print $$2}' | tr -d ' ') +SERVER = 'dl.fedoraproject.org' +REMOTE_PATH = 'pub/alt/$(USERNAME)/mgmt' all: docs @@ -11,6 +43,9 @@ all: docs version: @echo $(VERSION) +program: + @echo $(PROGRAM) + path: ./misc/make-path.sh @@ -18,22 +53,22 @@ deps: ./misc/make-deps.sh run: - find -maxdepth 1 -type f -name '*.go' -not -name '*_test.go' | xargs go run -ldflags "-X main.version=$(VERSION) -X main.program=$(PROGRAM)" + find -maxdepth 1 -type f -name '*.go' -not -name '*_test.go' | xargs go run -ldflags "-X main.program=$(PROGRAM) -X main.version=$(SVERSION)" # include race flag race: - find -maxdepth 1 -type f -name '*.go' -not -name '*_test.go' | xargs go run -race -ldflags "-X main.version=$(VERSION) -X main.program=$(PROGRAM)" + find -maxdepth 1 -type f -name '*.go' -not -name '*_test.go' | xargs go run -race -ldflags "-X main.program=$(PROGRAM) -X main.version=$(SVERSION)" build: mgmt mgmt: main.go - @echo "Building: $(PROGRAM), version: $(VERSION)." + @echo "Building: $(PROGRAM), version: $(SVERSION)." go generate # avoid equals sign in old golang versions eg in: -X foo=bar if go version | grep -qE 'go1.3|go1.4'; then \ - go build -ldflags "-X main.version $(VERSION) -X main.program $(PROGRAM)"; \ + go build -ldflags "-X main.program $(PROGRAM) -X main.version $(SVERSION)" -o mgmt; \ else \ - go build -ldflags "-X main.version=$(VERSION) -X main.program=$(PROGRAM)"; \ + go build -ldflags "-X main.program=$(PROGRAM) -X main.version=$(SVERSION)" -o mgmt; \ fi clean: @@ -51,3 +86,136 @@ docs: mgmt-documentation.pdf mgmt-documentation.pdf: DOCUMENTATION.md pandoc DOCUMENTATION.md -o 'mgmt-documentation.pdf' + +# +# build aliases +# +# TODO: does making an rpm depend on making a .srpm first ? +rpm: $(SRPM) $(RPM) + # do nothing + +srpm: $(SRPM) + # do nothing + +spec: $(SPEC) + # do nothing + +tar: $(SOURCE) + # do nothing + +rpmbuild/SOURCES/: tar +rpmbuild/SRPMS/: srpm +rpmbuild/RPMS/: rpm + +upload: upload-sources upload-srpms upload-rpms + # do nothing + +# +# rpmbuild +# +$(RPM): $(SPEC) $(SOURCE) + @echo Running rpmbuild -bb... + rpmbuild --define '_topdir $(shell pwd)/rpmbuild' -bb $(SPEC) && \ + mv rpmbuild/RPMS/$(ARCH)/mgmt-$(VERSION)-$(RELEASE).*.rpm $(RPM) + +$(SRPM): $(SPEC) $(SOURCE) + @echo Running rpmbuild -bs... + rpmbuild --define '_topdir $(shell pwd)/rpmbuild' -bs $(SPEC) + # renaming is not needed because we aren't using the dist variable + #mv rpmbuild/SRPMS/mgmt-$(VERSION)-$(RELEASE).*.src.rpm $(SRPM) + +# +# spec +# +$(SPEC): rpmbuild/ mgmt.spec.in + @echo Running templater... + #cat mgmt.spec.in > $(SPEC) + sed -e s/__VERSION__/$(VERSION)/ -e s/__RELEASE__/$(RELEASE)/ < mgmt.spec.in > $(SPEC) + # append a changelog to the .spec file + git log --format="* %cd %aN <%aE>%n- (%h) %s%d%n" --date=local | sed -r 's/[0-9]+:[0-9]+:[0-9]+ //' >> $(SPEC) + +# +# archive +# +$(SOURCE): rpmbuild/ + @echo Running git archive... + # use HEAD if tag doesn't exist yet, so that development is easier... + git archive --prefix=mgmt-$(VERSION)/ -o $(SOURCE) $(VERSION) 2> /dev/null || (echo 'Warning: $(VERSION) does not exist. Using HEAD instead.' && git archive --prefix=mgmt-$(VERSION)/ -o $(SOURCE) HEAD) + # TODO: if git archive had a --submodules flag this would easier! + @echo Running git archive submodules... + # i thought i would need --ignore-zeros, but it doesn't seem necessary! + p=`pwd` && (echo .; git submodule foreach) | while read entering path; do \ + temp="$${path%\'}"; \ + temp="$${temp#\'}"; \ + path=$$temp; \ + [ "$$path" = "" ] && continue; \ + (cd $$path && git archive --prefix=mgmt-$(VERSION)/$$path/ HEAD > $$p/rpmbuild/tmp.tar && tar --concatenate --file=$$p/$(SOURCE) $$p/rpmbuild/tmp.tar && rm $$p/rpmbuild/tmp.tar); \ + done + +# TODO: ensure that each sub directory exists +rpmbuild/: + mkdir -p rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS} + +rpmbuild: + mkdir -p rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS} + +# +# sha256sum +# +rpmbuild/SOURCES/SHA256SUMS: rpmbuild/SOURCES/ $(SOURCE) + @echo Running SOURCES sha256sum... + cd rpmbuild/SOURCES/ && sha256sum *.tar.bz2 > SHA256SUMS; cd - + +rpmbuild/SRPMS/SHA256SUMS: rpmbuild/SRPMS/ $(SRPM) + @echo Running SRPMS sha256sum... + cd rpmbuild/SRPMS/ && sha256sum *src.rpm > SHA256SUMS; cd - + +rpmbuild/RPMS/SHA256SUMS: rpmbuild/RPMS/ $(RPM) + @echo Running RPMS sha256sum... + cd rpmbuild/RPMS/ && sha256sum *.rpm > SHA256SUMS; cd - + +# +# gpg +# +rpmbuild/SOURCES/SHA256SUMS.asc: rpmbuild/SOURCES/SHA256SUMS + @echo Running SOURCES gpg... + # the --yes forces an overwrite of the SHA256SUMS.asc if necessary + gpg2 --yes --clearsign rpmbuild/SOURCES/SHA256SUMS + +rpmbuild/SRPMS/SHA256SUMS.asc: rpmbuild/SRPMS/SHA256SUMS + @echo Running SRPMS gpg... + gpg2 --yes --clearsign rpmbuild/SRPMS/SHA256SUMS + +rpmbuild/RPMS/SHA256SUMS.asc: rpmbuild/RPMS/SHA256SUMS + @echo Running RPMS gpg... + gpg2 --yes --clearsign rpmbuild/RPMS/SHA256SUMS + +# +# upload +# +# upload to public server +upload-sources: rpmbuild/SOURCES/ rpmbuild/SOURCES/SHA256SUMS rpmbuild/SOURCES/SHA256SUMS.asc + if [ "`cat rpmbuild/SOURCES/SHA256SUMS`" != "`ssh $(SERVER) 'cd $(REMOTE_PATH)/SOURCES/ && cat SHA256SUMS'`" ]; then \ + echo Running SOURCES upload...; \ + rsync -avz rpmbuild/SOURCES/ $(SERVER):$(REMOTE_PATH)/SOURCES/; \ + fi + +upload-srpms: rpmbuild/SRPMS/ rpmbuild/SRPMS/SHA256SUMS rpmbuild/SRPMS/SHA256SUMS.asc + if [ "`cat rpmbuild/SRPMS/SHA256SUMS`" != "`ssh $(SERVER) 'cd $(REMOTE_PATH)/SRPMS/ && cat SHA256SUMS'`" ]; then \ + echo Running SRPMS upload...; \ + rsync -avz rpmbuild/SRPMS/ $(SERVER):$(REMOTE_PATH)/SRPMS/; \ + fi + +upload-rpms: rpmbuild/RPMS/ rpmbuild/RPMS/SHA256SUMS rpmbuild/RPMS/SHA256SUMS.asc + if [ "`cat rpmbuild/RPMS/SHA256SUMS`" != "`ssh $(SERVER) 'cd $(REMOTE_PATH)/RPMS/ && cat SHA256SUMS'`" ]; then \ + echo Running RPMS upload...; \ + rsync -avz --prune-empty-dirs rpmbuild/RPMS/ $(SERVER):$(REMOTE_PATH)/RPMS/; \ + fi + +# +# copr build +# +copr: upload-srpms + ./misc/copr-build.py https://$(SERVER)/$(REMOTE_PATH)/SRPMS/$(SRPM_BASE) + +# vim: ts=8 diff --git a/main.go b/main.go index 92d49fcc..9163d044 100644 --- a/main.go +++ b/main.go @@ -30,8 +30,8 @@ import ( // set at compile time var ( - version string program string + version string ) const ( diff --git a/mgmt.spec.in b/mgmt.spec.in new file mode 100644 index 00000000..aa476212 --- /dev/null +++ b/mgmt.spec.in @@ -0,0 +1,61 @@ +%global project_version __VERSION__ +%define debug_package %{nil} + +Name: mgmt +Version: __VERSION__ +Release: __RELEASE__ +Summary: A next generation config management prototype! +License: AGPLv3+ +URL: https://github.com/purpleidea/mgmt +Source0: https://dl.fedoraproject.org/pub/alt/purpleidea/mgmt/SOURCES/mgmt-%{project_version}.tar.bz2 + +# graphviz should really be a "suggests", since technically it's optional +Requires: graphviz + +BuildRequires: golang +BuildRequires: golang-googlecode-tools-stringer + +%description +A next generation config management prototype! + +%prep +%setup + +%build +# FIXME: in the future, these could be vendor-ed in +mkdir -p vendor/ +export GOPATH=`pwd`/vendor/ +go get github.com/coreos/etcd/client +go get gopkg.in/yaml.v2 +go get gopkg.in/fsnotify.v1 +go get github.com/codegangsta/cli +go get github.com/coreos/go-systemd/dbus +go get github.com/coreos/go-systemd/util +make build + +%install +rm -rf %{buildroot} +# _datadir is typically /usr/share/ +install -d -m 0755 %{buildroot}/%{_datadir}/mgmt/ +cp -a AUTHORS COPYING COPYRIGHT DOCUMENTATION.md README.md THANKS examples/ %{buildroot}/%{_datadir}/mgmt/ + +# install the binary +mkdir -p %{buildroot}/%{_bindir} +install -m 0755 mgmt %{buildroot}/%{_bindir}/mgmt + +# profile.d bash completion +mkdir -p %{buildroot}%{_sysconfdir}/profile.d +install misc/mgmt.bashrc -m 0755 %{buildroot}%{_sysconfdir}/profile.d/mgmt.sh + +# etc dir +mkdir -p %{buildroot}%{_sysconfdir}/mgmt/ +install -m 0644 misc/mgmt.conf.example %{buildroot}%{_sysconfdir}/mgmt/mgmt.conf + +%files +%attr(0755, root, root) %{_sysconfdir}/profile.d/mgmt.sh +%{_datadir}/mgmt/* +%{_bindir}/mgmt +%{_sysconfdir}/mgmt/* + +# this changelog is auto-generated by git log +%changelog diff --git a/misc/copr-build.py b/misc/copr-build.py new file mode 100755 index 00000000..c977e285 --- /dev/null +++ b/misc/copr-build.py @@ -0,0 +1,66 @@ +#!/usr/bin/python + +# README: +# for initial setup, browse to: https://copr.fedoraproject.org/api/ +# and it will have a ~/.config/copr config that you can download. +# happy hacking! + +import os +import sys +import copr +import time + +COPR = 'mgmt' + +if len(sys.argv) != 2: + print("Usage: %s " % sys.argv[0]) + sys.exit(1) + +url = sys.argv[1] + +client = copr.CoprClient.create_from_file_config(os.path.expanduser("~/.config/copr")) + +result = client.create_new_build(COPR, [url]) +if result.output != 'ok': + print(result.error) + sys.exit(1) +print(result.message) + +# modified from: https://python-copr.readthedocs.org/en/latest/Examples.html#work-with-builds +for bw in result.builds_list: + print("Build #{}: {}".format(bw.build_id, bw.handle.get_build_details().status)) + +# cancel all created build +#for bw in result.builds_list: +# bw.handle.cancel_build() + +# get build status for each chroot +#for bw in result.builds_list: +# print("build: {}".format(bw.build_id)) +# for ch, status in bw.handle.get_build_details().data["chroots"].items(): +# print("\t chroot {}:\t {}".format(ch, status)) + +# simple build progress: + +watched = set(result.builds_list) +done = set() +state = {} +for bw in watched: # store initial states + state[bw.build_id] = bw.handle.get_build_details().status + +while watched != done: + for bw in watched: + if bw in done: + continue + status = bw.handle.get_build_details().status + if status != state.get(bw.build_id): + print("Build #{}: {}".format(bw.build_id, status)) + state[bw.build_id] = status # update status + + if status in ['skipped', 'failed', 'succeeded']: + done.add(bw) + + if watched == done: break # avoid long while sleep + else: time.sleep(10) + +print 'Done!' diff --git a/misc/mgmt.bashrc b/misc/mgmt.bashrc new file mode 100755 index 00000000..5f96c07c --- /dev/null +++ b/misc/mgmt.bashrc @@ -0,0 +1,13 @@ +#!/bin/bash + +_cli_bash_autocomplete_mgmt() { + local cur prev opts base + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} --generate-bash-completion ) + COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) + return 0 +} + +complete -F _cli_bash_autocomplete_mgmt mgmt diff --git a/misc/mgmt.conf.example b/misc/mgmt.conf.example new file mode 100644 index 00000000..e5a1857e --- /dev/null +++ b/misc/mgmt.conf.example @@ -0,0 +1 @@ +# example mgmt configuration file, currently has not options at the moment!