naughty-constraints.sh 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. #!/usr/bin/env bash
  2. set -Eeuo pipefail
  3. : "${BASHBREW_CACHE:=$HOME/.cache/bashbrew}"
  4. export BASHBREW_CACHE BASHBREW_ARCH=
  5. if [ ! -d "$BASHBREW_CACHE/git" ]; then
  6. # initialize the "bashbrew cache"
  7. bashbrew --arch amd64 from --uniq --apply-constraints hello-world:linux > /dev/null
  8. fi
  9. if [ "$#" -eq 0 ]; then
  10. set -- '--all'
  11. fi
  12. _windows_constraint() {
  13. local from="$1"; shift
  14. local repo="${from%:*}"
  15. local tag="${from#$repo:}"
  16. local constraint
  17. case "$repo" in
  18. mcr.microsoft.com/windows/nanoserver | microsoft/nanoserver) constraint='nanoserver' ;;
  19. mcr.microsoft.com/windows/servercore | microsoft/windowsservercore) constraint='windowsservercore' ;;
  20. *) echo >&2 "error: unknown Windows image: $from"; exit 1 ;;
  21. esac
  22. if [ "$tag" != 'latest' ]; then
  23. constraint+="-$tag"
  24. fi
  25. echo "$constraint"
  26. }
  27. _expected_constraints() {
  28. local from="$1"; shift
  29. local fromConstraints
  30. if fromConstraints="$(bashbrew cat --format '{{ .TagEntry.Constraints | join "\n" }}' "$from" 2>/dev/null)" && [ -n "$fromConstraints" ]; then
  31. echo "$fromConstraints"
  32. return
  33. fi
  34. case "$from" in
  35. *microsoft*) _windows_constraint "$from" ;;
  36. esac
  37. return
  38. }
  39. _arches() {
  40. bashbrew cat --format '
  41. {{- range .TagEntries -}}
  42. {{- .Architectures | join "\n" -}}
  43. {{- "\n" -}}
  44. {{- end -}}
  45. ' "$@" | sort -u
  46. }
  47. _froms() {
  48. bashbrew cat --format '
  49. {{- range .TagEntries -}}
  50. {{- $.DockerFroms . | join "\n" -}}
  51. {{- "\n" -}}
  52. {{- end -}}
  53. ' "$@" | sort -u
  54. }
  55. declare -A naughtyFromsArches=(
  56. #[img:tag=from:tag]='arch arch ...'
  57. )
  58. naughtyFroms=()
  59. declare -A allNaughty=(
  60. #[img:tag]=1
  61. )
  62. tags="$(bashbrew list --uniq "$@" | sort -u)"
  63. naughtyCount=0
  64. for img in $tags; do
  65. arches="$(_arches "$img")"
  66. constraints="$(bashbrew cat --format '{{ .TagEntry.Constraints | join "\n" }}' "$img" | sort -u)"
  67. declare -A imgMissing=()
  68. declare -A imgExtra=()
  69. for BASHBREW_ARCH in $arches; do
  70. export BASHBREW_ARCH
  71. if ! froms="$(_froms "$img" 2>/dev/null)"; then
  72. # if we can't fetch the tags from their real locations, let's try the warehouse
  73. refsList="$(
  74. bashbrew list --uniq "$img" \
  75. | sed \
  76. -e 's!:!/!' \
  77. -e "s!^!refs/tags/$BASHBREW_ARCH/!" \
  78. -e 's!$!:!'
  79. )"
  80. [ -n "$refsList" ]
  81. git -C "$BASHBREW_CACHE/git" \
  82. fetch --no-tags --quiet \
  83. https://github.com/docker-library/commit-warehouse.git \
  84. $refsList
  85. froms="$(_froms "$img")"
  86. fi
  87. [ -n "$froms" ] # rough sanity check
  88. for from in $froms; do
  89. expected="$(_expected_constraints "$from" | sort -u)"
  90. missing="$(comm -13 <(echo "$constraints") <(echo "$expected"))"
  91. if [ -n "$missing" ]; then
  92. imgMissing[$from]+=$'\n'"$missing"
  93. fi
  94. extra="$(comm -23 <(echo "$constraints") <(echo "$expected"))"
  95. if [ "$from" = 'scratch' ]; then
  96. # if a given image is "FROM scratch", then consider "!aufs" an acceptable constraint that doesn't show
  97. extra="$(grep -vE '^!aufs$' <<<"$extra" || :)"
  98. fi
  99. if [ -n "$extra" ]; then
  100. imgExtra[$from]+=$'\n'"$extra"
  101. fi
  102. done
  103. done
  104. if [ "${#imgMissing[@]}" -gt 0 ]; then
  105. for from in $(IFS=$'\n'; sort -u <<<"${!imgMissing[*]}"); do
  106. missing="${imgMissing[$from]}"
  107. missing="$(sed '/^$/d' <<<"$missing" | sort -u)"
  108. echo " - $img -- missing constraints (FROM $from):"
  109. sed 's/^/ - /' <<<"$missing"
  110. (( naughtyCount++ )) || :
  111. done
  112. fi
  113. if [ "${#imgExtra[@]}" -gt 0 ]; then
  114. for from in $(IFS=$'\n'; sort -u <<<"${!imgExtra[*]}"); do
  115. extra="${imgExtra[$from]}"
  116. extra="$(sed '/^$/d' <<<"$extra" | sort -u)"
  117. echo " - $img -- extra constraints (FROM $from):"
  118. sed 's/^/ - /' <<<"$extra"
  119. (( naughtyCount++ )) || :
  120. done
  121. fi
  122. done
  123. exit "$naughtyCount"