k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/hack/update-vendor-licenses.sh (about)

     1  #!/usr/bin/env bash
     2  # Copyright 2015 The Kubernetes Authors.
     3  #
     4  # Licensed under the Apache License, Version 2.0 (the "License");
     5  # you may not use this file except in compliance with the License.
     6  # You may obtain a copy of the License at
     7  #
     8  #     http://www.apache.org/licenses/LICENSE-2.0
     9  #
    10  # Unless required by applicable law or agreed to in writing, software
    11  # distributed under the License is distributed on an "AS IS" BASIS,
    12  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  # See the License for the specific language governing permissions and
    14  # limitations under the License.
    15  
    16  # Update the LICENSES directory.
    17  # Generates a table of Go dependencies and their licenses.
    18  #
    19  # Usage:
    20  #    $0 [--create-missing] [/path/to/licenses]
    21  #
    22  #    --create-missing will write the files that only exist upstream, locally.
    23  #    This option is mostly used for testing as we cannot check-in any of the
    24  #    additionally created files into the vendor auto-generated tree.
    25  #
    26  #    Run every time a license file is added/modified within /vendor to
    27  #    update /LICENSES
    28  
    29  set -o errexit
    30  set -o nounset
    31  set -o pipefail
    32  
    33  KUBE_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
    34  source "${KUBE_ROOT}/hack/lib/init.sh"
    35  
    36  export LANG=C
    37  export LC_ALL=C
    38  
    39  ###############################################################################
    40  # Process package content
    41  #
    42  # @param package  The incoming package name
    43  # @param type     The type of content (LICENSE, COPYRIGHT or COPYING)
    44  #
    45  process_content () {
    46    local package=$1
    47    local type=$2
    48  
    49    local package_root
    50    local ensure_pattern
    51    local dir_root
    52    local find_maxdepth
    53    local find_names
    54    local -a local_files=()
    55  
    56    # Necessary to expand {}
    57    case ${type} in
    58        LICENSE) find_names=(-iname 'licen[sc]e*')
    59                 find_maxdepth=1
    60                 # Sadly inconsistent in the wild, but mostly license files
    61                 # containing copyrights, but no readme/notice files containing
    62                 # licenses (except to "see license file")
    63                 ensure_pattern="license|copyright"
    64                 ;;
    65      # We search READMEs for copyrights and this includes notice files as well
    66      # Look in as many places as we find files matching
    67      COPYRIGHT) find_names=(-iname 'notice*' -o -iname 'readme*')
    68                 find_maxdepth=3
    69                 ensure_pattern="copyright"
    70                 ;;
    71        COPYING) find_names=(-iname 'copying*')
    72                 find_maxdepth=1
    73                 ensure_pattern="license|copyright"
    74                 ;;
    75    esac
    76  
    77    # Start search at package root
    78    case ${package} in
    79      github.com/*|golang.org/*|bitbucket.org/*|gonum.org/*)
    80       package_root=$(echo "${package}" |awk -F/ '{ print $1"/"$2"/"$3 }')
    81       ;;
    82      go4.org/*)
    83       package_root=$(echo "${package}" |awk -F/ '{ print $1 }')
    84       ;;
    85      gopkg.in/*)
    86       # Root of gopkg.in package always ends with '.v(number)' and my contain
    87       # more than two path elements. For example:
    88       # - gopkg.in/yaml.v2
    89       # - gopkg.in/inf.v0
    90       # - gopkg.in/square/go-jose.v2
    91       package_root=$(echo "${package}" |grep -oh '.*\.v[0-9]')
    92       ;;
    93      */*)
    94       package_root=$(echo "${package}" |awk -F/ '{ print $1"/"$2 }')
    95       ;;
    96      *)
    97       package_root="${package}"
    98       ;;
    99    esac
   100  
   101    # Find files - only root and package level
   102    local_files=()
   103    IFS=" " read -r -a local_files <<< "$(
   104      for dir_root in ${package} ${package_root}; do
   105        [[ -d ${DEPS_DIR}/${dir_root} ]] || continue
   106  
   107        # One (set) of these is fine
   108        find "${DEPS_DIR}/${dir_root}" \
   109            -xdev -follow -maxdepth ${find_maxdepth} \
   110            -type f "${find_names[@]}"
   111      done | sort -u)"
   112  
   113    local index
   114    local f
   115    index="${package}-${type}"
   116    if [[ -z "${CONTENT[${index}]-}" ]]; then
   117      for f in "${local_files[@]-}"; do
   118        if [[ -z "$f" ]]; then
   119          # Set the default value and then check it to prevent
   120          # accessing potentially empty array
   121          continue
   122        fi
   123        # Find some copyright info in any file and break
   124        if grep -E -i -wq "${ensure_pattern}" "${f}"; then
   125          CONTENT[${index}]="${f}"
   126          break
   127        fi
   128      done
   129    fi
   130  }
   131  
   132  
   133  #############################################################################
   134  # MAIN
   135  #############################################################################
   136  
   137  # use modules, and use module info rather than the vendor dir for computing dependencies
   138  kube::golang::setup_env
   139  export GOWORK=off
   140  export GOFLAGS=-mod=mod
   141  
   142  # Check bash version
   143  if (( BASH_VERSINFO[0] < 4 )); then
   144    echo
   145    echo "ERROR: Bash v4+ required."
   146    # Extra help for OSX
   147    if [[ "$(uname -s)" == "Darwin" ]]; then
   148      echo
   149      echo "Ensure you are up to date on the following packages:"
   150      echo "$ brew install md5sha1sum bash jq"
   151    fi
   152    echo
   153    exit 9
   154  fi
   155  
   156  # This variable can be injected, as in the verify script.
   157  LICENSE_ROOT="${LICENSE_ROOT:-${KUBE_ROOT}}"
   158  cd "${LICENSE_ROOT}"
   159  
   160  kube::util::ensure-temp-dir
   161  
   162  # Save the genreated LICENSE file for each package temporarily
   163  TMP_LICENSE_FILE="${KUBE_TEMP}/LICENSES.$$"
   164  
   165  # The directory to save all the LICENSE files
   166  LICENSES_DIR="${LICENSES_DIR:-${LICENSE_ROOT}/LICENSES}"
   167  mkdir -p "${LICENSES_DIR}"
   168  
   169  # The tmp directory to save all the LICENSE files, will move to LICENSES_DIR
   170  TMP_LICENSES_DIR="${KUBE_TEMP}/LICENSES.DIR.$$"
   171  mkdir -p "${TMP_LICENSES_DIR}"
   172  
   173  DEPS_DIR="vendor"
   174  declare -Ag CONTENT
   175  
   176  # Put the K8S LICENSE on top
   177  if [ -f "${LICENSE_ROOT}/LICENSE" ]; then
   178    (
   179      echo "================================================================================"
   180      echo "= Kubernetes licensed under: ="
   181      echo
   182      cat "${LICENSE_ROOT}/LICENSE"
   183      echo
   184      echo "= LICENSE $(kube::util::md5 "${LICENSE_ROOT}/LICENSE")"
   185      echo "================================================================================"
   186    ) > "${TMP_LICENSE_FILE}"
   187    mv "${TMP_LICENSE_FILE}" "${TMP_LICENSES_DIR}/LICENSE"
   188  fi
   189  
   190  # Capture all module dependencies
   191  modules=$(go list -m -json all | jq -r .Path | sort -f)
   192  # Loop through every vendored package
   193  for PACKAGE in ${modules}; do
   194    if [[ -e "staging/src/${PACKAGE}" ]]; then
   195      echo "${PACKAGE} is a staging package, skipping" >&2
   196      continue
   197    fi
   198    if [[ ! -e "${DEPS_DIR}/${PACKAGE}" ]]; then
   199      echo "${PACKAGE} doesn't exist in ${DEPS_DIR}, skipping" >&2
   200      continue
   201    fi
   202  
   203    # if there are no files vendored under this package...
   204    if [[ -z "$(find "${DEPS_DIR}/${PACKAGE}" -mindepth 1 -maxdepth 1 -type f)" ]]; then
   205      # and we have at least the same number of submodules as subdirectories...
   206      if [[ "$(find "${DEPS_DIR}/${PACKAGE}/" -mindepth 1 -maxdepth 1 -type d | wc -l)" -le "$(echo "${modules}" | grep -cE "^${PACKAGE}/")" ]]; then
   207        echo "Only submodules of ${PACKAGE} are vendored, skipping" >&2
   208        continue
   209      fi
   210    fi
   211  
   212    echo "${PACKAGE}"
   213  
   214    process_content "${PACKAGE}" LICENSE
   215    process_content "${PACKAGE}" COPYRIGHT
   216    process_content "${PACKAGE}" COPYING
   217  
   218    # copy content and throw error message
   219    {
   220      echo "= ${DEPS_DIR}/${PACKAGE} licensed under: ="
   221      echo
   222  
   223      file=""
   224      if [[ -n "${CONTENT[${PACKAGE}-LICENSE]-}" ]]; then
   225        file="${CONTENT[${PACKAGE}-LICENSE]-}"
   226      elif [[ -n "${CONTENT[${PACKAGE}-COPYRIGHT]-}" ]]; then
   227        file="${CONTENT[${PACKAGE}-COPYRIGHT]-}"
   228      elif [[ -n "${CONTENT[${PACKAGE}-COPYING]-}" ]]; then
   229        file="${CONTENT[${PACKAGE}-COPYING]-}"
   230      fi
   231      if [[ -z "${file}" ]]; then
   232        cat >&2 << __EOF__
   233  No license could be found for ${PACKAGE} - aborting.
   234  
   235  Options:
   236  1. Check if the upstream repository has a newer version with LICENSE, COPYRIGHT and/or
   237     COPYING files.
   238  2. Contact the author of the package to ensure there is a LICENSE, COPYRIGHT and/or
   239     COPYING file present.
   240  3. Do not use this package in Kubernetes.
   241  __EOF__
   242        exit 9
   243      fi
   244  
   245      cat "${file}"
   246      echo
   247      echo "= ${file} $(kube::util::md5 "${file}")"
   248    } >> "${TMP_LICENSE_FILE}"
   249  
   250    dest_dir="${TMP_LICENSES_DIR}/vendor/${PACKAGE}"
   251    mkdir -p "${dest_dir}"
   252    mv "${TMP_LICENSE_FILE}" "${dest_dir}/LICENSE"
   253  done
   254  
   255  # copy licenses for forked code from vendor and third_party directories
   256  (cd "${KUBE_ROOT}" && \
   257    find vendor third_party -iname 'licen[sc]e*' -o -iname 'notice*' -o -iname 'copying*' | \
   258    grep -E 'third_party|forked' | \
   259    xargs tar -czf - | tar -C "${TMP_LICENSES_DIR}" -xzf -)
   260  
   261  # Leave things like OWNERS alone.
   262  rm -f "${LICENSES_DIR}/LICENSE"
   263  rm -rf "${LICENSES_DIR}/vendor"
   264  rm -rf "${LICENSES_DIR}/third_party"
   265  mv "${TMP_LICENSES_DIR}"/* "${LICENSES_DIR}"