File k3s.spec of Package k3s

#
# spec file for package k3s
#
# Copyright (c) 2025 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
# upon. The license for this file, and modifications and additions to the
# file, is the same license as for the pristine package itself (unless the
# license for the pristine package is not an Open Source License, in which
# case the license is the MIT License). An "Open Source License" is a
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.

# Please submit bugfixes or comments via https://bugs.opensuse.org/
#


%define directory_name k3s
%define binary_name k3s
%define kubernetes_version v1.33.0
%define kubernetes_version_major_minor 1.33
%define kubernetes_version_next 1.34
# check the upstream dependency file and adapt according to the 'golang: upstream version'
# https://raw.githubusercontent.com/kubernetes/kubernetes/${KUBERNETES_VERSION}/build/dependencies.yaml
# curl -sL https://raw.githubusercontent.com/kubernetes/kubernetes/${KUBERNETES_VERSION}/build/dependencies.yaml | yq e '.dependencies[] | select(.name == "golang: upstream version").version'
# example:
# result of the command 1.22.2 => golang_version go1.22 (including go prefix, without patch version)
# result of the command 1.22.2 => min_required_golang_minor_version 1.22.2
%define golang_version go1.24
%define min_required_golang_minor_version 1.24.2

# baseversion - version of kubernetes for this package
%define baseversion 1.33

Name:           k3s
Version:        1.33.0+k3s1
Release:        0
Summary:        Lightweight Kubernetes
License:        Apache-2.0
URL:            https://github.com/k3s-io/k3s
Source0:        k3s-%{version}.tar.gz
Source1:        vendor.tar.gz
Source2:        config-agent.yaml
Source3:        k3s-agent.service
Source4:        config-server.yaml
Source5:        k3s-server.service
BuildRequires:  %{golang_version} >= %{min_required_golang_minor_version}
BuildRequires:  fdupes
BuildRequires:  git
Provides:       k3s = %{version}-%{release}
Conflicts:      k3s < %{kubernetes_version_major_minor}
Conflicts:      k3s >= %{kubernetes_version_next}

# /var/lib/kubelet is also packaged in kubernetes1.XX-kubelet-common
# this in turn Requires kubernetes-kubelet-common
# by conflicting with kubernetes-kubelet-common we conflict with all
# kubernetes-version packages
Conflicts:      kubernetes-kubelet-common
Conflicts:      rke2
Conflicts:      kubectl
Conflicts:      kubernetes-client
Conflicts:      kubernetes-client-provider
Conflicts:      cri-tools
# if iptables is missing, the nginx-controller pod does not start
Requires:       iptables
Requires:       cni-plugins
Requires:       conntrack-tools
Requires:       containerd
Requires:       iptables
Requires:       runc
Requires:       %{golang_version}
Recommends:     cni-plugin-flannel

%description
k3s is a container orchestration system for automating application
deployment, scaling, and management. It is a Kubernetes-compliant
distribution that differs from the original Kubernetes (colloquially
"k8s") in that:

  * Legacy, alpha, or non-default features are removed.
  * Most in-tree plugins (cloud providers and storage plugins) were
    removed, since they can be replaced with out-of-tree addons.
  * sqlite3 is the default storage mechanism.
    etcd3 is still available, but not the default.
  * There is a new launcher that handles a lot of the complexity of
    TLS and options.

%prep
%autosetup -p 1 -a 1 -n %{directory_name}-%{version}

%define commit %(awk '/^commit/{print $2}' %{_sourcedir}/%{name}.obsinfo)

%build
# instead of hardcoding the various pieces of information,
# run the upstream script
# VERSION_GOLANG tries to download the dependencies.yaml from upstream Kubernetes
# that is being packaged, so we remove that line from the script
bash --version
sed -i '/^VERSION_GOLANG/d' ./scripts/version.sh
DRONE_COMMIT=%{commit}
source ./scripts/version.sh

# instead of getting the golang version from the kubernetes dependencies.yaml,
# we hardcode the goland version that we are using
# As long as the go major version is not different, this should be fine
VERSION_GOLANG="go$(rpm -q %{golang_version}|cut -d '-' -f 2)"
buildDate=$(date -u '+%Y-%m-%dT%H:%M:%SZ')

PKG="github.com/k3s-io/k3s"
PKG_CONTAINERD="github.com/containerd/containerd/v2"
PKG_CRICTL="sigs.k8s.io/cri-tools/pkg"
PKG_K8S_BASE="k8s.io/component-base"
PKG_K8S_CLIENT="k8s.io/client-go/pkg"
PKG_CNI_PLUGINS="github.com/containernetworking/plugins"
PKG_KUBE_ROUTER="github.com/cloudnativelabs/kube-router/v2"
PKG_CRI_DOCKERD="github.com/Mirantis/cri-dockerd"
PKG_ETCD="go.etcd.io/etcd"

go build \
   -mod=vendor \
   -buildmode=pie \
   -buildvcs=false \
   -tags="ctrd netcgo osusergo providerless urfave_cli_no_docs sqlite_omit_load_extension apparmor seccomp" \
   -ldflags=" \
     -X ${PKG}/pkg/version.Version=${VERSION} \
     -X ${PKG}/pkg/version.GitCommit=${COMMIT:0:8} \
     -X ${PKG}/pkg/version.UpstreamGolang=${VERSION_GOLANG} \
     -X ${PKG_K8S_CLIENT}/version.gitVersion=${VERSION} \
     -X ${PKG_K8S_CLIENT}/version.gitCommit=${COMMIT} \
     -X ${PKG_K8S_CLIENT}/version.gitTreeState=${TREE_STATE} \
     -X ${PKG_K8S_CLIENT}/version.buildDate=${buildDate} \
     -X ${PKG_K8S_BASE}/version.gitVersion=${VERSION} \
     -X ${PKG_K8S_BASE}/version.gitCommit=${COMMIT} \
     -X ${PKG_K8S_BASE}/version.gitTreeState=${TREE_STATE} \
     -X ${PKG_K8S_BASE}/version.buildDate=${buildDate} \
     -X ${PKG_CRICTL}/version.Version=${VERSION_CRICTL} \
     -X ${PKG_CONTAINERD}/version.Version=${VERSION_CONTAINERD} \
     -X ${PKG_CONTAINERD}/version.Package=${PKG_CONTAINERD_K3S} \
     -X ${PKG_CNI_PLUGINS}/pkg/utils/buildversion.BuildVersion=${VERSION_CNIPLUGINS} \
     -X ${PKG_CNI_PLUGINS}/plugins/meta/flannel.Program=flannel \
     -X ${PKG_CNI_PLUGINS}/plugins/meta/flannel.Version=${VERSION_FLANNEL_PLUGIN}+${VERSION_FLANNEL} \
     -X ${PKG_CNI_PLUGINS}/plugins/meta/flannel.Commit=HEAD \
     -X ${PKG_CNI_PLUGINS}/plugins/meta/flannel.buildDate=${buildDate} \
     -X ${PKG_KUBE_ROUTER}/pkg/version.Version=${VERSION_KUBE_ROUTER} \
     -X ${PKG_KUBE_ROUTER}/pkg/version.BuildDate=${buildDate} \
     -X ${PKG_CRI_DOCKERD}/cmd/version.Version=${VERSION_CRI_DOCKERD} \
     -X ${PKG_CRI_DOCKERD}/cmd/version.GitCommit=HEAD \
     -X ${PKG_CRI_DOCKERD}/cmd/version.BuildTime=${buildDate} \
     -X ${PKG_ETCD}/api/v3/version.GitSHA=HEAD \
     -w -s \
   " -o ./bin/%{binary_name} ./cmd/server

for i in ctr crictl kubectl k3s-agent k3s-server k3s-token k3s-etcd-snapshot k3s-secrets-encrypt k3s-certificate k3s-completion; do
    rm -f bin/$i${BINARY_POSTFIX}
    ln -s k3s${BINARY_POSTFIX} bin/$i${BINARY_POSTFIX}
done

cp contrib/util/check-config.sh bin/check-config

rm -rf build/data
mkdir -p build/data build/out build/static
mkdir -p dist/artifacts
mkdir -p ./etc

(
    set +x
    cd bin
    find . -not -path '*/\.*' -type f -exec sha256sum {} \; | sed -e 's| \./| |' | sort -k2 >.sha256sums
    (
        for f in $(find . -type l); do
            echo $f $(readlink $f)
        done
    ) | sed -e 's|^\./||' | sort >.links
    set -x
)

tar cvf ./build/out/data.tar ./bin ./etc
zstd --no-progress -T0 -16 -f --long=25 --rm ./build/out/data.tar -o ./build/out/data.tar.zst
HASH=$(sha256sum ./build/out/data.tar.zst | awk '{print $1}')

cp ./build/out/data.tar.zst ./build/data/${HASH}.tar.zst

GOOS=linux CC=gcc CXX=g++ go generate
LDFLAGS="
    -X github.com/k3s-io/k3s/pkg/version.Version=$VERSION
    -X github.com/k3s-io/k3s/pkg/version.GitCommit=${COMMIT:0:8}
    -w -s
"
TAGS="urfave_cli_no_docs"
STATIC="-extldflags '-static'"
CGO_ENABLED=0 go build -tags "$TAGS" -buildvcs=false -ldflags "$LDFLAGS $STATIC" -o %{binary_name} ./cmd/k3s


%install
# Install the binary.
install -D -m 0755 %{binary_name} %{buildroot}%{_bindir}/%{binary_name}

k3s_binaries=(
    "kubectl"
    "crictl"
    "ctr"
)

for i in "${k3s_binaries[@]}"; do
    ln -s "%{_bindir}/%{binary_name}" "%{buildroot}%{_bindir}/$i"
done

# systemd unit and env files
install -D -m 0644 %{SOURCE3} %{buildroot}%{_unitdir}/k3s-agent.service
install -D -m 0644 %{SOURCE2} %{buildroot}%{_sysconfdir}/rancher/%{binary_name}/config-agent.yaml
install -D -m 0644 %{SOURCE5} %{buildroot}%{_unitdir}/k3s-server.service
install -D -m 0644 %{SOURCE4} %{buildroot}%{_sysconfdir}/rancher/%{binary_name}/config-server.yaml

# configuration directory
install -d -m 0755 %{buildroot}%{_sysconfdir}/rancher/
install -d -m 0755 %{buildroot}%{_sysconfdir}/rancher/%{binary_name}/
install -d -m 0750 %{buildroot}%{_sharedstatedir}/kubelet/
install -d -m 0755 %{buildroot}%{_sharedstatedir}/rancher/
install -d -m 0755 %{buildroot}%{_sharedstatedir}/rancher/%{binary_name}/
install -d -m 0755 %{buildroot}%{_localstatedir}/log/containers/
install -d -m 0755 %{buildroot}%{_localstatedir}/log/pods/

%fdupes %{buildroot}/%{_unitdir}/

%check

%pre
%service_add_pre k3s-agent.service
%service_add_pre k3s-server.service

%post
%service_add_post k3s-agent.service
%service_add_post k3s-server.service

%preun
%service_del_preun k3s-agent.service
%service_del_preun k3s-server.service

%postun
%service_del_postun k3s-agent.service
%service_del_postun k3s-server.service

%service_del_postun k3s-server.service k3s-agent.service

%files
%doc README.md
%license LICENSE
%{_bindir}/k3s
%{_bindir}/kubectl
%{_bindir}/crictl
%{_bindir}/ctr

%{_unitdir}/k3s-agent.service
%{_unitdir}/k3s-server.service

%dir %config %{_sysconfdir}/rancher/
%dir %config %{_sysconfdir}/rancher/%{binary_name}/
%dir %{_sharedstatedir}/rancher/
%dir %{_sharedstatedir}/rancher/%{binary_name}/
%dir %{_localstatedir}/log/containers/
%dir %{_localstatedir}/log/pods/

%config %{_sysconfdir}/rancher/%{binary_name}/config-server.yaml
%config %{_sysconfdir}/rancher/%{binary_name}/config-agent.yaml

%changelog
openSUSE Build Service is sponsored by