Apt_repository Lacks PPA Parity and Unreliable

Description

Chef's apt_repository resource does not provide behavioral parity with Ubuntu's add-apt-repository command when configuring Launchpad PPAs.

When adding a PPA, apt_repository attempts to retrieve the repository signing key through the GPG/HKP keyserver path using keyserver.ubuntu.com. On a system where IPv6 routing to keyserver.ubuntu.com is broken or unavailable, the key retrieval attempts the non-functional IPv6 route and does not successfully fall back to the working IPv4 path.

In contrast, Ubuntu's add-apt-repository successfully configures the same PPAs on the same host by querying LaunchPad's HTTPS API.

As a result, using Chef's native apt_repository resource is less reliable than shelling out to add-apt-repository for this use case.

Steps to Reproduce

On an Ubuntu host where:

  • IPv6 DNS resolution for keyserver.ubuntu.com is available
  • IPv6 connectivity to keyserver.ubuntu.com is unavailable or has a dead route
  • IPv4 connectivity is functional

Verify that the PPAs can be added successfully using Ubuntu's add-apt-repository:

sudo add-apt-repository -y ppa:longsleep/golang-backports
sudo add-apt-repository -y ppa:dotnet/backports

Then attempt to configure the equivalent repositories using Chef:

apt_repository 'golang-backports' do
  uri 'ppa:longsleep/golang-backports'
  action :add
end

apt_repository 'dotnet-backports' do
  uri 'ppa:dotnet/backports'
  action :add
end

Expected Behavior

Chef's apt_repository resource should successfully configure a Launchpad PPA under the same network conditions where Ubuntu's add-apt-repository succeeds.

Ideally, PPA handling should use the current Launchpad/Ubuntu mechanism for retrieving repository signing keys rather than depending on direct HKP access to keyserver.ubuntu.com.

At minimum, failure to reach the keyserver over IPv6 should not prevent key retrieval when IPv4 connectivity is available.

Actual Behavior

apt_repository attempts to retrieve the PPA signing key through keyserver.ubuntu.com using the GPG/HKP keyserver path.

When the host has a non-functional IPv6 route to the keyserver, key retrieval fails rather than successfully using the available IPv4 path.

The equivalent:

add-apt-repository -y ppa:<owner>/<repository>

succeeds on the same system.

This means a Chef recipe must potentially bypass the native apt_repository resource and execute add-apt-repository directly to obtain the behavior already provided by the operating system.

As a workaround for the limitation with the fragile GPG/HKP path, I implemented a helper function that I can use:

def ppa_key_url(ppa)
  owner, name = ppa.delete_prefix('ppa:').split('/', 2)
  lp_uri = URI("https://launchpad.net/api/1.0/~#{owner}/+archive/ubuntu/#{name}")
  response = Net::HTTP.get_response(lp_uri)
  raise "lessons: could not resolve signing key for #{ppa} from Launchpad (HTTP #{response.code})" unless response.is_a?(Net::HTTPSuccess)

  fingerprint = JSON.parse(response.body)['signing_key_fingerprint']
  raise "lessons: Launchpad returned no signing_key_fingerprint for #{ppa}" unless fingerprint

  "https://keyserver.ubuntu.com/pks/lookup?op=get&options=mr&search=0x#{fingerprint}"
end

Later I can then

key_url = ppa_key_url('ppa:dotnet-backports')
apt_repository 'ppa:dotnet-backports' do
  uri ppa:dotnet-backports
  key key_url
  action :add
end